|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
25: *
26: * NXConditionLock.m. Lock object with exported condition variable,
27: * kernel version.
28: *
29: * HISTORY
30: * 01-Aug-91 Doug Mitchell at NeXT
31: * Created.
32: */
33:
34: #define KERNEL 1
35: #define KERNEL_PRIVATE 1
36: #define ARCH_PRIVATE 1
37: #undef MACH_USER_API
38:
39: #import <machkit/NXLock.h>
40: #import <kern/sched_prim.h>
41: #import <kernserv/lock.h>
42:
43: /*
44: * _priv instance variable points to one of these.
45: */
46: struct _priv {
47: simple_lock_t spin_lock;
48: lock_t sleep_lock;
49: int conditionVar;
50: };
51:
52: @implementation NXConditionLock
53:
54: - init
55: {
56: return [self initWith:0];
57: }
58:
59: - initWith : (int)condition
60: {
61: struct _priv *p = _priv;
62:
63: [super init];
64:
65: if (p == 0) {
66: p = (struct _priv *)kalloc(sizeof (struct _priv));
67: p->spin_lock = simple_lock_alloc();
68: p->sleep_lock = lock_alloc();
69:
70: _priv = p;
71: }
72:
73: simple_lock_init(p->spin_lock);
74: lock_init(p->sleep_lock, TRUE);
75: p->conditionVar = condition;
76:
77: return self;
78: }
79:
80: - (int) condition
81: {
82: struct _priv *p = _priv;
83:
84: return (p->conditionVar);
85: }
86:
87: - free
88: {
89: struct _priv *p = _priv;
90:
91: if (p) {
92: lock_free(p->sleep_lock);
93: simple_lock_free(p->spin_lock);
94: kfree(p, sizeof (struct _priv));
95: }
96:
97: return [super free];
98: }
99:
100: - lock
101: {
102: struct _priv *p = _priv;
103:
104: lock_write(p->sleep_lock);
105:
106: return self;
107: }
108:
109: - unlock
110: {
111: struct _priv *p = _priv;
112:
113: thread_wakeup_one(&p->conditionVar);
114: lock_done(p->sleep_lock);
115:
116: return self;
117: }
118:
119: - lockWhen : (int)condition
120: {
121: struct _priv *p = _priv;
122:
123: /*
124: * First acquire ownership of the entire object.
125: */
126: lock_write(p->sleep_lock);
127: while (condition != p->conditionVar) {
128:
129: /*
130: * Need to hold a simple_lock when we call thread_sleep().
131: * Both _spin_lock and sleep_lock must be held to
132: * change _conditionVar.
133: */
134: simple_lock(p->spin_lock);
135: lock_done(p->sleep_lock);
136:
137: /*
138: * this is the critical section on a multi in which
139: * another thread could hold _sleep_lock, but they
140: * can't change _conditionVar. Holding _spin_lock here
141: * (until after assert_wait() is called from
142: * thread_sleep()) ensures that we'll be notified
143: * of changes in _conditionVar.
144: */
145: thread_sleep((void *)&p->conditionVar, p->spin_lock, FALSE);
146: lock_write(p->sleep_lock);
147: }
148:
149: return self;
150: }
151:
152: - unlockWith : (int)condition
153: {
154: struct _priv *p = _priv;
155:
156: /*
157: * _sleep_lock held, but not _spin_lock.
158: */
159: simple_lock(p->spin_lock);
160: p->conditionVar = condition;
161: simple_unlock(p->spin_lock);
162: thread_wakeup_one(&p->conditionVar);
163: lock_done(p->sleep_lock);
164:
165: return self;
166: }
167:
168: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.