macos-rollup-20051013
[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 #else
22 #include <sys/lock.h>
23 #endif
24 #include <kern/thread.h>
25 #include <sys/vm.h>
26
27 #define RX_ENABLE_LOCKS         1
28 #define AFS_GLOBAL_RXLOCK_KERNEL
29
30 /*
31  * Condition variables
32  *
33  * In Digital Unix (OSF/1), we use something akin to the ancient sleep/wakeup
34  * mechanism.  The condition variable itself plays no role; we just use its
35  * address as a convenient unique number.
36  * 
37  * XXX in darwin, both mach and bsd facilities are available. Should really
38  * stick to one or the other (but mach locks don't have a _try.....)
39  *
40  * in darwin 8.0, the bsd lock facility is no longer available, and only one
41  * sleep variant is available. Still no lock_try, but we can work around that.
42  * We can't pass the mutex into msleep, even if we didn't need the two mutex 
43  * hack for lock_try emulation, since msleep won't fixup the owner variable
44  * and we'll panic.
45  */
46 #define CV_INIT(cv,a,b,c)
47 #define CV_DESTROY(cv)
48 #ifdef AFS_DARWIN14_ENV
49 #ifdef AFS_DARWIN80_ENV
50 #define VFSSLEEP(cv) msleep(cv, NULL, PVFS, "afs_CV_WAIT", NULL)
51 #define VFSTSLEEP(cv,t) do { \
52    struct timespec ts; \
53    ts.ts_sec = t; \
54    ts.ts_nsec = 0; \
55    msleep(cv, NULL, PVFS, "afs_CV_TIMEDWAIT", &ts); \
56 } while(0)
57 #else
58 #define VFSSLEEP(cv) sleep(cv, PVFS)
59 #define VFSTSLEEP(cv, t) tsleep(cv,PVFS, "afs_CV_TIMEDWAIT",t)
60 #endif
61 #define CV_WAIT(cv, lck)    do { \
62                                 int isGlockOwner = ISAFS_GLOCK(); \
63                                 if (isGlockOwner) AFS_GUNLOCK();  \
64                                 MUTEX_EXIT(lck);        \
65                                 VFSSLEEP(cv);                \
66                                 if (isGlockOwner) AFS_GLOCK();  \
67                                 MUTEX_ENTER(lck); \
68                             } while(0)
69
70 #define CV_TIMEDWAIT(cv,lck,t)  do { \
71                                 int isGlockOwner = ISAFS_GLOCK(); \
72                                 if (isGlockOwner) AFS_GUNLOCK();  \
73                                 MUTEX_EXIT(lck);        \
74                                 VFSTSLEEP(cv,t);  \
75                                 if (isGlockOwner) AFS_GLOCK();  \
76                                 MUTEX_ENTER(lck);       \
77                             } while(0)
78
79 #define CV_SIGNAL(cv)           wakeup_one((void *)(cv))
80 #define CV_BROADCAST(cv)        wakeup((void *)(cv))
81 #else
82 #define CV_WAIT(cv, lck)    { \
83                                 int isGlockOwner = ISAFS_GLOCK(); \
84                                 if (isGlockOwner) AFS_GUNLOCK();  \
85                                 assert_wait((event_t)(cv), 0);  \
86                                 MUTEX_EXIT(lck);        \
87                                 thread_block(0);                \
88                                 if (isGlockOwner) AFS_GLOCK();  \
89                                 MUTEX_ENTER(lck); \
90                             }
91
92 #define CV_TIMEDWAIT(cv,lck,t)  { \
93                                 int isGlockOwner = ISAFS_GLOCK(); \
94                                 if (isGlockOwner) AFS_GUNLOCK();  \
95                                 assert_wait((event_t)(cv), 0);  \
96                                 thread_set_timer(t, NSEC_PER_SEC/hz);   \
97                                 MUTEX_EXIT(lck);        \
98                                 thread_block(0);                \
99                                 if (isGlockOwner) AFS_GLOCK();  \
100                                 MUTEX_ENTER(lck);       \
101                                 }
102
103 #define CV_SIGNAL(cv)           thread_wakeup_one((event_t)(cv))
104 #define CV_BROADCAST(cv)        thread_wakeup((event_t)(cv))
105 #endif
106
107 #ifdef AFS_DARWIN80_ENV
108 typedef struct {
109     lck_mtx_t *meta;
110     int waiters; /* also includes anyone holding the lock */
111     lck_mtx_t *lock;
112     thread_t owner;
113 } afs_kmutex_t;
114 typedef int afs_kcondvar_t;
115
116 extern lck_grp_t * openafs_lck_grp;
117
118 #define MUTEX_SETUP() rx_kmutex_setup()
119 #define MUTEX_FINISH() rx_kmutex_finish()
120 #define LOCKINIT(a) \
121     do { \
122         lck_attr_t *openafs_lck_attr = lck_attr_alloc_init(); \
123         (a) = lck_mtx_alloc_init(openafs_lck_grp, openafs_lck_attr); \
124         lck_attr_free(openafs_lck_attr); \
125     } while(0)
126 #define MUTEX_INIT(a,b,c,d) \
127     do { \
128         lck_attr_t *openafs_lck_attr = lck_attr_alloc_init(); \
129         (a)->meta = lck_mtx_alloc_init(openafs_lck_grp, openafs_lck_attr); \
130         (a)->lock = lck_mtx_alloc_init(openafs_lck_grp, openafs_lck_attr); \
131         lck_attr_free(openafs_lck_attr); \
132         (a)->waiters = 0; \
133         (a)->owner = (thread_t)0; \
134     } while(0)
135 #define MUTEX_DESTROY(a) \
136     do { \
137         lck_mtx_destroy((a)->lock, openafs_lck_grp); \
138         lck_mtx_destroy((a)->meta, openafs_lck_grp); \
139         (a)->owner = (thread_t)-1; \
140     } while(0)
141 #define MUTEX_ENTER(a) \
142     do { \
143         lck_mtx_lock((a)->meta); \
144         (a)->waiters++; \
145         lck_mtx_unlock((a)->meta); \
146         lck_mtx_lock((a)->lock); \
147         osi_Assert((a)->owner == (thread_t)0); \
148         (a)->owner = current_thread(); \
149     } while(0)
150
151 /* acquire main lock before releasing meta lock, so we don't race */
152 #define MUTEX_TRYENTER(a) ({ \
153     int _ret; \
154     lck_mtx_lock((a)->meta); \
155     if ((a)->waiters) { \
156        lck_mtx_unlock((a)->meta); \
157        _ret = 0; \
158     } else { \
159        (a)->waiters++; \
160        lck_mtx_lock((a)->lock); \
161        lck_mtx_unlock((a)->meta); \
162        osi_Assert((a)->owner == (thread_t)0); \
163        (a)->owner = current_thread(); \
164        _ret = 1; \
165     } \
166     _ret; \
167 })
168
169 #define MUTEX_EXIT(a) \
170     do { \
171         osi_Assert((a)->owner == current_thread()); \
172         (a)->owner = (thread_t)0; \
173         lck_mtx_unlock((a)->lock); \
174         lck_mtx_lock((a)->meta); \
175         (a)->waiters--; \
176         lck_mtx_unlock((a)->meta); \
177     } while(0)
178
179 #undef MUTEX_ISMINE
180 #define MUTEX_ISMINE(a) (((afs_kmutex_t *)(a))->owner == current_thread())
181 #else
182 typedef struct {
183     struct lock__bsd__ lock;
184     thread_t owner;
185 } afs_kmutex_t;
186 typedef int afs_kcondvar_t;
187
188 #define LOCK_INIT(a,b) \
189     do { \
190         lockinit(&(a)->lock,PSOCK, "afs rx lock", 0, 0); \
191         (a)->owner = (thread_t)0; \
192     } while(0);
193 #define MUTEX_INIT(a,b,c,d) \
194     do { \
195         lockinit(&(a)->lock,PSOCK, "afs rx mutex", 0, 0); \
196         (a)->owner = (thread_t)0; \
197     } while(0);
198 #define MUTEX_DESTROY(a) \
199     do { \
200         (a)->owner = (thread_t)-1; \
201     } while(0);
202 #define MUTEX_ENTER(a) \
203     do { \
204         lockmgr(&(a)->lock, LK_EXCLUSIVE, 0, current_proc()); \
205         osi_Assert((a)->owner == (thread_t)0); \
206         (a)->owner = current_thread(); \
207     } while(0);
208 #define MUTEX_TRYENTER(a) \
209     ( lockmgr(&(a)->lock, LK_EXCLUSIVE|LK_NOWAIT, 0, current_proc()) ? 0 : ((a)->owner = current_thread(), 1) )
210 #define MUTEX_EXIT(a) \
211     do { \
212         osi_Assert((a)->owner == current_thread()); \
213         (a)->owner = (thread_t)0; \
214         lockmgr(&(a)->lock, LK_RELEASE, 0, current_proc()); \
215     } while(0);
216
217 #undef MUTEX_ISMINE
218 #define MUTEX_ISMINE(a) (((afs_kmutex_t *)(a))->owner == current_thread())
219 #endif
220
221 #undef osirx_AssertMine
222 extern void osirx_AssertMine(afs_kmutex_t * lockaddr, char *msg);
223
224 #endif /* _RX_KMUTEX_H_ */