Whamcloud - gitweb
Landing b_hd_newconfig on HEAD
[fs/lustre-release.git] / lnet / include / libcfs / darwin / darwin-sync.h
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Implementation of standard libcfs synchronization primitives for XNU
5  * kernel.
6  *
7  *  Copyright (c) 2004 Cluster File Systems, Inc.
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or modify it under
12  *   the terms of version 2 of the GNU General Public License as published by
13  *   the Free Software Foundation. Lustre is distributed in the hope that it
14  *   will be useful, but WITHOUT ANY WARRANTY; without even the implied
15  *   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details. You should have received a
17  *   copy of the GNU General Public License along with Lustre; if not, write
18  *   to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
19  *   USA.
20  */
21
22 /*
23  * xnu_sync.h
24  *
25  * Created by nikita on Sun Jul 18 2004.
26  *
27  * Prototypes of XNU synchronization primitives.
28  */
29
30 #ifndef __LIBCFS_DARWIN_XNU_SYNC_H__
31 #define __LIBCFS_DARWIN_XNU_SYNC_H__
32
33 #ifndef __LIBCFS_LIBCFS_H__
34 #error Do not #include this file directly. #include <libcfs/libcfs.h> instead
35 #endif
36
37 #define XNU_SYNC_DEBUG (1)
38
39 #if XNU_SYNC_DEBUG
40 #define ON_SYNC_DEBUG(e) e
41 #else
42 #define ON_SYNC_DEBUG(e)
43 #endif
44
45 enum {
46         /* "egrep -i '^(o?x)?[abcdeflo]*$' /usr/dict/words" is your friend */
47         KMUT_MAGIC  = 0x0bac0cab, /* [a, [b, c]] = b (a, c) - c (a, b) */
48         KSEM_MAGIC  = 0x1abe11ed,
49         KCOND_MAGIC = 0xb01dface,
50         KRW_MAGIC   = 0xdabb1edd,
51         KSPIN_MAGIC = 0xca11ab1e,
52         KRW_SPIN_MAGIC    = 0xbabeface,
53         KSLEEP_CHAN_MAGIC = 0x0debac1e,
54         KSLEEP_LINK_MAGIC = 0xacc01ade,
55         KTIMER_MAGIC      = 0xbefadd1e
56 };
57
58 /* ------------------------- spin lock ------------------------- */
59
60 /*
61  * XXX nikita: don't use NCPUS it's hardcoded to (1) in cpus.h
62  */
63 #define SMP (1)
64
65 #include <libcfs/list.h>
66
67 #ifdef __DARWIN8__
68
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/kernel.h>
72 #include <kern/locks.h>
73
74 /*
75  * hw_lock is not available in Darwin8 (hw_lock_* are not exported at all), 
76  * so use lck_spin_t. we can hack out lck_spin_t easily, it's the only 
77  * hacking in Darwin8.x. We did so because it'll take a lot of time to 
78  * add lock_done for all locks, maybe it should be done in the future.
79  * If lock_done for all locks were added, we can:
80  *
81  * typedef lck_spin_t      *xnu_spin_t;
82  */
83 #if defined (__ppc__)
84 typedef struct {
85         unsigned int    opaque[3];
86 } xnu_spin_t;
87 #elif defined (__i386__)
88 typedef struct {
89         unsigned int    opaque[10];
90 } xnu_spin_t;
91 #endif
92
93 /* 
94  * wait_queue is not available in Darwin8 (wait_queue_* are not exported), 
95  * use assert_wait/wakeup/wake_one (wait_queue in kernel hash).
96  */
97 typedef void * xnu_wait_queue_t;
98
99 /* DARWIN8 */
100 #else
101
102 #include <mach/mach_types.h>
103 #include <sys/types.h>
104 #include <kern/simple_lock.h>
105
106 typedef hw_lock_data_t          xnu_spin_t;
107 typedef struct wait_queue       xnu_wait_queue_t;
108
109 /* DARWIN8 */
110 #endif
111
112 struct kspin {
113 #if SMP
114         xnu_spin_t      lock;
115 #endif
116 #if XNU_SYNC_DEBUG
117         unsigned        magic;
118         thread_t        owner;
119 #endif
120 };
121
122 void kspin_init(struct kspin *spin);
123 void kspin_done(struct kspin *spin);
124 void kspin_lock(struct kspin *spin);
125 void kspin_unlock(struct kspin *spin);
126 int  kspin_trylock(struct kspin *spin);
127
128 #if XNU_SYNC_DEBUG
129 /*
130  * two functions below are for use in assertions
131  */
132 /* true, iff spin-lock is locked by the current thread */
133 int kspin_islocked(struct kspin *spin);
134 /* true, iff spin-lock is not locked by the current thread */
135 int kspin_isnotlocked(struct kspin *spin);
136 #else
137 #define kspin_islocked(s) (1)
138 #define kspin_isnotlocked(s) (1)
139 #endif
140
141 /* ------------------------- rw spinlock ----------------------- */
142 struct krw_spin {
143         struct kspin      guard;
144         int               count;
145 #if XNU_SYNC_DEBUG
146         unsigned          magic;
147 #endif
148 };
149
150 void krw_spin_init(struct krw_spin *sem);
151 void krw_spin_done(struct krw_spin *sem);
152 void krw_spin_down_r(struct krw_spin *sem);
153 void krw_spin_down_w(struct krw_spin *sem);
154 void krw_spin_up_r(struct krw_spin *sem);
155 void krw_spin_up_w(struct krw_spin *sem);
156
157 /* ------------------------- semaphore ------------------------- */
158
159 struct ksem {
160         struct kspin      guard;
161         xnu_wait_queue_t  q;
162         int               value;
163 #if XNU_SYNC_DEBUG
164         unsigned          magic;
165 #endif
166 };
167
168 void ksem_init(struct ksem *sem, int value);
169 void ksem_done(struct ksem *sem);
170 int  ksem_up  (struct ksem *sem, int value);
171 void ksem_down(struct ksem *sem, int value);
172 int  ksem_trydown(struct ksem *sem, int value);
173
174 /* ------------------------- mutex ------------------------- */
175
176 struct kmut {
177         struct ksem s;
178 #if XNU_SYNC_DEBUG
179         unsigned    magic;
180         thread_t    owner;
181 #endif
182 };
183
184 void kmut_init(struct kmut *mut);
185 void kmut_done(struct kmut *mut);
186
187 void kmut_lock   (struct kmut *mut);
188 void kmut_unlock (struct kmut *mut);
189 int  kmut_trylock(struct kmut *mut);
190
191 #if XNU_SYNC_DEBUG
192 /*
193  * two functions below are for use in assertions
194  */
195 /* true, iff mutex is locked by the current thread */
196 int kmut_islocked(struct kmut *mut);
197 /* true, iff mutex is not locked by the current thread */
198 int kmut_isnotlocked(struct kmut *mut);
199 #else
200 #define kmut_islocked(m) (1)
201 #define kmut_isnotlocked(m) (1)
202 #endif
203
204 /* ------------------------- condition variable ------------------------- */
205
206 struct kcond_link {
207         struct kcond_link *next;
208         struct ksem        sem;
209 };
210
211 struct kcond {
212         struct kspin       guard;
213         struct kcond_link *waiters;
214 #if XNU_SYNC_DEBUG
215         unsigned           magic;
216 #endif
217 };
218
219 void kcond_init(struct kcond *cond);
220 void kcond_done(struct kcond *cond);
221 void kcond_wait(struct kcond *cond, struct kspin *lock);
222 void kcond_signal(struct kcond *cond);
223 void kcond_broadcast(struct kcond *cond);
224
225 void kcond_wait_guard(struct kcond *cond);
226 void kcond_signal_guard(struct kcond *cond);
227 void kcond_broadcast_guard(struct kcond *cond);
228
229 /* ------------------------- read-write semaphore ------------------------- */
230
231 struct krw_sem {
232         int          count;
233         struct kcond cond;
234 #if XNU_SYNC_DEBUG
235         unsigned     magic;
236 #endif
237 };
238
239 void krw_sem_init(struct krw_sem *sem);
240 void krw_sem_done(struct krw_sem *sem);
241 void krw_sem_down_r(struct krw_sem *sem);
242 int krw_sem_down_r_try(struct krw_sem *sem);
243 void krw_sem_down_w(struct krw_sem *sem);
244 int krw_sem_down_w_try(struct krw_sem *sem);
245 void krw_sem_up_r(struct krw_sem *sem);
246 void krw_sem_up_w(struct krw_sem *sem);
247
248 /* ------------------------- sleep-channel ------------------------- */
249
250 struct ksleep_chan {
251         struct kspin     guard;
252         struct list_head waiters;
253 #if XNU_SYNC_DEBUG
254         unsigned     magic;
255 #endif
256 };
257
258 #define KSLEEP_CHAN_INITIALIZER         {{{0}}}
259
260 struct ksleep_link {
261         int                 flags;
262         event_t             event;
263         int                 hits;
264         struct ksleep_chan *forward;
265         struct list_head    linkage;
266 #if XNU_SYNC_DEBUG
267         unsigned     magic;
268 #endif
269 };
270
271 enum {
272         KSLEEP_EXCLUSIVE = 1
273 };
274
275 void ksleep_chan_init(struct ksleep_chan *chan);
276 void ksleep_chan_done(struct ksleep_chan *chan);
277
278 void ksleep_link_init(struct ksleep_link *link);
279 void ksleep_link_done(struct ksleep_link *link);
280
281 void ksleep_add(struct ksleep_chan *chan, struct ksleep_link *link);
282 void ksleep_del(struct ksleep_chan *chan, struct ksleep_link *link);
283
284 void ksleep_wait(struct ksleep_chan *chan, int state);
285 int64_t  ksleep_timedwait(struct ksleep_chan *chan, int state, uint64_t timeout);
286
287 void ksleep_wake(struct ksleep_chan *chan);
288 void ksleep_wake_all(struct ksleep_chan *chan);
289 void ksleep_wake_nr(struct ksleep_chan *chan, int nr);
290
291 #define KSLEEP_LINK_DECLARE(name)               \
292 {                                               \
293         .flags   = 0,                           \
294         .event   = 0,                           \
295         .hits    = 0,                           \
296         .linkage = CFS_LIST_HEAD(name.linkage), \
297         .magic   = KSLEEP_LINK_MAGIC            \
298 }
299
300 /* ------------------------- timer ------------------------- */
301
302 struct ktimer {
303         struct kspin   guard;
304         void         (*func)(void *);
305         void          *arg;
306         u_int64_t      deadline; /* timer deadline in absolute nanoseconds */
307         int            armed;
308 #if XNU_SYNC_DEBUG
309         unsigned     magic;
310 #endif
311 };
312
313 void ktimer_init(struct ktimer *t, void (*func)(void *), void *arg);
314 void ktimer_done(struct ktimer *t);
315 void ktimer_arm(struct ktimer *t, u_int64_t deadline);
316 void ktimer_disarm(struct ktimer *t);
317 int  ktimer_is_armed(struct ktimer *t);
318
319 u_int64_t ktimer_deadline(struct ktimer *t);
320
321 /* __XNU_SYNC_H__ */
322 #endif
323
324 /*
325  * Local variables:
326  * c-indentation-style: "K&R"
327  * c-basic-offset: 8
328  * tab-width: 8
329  * fill-column: 80
330  * scroll-step: 1
331  * End:
332  */