Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / rx / DARWIN / rx_kmutex.h
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 /*
11 * rx_kmutex.h - mutex and condition variable macros for kernel environment.
12 *
13 * MACOS implementation.
14 */
15
16 #ifndef _RX_KMUTEX_H_
17 #define _RX_KMUTEX_H_
18
19 #ifdef AFS_DARWIN80_ENV
20 #include <kern/locks.h>
21 /* kernel private from osfmk/kern/locks.h ... sigh */
22 extern boolean_t lck_mtx_try_lock(lck_mtx_t *lck);
23 extern boolean_t lck_rw_try_lock(lck_rw_t *lck, lck_rw_type_t lck_rw_type);
24 #else
25 #include <sys/lock.h>
26 #endif
27 #include <kern/thread.h>
28 #include <sys/vm.h>
29
30 #define RX_ENABLE_LOCKS 1
31
32 /*
33 * Condition variables
34 *
35 * In Digital Unix (OSF/1), we use something akin to the ancient sleep/wakeup
36 * mechanism. The condition variable itself plays no role; we just use its
37 * address as a convenient unique number.
38 *
39 * XXX in darwin, both mach and bsd facilities are available. Should really
40 * stick to one or the other (but mach locks don't have a _try.....)
41 *
42 * in darwin 8.0, the bsd lock facility is no longer available, and only one
43 * sleep variant is available. Still no lock_try, but we can work around that.
44 * We can't pass the mutex into msleep, even if we didn't need the two mutex
45 * hack for lock_try emulation, since msleep won't fixup the owner variable
46 * and we'll panic.
47 */
48 #define CV_INIT(cv,a,b,c)
49 #define CV_DESTROY(cv)
50 #ifdef AFS_DARWIN80_ENV
51 #define CV_WAIT(cv, lck) do { \
52 int isGlockOwner = ISAFS_GLOCK(); \
53 if (isGlockOwner) AFS_GUNLOCK(); \
54 osi_Assert((lck)->owner == current_thread()); \
55 (lck)->owner = (thread_t)0; \
56 lck_mtx_lock((lck)->meta); \
57 (lck)->waiters--; \
58 lck_mtx_unlock((lck)->meta); \
59 msleep(cv, (lck)->lock, PDROP|PVFS, "afs_CV_WAIT", NULL); \
60 if (isGlockOwner) AFS_GLOCK(); \
61 MUTEX_ENTER(lck); \
62 } while(0)
63
64 #define CV_TIMEDWAIT(cv,lck,t) do { \
65 struct timespec ts; \
66 int isGlockOwner = ISAFS_GLOCK(); \
67 ts.ts_sec = t; \
68 ts.ts_nsec = 0; \
69 if (isGlockOwner) AFS_GUNLOCK(); \
70 osi_Assert((lck)->owner == current_thread()); \
71 (lck)->owner = (thread_t)0; \
72 lck_mtx_lock((lck)->meta); \
73 (lck)->waiters--; \
74 lck_mtx_unlock((lck)->meta); \
75 msleep(cv, (lck)->lock, PDROP|PVFS, "afs_CV_TIMEDWAIT", &ts); \
76 if (isGlockOwner) AFS_GLOCK(); \
77 MUTEX_ENTER(lck); \
78 } while(0)
79 #else
80 #define CV_WAIT(cv, lck) do { \
81 int isGlockOwner = ISAFS_GLOCK(); \
82 if (isGlockOwner) AFS_GUNLOCK(); \
83 MUTEX_EXIT(lck); \
84 sleep(cv, PVFS); \
85 if (isGlockOwner) AFS_GLOCK(); \
86 MUTEX_ENTER(lck); \
87 } while(0)
88
89 #define CV_TIMEDWAIT(cv,lck,t) do { \
90 int isGlockOwner = ISAFS_GLOCK(); \
91 if (isGlockOwner) AFS_GUNLOCK(); \
92 MUTEX_EXIT(lck); \
93 tsleep(cv,PVFS, "afs_CV_TIMEDWAIT",t); \
94 if (isGlockOwner) AFS_GLOCK(); \
95 MUTEX_ENTER(lck); \
96 } while(0)
97 #endif
98 #define CV_SIGNAL(cv) wakeup_one((void *)(cv))
99 #define CV_BROADCAST(cv) wakeup((void *)(cv))
100
101 #ifdef AFS_DARWIN80_ENV
102 typedef struct {
103 lck_mtx_t *meta;
104 int waiters; /* also includes anyone holding the lock */
105 lck_mtx_t *lock;
106 thread_t owner;
107 } afs_kmutex_t;
108 typedef int afs_kcondvar_t;
109
110 extern lck_grp_t * openafs_lck_grp;
111
112 #define MUTEX_SETUP() rx_kmutex_setup()
113 #define MUTEX_FINISH() rx_kmutex_finish()
114 #define LOCKINIT(a) \
115 do { \
116 lck_attr_t *openafs_lck_attr = lck_attr_alloc_init(); \
117 (a) = lck_mtx_alloc_init(openafs_lck_grp, openafs_lck_attr); \
118 lck_attr_free(openafs_lck_attr); \
119 } while(0)
120 #define MUTEX_INIT(a,b,c,d) \
121 do { \
122 lck_attr_t *openafs_lck_attr = lck_attr_alloc_init(); \
123 (a)->meta = lck_mtx_alloc_init(openafs_lck_grp, openafs_lck_attr); \
124 (a)->lock = lck_mtx_alloc_init(openafs_lck_grp, openafs_lck_attr); \
125 lck_attr_free(openafs_lck_attr); \
126 (a)->waiters = 0; \
127 (a)->owner = (thread_t)0; \
128 } while(0)
129 #define MUTEX_DESTROY(a) \
130 do { \
131 lck_mtx_destroy((a)->lock, openafs_lck_grp); \
132 lck_mtx_destroy((a)->meta, openafs_lck_grp); \
133 (a)->owner = (thread_t)-1; \
134 } while(0)
135 #define MUTEX_ENTER(a) \
136 do { \
137 lck_mtx_lock((a)->meta); \
138 (a)->waiters++; \
139 lck_mtx_unlock((a)->meta); \
140 lck_mtx_lock((a)->lock); \
141 osi_Assert((a)->owner == (thread_t)0); \
142 (a)->owner = current_thread(); \
143 } while(0)
144
145 /* acquire main lock before releasing meta lock, so we don't race */
146 #define MUTEX_TRYENTER(a) ({ \
147 int _ret; \
148 lck_mtx_lock((a)->meta); \
149 if ((a)->waiters) { \
150 lck_mtx_unlock((a)->meta); \
151 _ret = 0; \
152 } else { \
153 (a)->waiters++; \
154 lck_mtx_lock((a)->lock); \
155 lck_mtx_unlock((a)->meta); \
156 osi_Assert((a)->owner == (thread_t)0); \
157 (a)->owner = current_thread(); \
158 _ret = 1; \
159 } \
160 _ret; \
161 })
162
163 #define MUTEX_EXIT(a) \
164 do { \
165 osi_Assert((a)->owner == current_thread()); \
166 (a)->owner = (thread_t)0; \
167 lck_mtx_unlock((a)->lock); \
168 lck_mtx_lock((a)->meta); \
169 (a)->waiters--; \
170 lck_mtx_unlock((a)->meta); \
171 } while(0)
172
173 #define MUTEX_ASSERT(a) osi_Assert(((afs_kmutex_t *)(a))->owner == current_thread())
174 #else
175 typedef struct {
176 struct lock__bsd__ lock;
177 thread_t owner;
178 } afs_kmutex_t;
179 typedef int afs_kcondvar_t;
180
181 #define LOCK_INIT(a,b) \
182 do { \
183 lockinit(&(a)->lock,PSOCK, "afs rx lock", 0, 0); \
184 (a)->owner = (thread_t)0; \
185 } while(0);
186 #define MUTEX_INIT(a,b,c,d) \
187 do { \
188 lockinit(&(a)->lock,PSOCK, "afs rx mutex", 0, 0); \
189 (a)->owner = (thread_t)0; \
190 } while(0);
191 #define MUTEX_DESTROY(a) \
192 do { \
193 (a)->owner = (thread_t)-1; \
194 } while(0);
195 #define MUTEX_ENTER(a) \
196 do { \
197 lockmgr(&(a)->lock, LK_EXCLUSIVE, 0, current_proc()); \
198 osi_Assert((a)->owner == (thread_t)0); \
199 (a)->owner = current_thread(); \
200 } while(0);
201 #define MUTEX_TRYENTER(a) \
202 ( lockmgr(&(a)->lock, LK_EXCLUSIVE|LK_NOWAIT, 0, current_proc()) ? 0 : ((a)->owner = current_thread(), 1) )
203 #define MUTEX_EXIT(a) \
204 do { \
205 osi_Assert((a)->owner == current_thread()); \
206 (a)->owner = (thread_t)0; \
207 lockmgr(&(a)->lock, LK_RELEASE, 0, current_proc()); \
208 } while(0);
209
210 #define MUTEX_ASSERT(a) osi_Assert(((afs_kmutex_t *)(a))->owner == current_thread())
211 #endif
212
213 #endif /* _RX_KMUTEX_H_ */