Whamcloud - gitweb
00fbeed0c613b6775e35bb2beb49a2841048ea82
[fs/lustre-release.git] / lnet / include / libcfs / darwin / darwin-prim.h
1 #ifndef __LIBCFS_DARWIN_CFS_PRIM_H__
2 #define __LIBCFS_DARWIN_CFS_PRIM_H__
3
4 #ifndef __LIBCFS_LIBCFS_H__
5 #error Do not #include this file directly. #include <libcfs/libcfs.h> instead
6 #endif
7
8 #ifdef __KERNEL__
9 #include <sys/types.h>
10 #include <sys/systm.h>
11
12 #ifndef __DARWIN8__
13 # ifndef __APPLE_API_PRIVATE
14 #  define __APPLE_API_PRIVATE
15 #  include <sys/user.h>
16 #  undef __APPLE_API_PRIVATE
17 # else
18 #  include <sys/user.h>
19 # endif
20 # include <mach/mach_traps.h>
21 # include <mach/thread_switch.h>
22 # include <machine/cpu_number.h>
23 #endif /* !__DARWIN8__ */
24
25 #include <sys/kernel.h>
26
27 #include <mach/thread_act.h>
28 #include <mach/mach_types.h>
29 #include <mach/time_value.h>
30 #include <kern/sched_prim.h>
31 #include <vm/pmap.h>
32 #include <vm/vm_kern.h>
33 #include <mach/machine/vm_param.h>
34 #include <machine/machine_routines.h>
35 #include <kern/clock.h>
36 #include <kern/thread_call.h>
37 #include <sys/param.h>
38 #include <sys/vm.h>
39
40 #include <libcfs/darwin/darwin-types.h>
41 #include <libcfs/darwin/darwin-utils.h>
42 #include <libcfs/darwin/darwin-lock.h>
43
44 /*
45  * Symbol functions for libcfs
46  *
47  * OSX has no facility for use to register symbol.
48  * So we have to implement it.
49  */
50 #define CFS_SYMBOL_LEN     64
51
52 struct  cfs_symbol {
53         char    name[CFS_SYMBOL_LEN];
54         void    *value;
55         int     ref;
56         struct  list_head sym_list;
57 };
58
59 extern kern_return_t            cfs_symbol_register(const char *, const void *);
60 extern kern_return_t            cfs_symbol_unregister(const char *);
61 extern void *                   cfs_symbol_get(const char *);
62 extern kern_return_t            cfs_symbol_put(const char *);
63
64 /*
65  * sysctl typedef
66  *
67  * User can register/unregister a list of sysctl_oids
68  * sysctl_oid is data struct of osx's sysctl-entry
69  */
70 #define         CONFIG_SYSCTL   1
71
72 typedef struct sysctl_oid *     cfs_sysctl_table_t;
73 typedef cfs_sysctl_table_t      cfs_sysctl_table_header_t;
74 cfs_sysctl_table_header_t       *cfs_register_sysctl_table (cfs_sysctl_table_t *table, int arg);
75 void cfs_unregister_sysctl_table (cfs_sysctl_table_header_t *table);
76
77 /*
78  * Proc file system APIs, no /proc fs support in OSX
79  */
80 typedef struct cfs_proc_dir_entry {
81         void            *data;
82 } cfs_proc_dir_entry_t;
83
84 cfs_proc_dir_entry_t * cfs_create_proc_entry(char *name, int mod,
85                                           cfs_proc_dir_entry_t *parent);
86 void cfs_free_proc_entry(cfs_proc_dir_entry_t *de);
87 void cfs_remove_proc_entry(char *name, cfs_proc_dir_entry_t *entry);
88
89 typedef int (cfs_read_proc_t)(char *page, char **start, off_t off,
90                           int count, int *eof, void *data);
91 typedef int (cfs_write_proc_t)(struct file *file, const char *buffer,
92                            unsigned long count, void *data);
93
94 /*
95  * cfs pseudo device
96  *
97  * cfs_psdev_t
98  * cfs_psdev_register:
99  * cfs_psdev_deregister:
100  */
101 typedef struct {
102         int             index;
103         void            *handle;
104         const char      *name;
105         struct cdevsw   *devsw;
106         void            *private;
107 } cfs_psdev_t;
108
109 extern kern_return_t            cfs_psdev_register(cfs_psdev_t *);
110 extern kern_return_t            cfs_psdev_deregister(cfs_psdev_t *);
111
112 /*
113  * Task struct and ...
114  *
115  * Using BSD current_proc in Darwin
116  */
117 extern boolean_t        assert_wait_possible(void);
118 extern void             *get_bsdtask_info(task_t);
119
120 #ifdef __DARWIN8__
121
122 typedef struct {}               cfs_task_t;
123 #define cfs_current()           ((cfs_task_t *)current_thread())
124 #else   /* !__DARWIN8__ */
125
126 typedef struct uthread          cfs_task_t;
127
128 #define current_uthread()       ((struct uthread *)get_bsdthread_info(current_act()))
129 #define cfs_current()           current_uthread()
130
131 #endif /* !__DARWIN8__ */
132
133 #define cfs_task_lock(t)        do {;} while (0)
134 #define cfs_task_unlock(t)      do {;} while (0)
135
136 #define set_current_state(s)    do {;} while (0)
137
138 #define CFS_DECL_JOURNAL_DATA   
139 #define CFS_PUSH_JOURNAL        do {;} while(0)
140 #define CFS_POP_JOURNAL         do {;} while(0)
141
142 #define THREAD_NAME(comm, fmt, a...)
143 /*
144  * Kernel thread:
145  *
146  * OSX kernel thread can not be created with args,
147  * so we have to implement new APIs to create thread with args
148  */
149
150 typedef int (*cfs_thread_t)(void *);
151
152 extern task_t   kernel_task;
153
154 /*
155  * cloning flags, no use in OSX, just copy them from Linux
156  */
157 #define CSIGNAL         0x000000ff      /* signal mask to be sent at exit */
158 #define CLONE_VM        0x00000100      /* set if VM shared between processes */
159 #define CLONE_FS        0x00000200      /* set if fs info shared between processes */
160 #define CLONE_FILES     0x00000400      /* set if open files shared between processes */
161 #define CLONE_SIGHAND   0x00000800      /* set if signal handlers and blocked signals shared */
162 #define CLONE_PID       0x00001000      /* set if pid shared */
163 #define CLONE_PTRACE    0x00002000      /* set if we want to let tracing continue on the child too */
164 #define CLONE_VFORK     0x00004000      /* set if the parent wants the child to wake it up on mm_release */
165 #define CLONE_PARENT    0x00008000      /* set if we want to have the same parent as the cloner */
166 #define CLONE_THREAD    0x00010000      /* Same thread group? */
167 #define CLONE_NEWNS     0x00020000      /* New namespace group? */
168
169 #define CLONE_SIGNAL    (CLONE_SIGHAND | CLONE_THREAD)
170
171 extern int cfs_kernel_thread(cfs_thread_t func, void *arg, int flag);
172
173
174 /*
175  * Wait Queue implementation
176  *
177  * Like wait_queue in Linux
178  */
179 typedef struct cfs_waitq {
180         struct ksleep_chan wq_ksleep_chan;
181 } cfs_waitq_t;
182
183 typedef struct cfs_waitlink {
184         struct cfs_waitq   *wl_waitq;
185         struct ksleep_link  wl_ksleep_link;
186 } cfs_waitlink_t;
187
188 typedef int cfs_task_state_t;
189
190 #define CFS_TASK_INTERRUPTIBLE  THREAD_ABORTSAFE
191 #define CFS_TASK_UNINT          THREAD_UNINT
192
193 void cfs_waitq_init(struct cfs_waitq *waitq);
194 void cfs_waitlink_init(struct cfs_waitlink *link);
195
196 void cfs_waitq_add(struct cfs_waitq *waitq, struct cfs_waitlink *link);
197 void cfs_waitq_add_exclusive(struct cfs_waitq *waitq,
198                              struct cfs_waitlink *link);
199 void cfs_waitq_forward(struct cfs_waitlink *link, struct cfs_waitq *waitq);
200 void cfs_waitq_del(struct cfs_waitq *waitq, struct cfs_waitlink *link);
201 int  cfs_waitq_active(struct cfs_waitq *waitq);
202
203 void cfs_waitq_signal(struct cfs_waitq *waitq);
204 void cfs_waitq_signal_nr(struct cfs_waitq *waitq, int nr);
205 void cfs_waitq_broadcast(struct cfs_waitq *waitq);
206
207 void cfs_waitq_wait(struct cfs_waitlink *link, cfs_task_state_t state);
208 cfs_duration_t cfs_waitq_timedwait(struct cfs_waitlink *link,
209                                    cfs_task_state_t state, 
210                                    cfs_duration_t timeout);
211
212 /*
213  * Thread schedule APIs.
214  */
215 #define MAX_SCHEDULE_TIMEOUT    ((long)(~0UL>>12))
216 extern void thread_set_timer_deadline(uint64_t  deadline);
217 extern void thread_cancel_timer(void);
218
219 static inline int cfs_schedule_timeout(int state, int64_t timeout)
220 {
221         int          result;
222         
223 #ifdef __DARWIN8__
224         result = assert_wait((event_t)current_thread(), state);
225 #else
226         result = assert_wait((event_t)current_uthread(), state);
227 #endif
228         if (timeout > 0) {
229                 uint64_t expire;
230                 nanoseconds_to_absolutetime(timeout, &expire);
231                 clock_absolutetime_interval_to_deadline(expire, &expire);
232                 thread_set_timer_deadline(expire);
233         }
234         if (result == THREAD_WAITING)
235                 result = thread_block(THREAD_CONTINUE_NULL);
236         if (timeout > 0)
237                 thread_cancel_timer();
238         if (result == THREAD_TIMED_OUT)
239                 result = 0;
240         else
241                 result = 1;
242         return result;
243 }
244
245 #define cfs_schedule()  cfs_schedule_timeout(CFS_TASK_UNINT, CFS_TICK)
246 #define cfs_pause(tick) cfs_schedule_timeout(CFS_TASK_UNINT, tick)
247
248 #define __wait_event(wq, condition)                             \
249 do {                                                            \
250         struct cfs_waitlink __wait;                             \
251                                                                 \
252         cfs_waitlink_init(&__wait);                             \
253         for (;;) {                                              \
254                 cfs_waitq_add(&wq, &__wait);                    \
255                 if (condition)                                  \
256                         break;                                  \
257                 cfs_waitq_wait(&__wait, CFS_TASK_UNINT);        \
258                 cfs_waitq_del(&wq, &__wait);                    \
259         }                                                       \
260         cfs_waitq_del(&wq, &__wait);                            \
261 } while (0)
262
263 #define wait_event(wq, condition)                               \
264 do {                                                            \
265         if (condition)                                          \
266                 break;                                          \
267         __wait_event(wq, condition);                            \
268 } while (0)
269
270 #define __wait_event_interruptible(wq, condition, ex, ret)      \
271 do {                                                            \
272         struct cfs_waitlink __wait;                             \
273                                                                 \
274         cfs_waitlink_init(&__wait);                             \
275         for (;;) {                                              \
276                 if (ex == 0)                                    \
277                         cfs_waitq_add(&wq, &__wait);            \
278                 else                                            \
279                         cfs_waitq_add_exclusive(&wq, &__wait);  \
280                 if (condition)                                  \
281                         break;                                  \
282                 if (!cfs_signal_pending()) {                    \
283                         cfs_waitq_wait(&__wait,                 \
284                                        CFS_TASK_INTERRUPTIBLE); \
285                         cfs_waitq_del(&wq, &__wait);            \
286                         continue;                               \
287                 }                                               \
288                 ret = -ERESTARTSYS;                             \
289                 break;                                          \
290         }                                                       \
291         cfs_waitq_del(&wq, &__wait);                            \
292 } while (0)
293
294 #define wait_event_interruptible(wq, condition)                 \
295 ({                                                              \
296         int __ret = 0;                                          \
297         if (!condition)                                         \
298                 __wait_event_interruptible(wq, condition,       \
299                                            0, __ret);           \
300         __ret;                                                  \
301 })
302
303 #define wait_event_interruptible_exclusive(wq, condition)       \
304 ({                                                              \
305         int __ret = 0;                                          \
306         if (!condition)                                         \
307                 __wait_event_interruptible(wq, condition,       \
308                                            1, __ret);           \
309         __ret;                                                  \
310 })
311
312 #ifndef __DARWIN8__
313 extern void     wakeup_one __P((void * chan));
314 #endif
315 /* only used in tests */
316 #define wake_up_process(p)                                      \
317         do {                                                    \
318                 wakeup_one((caddr_t)p);                         \
319         } while (0)
320         
321 /* used in couple of places */
322 static inline void sleep_on(cfs_waitq_t *waitq)
323 {
324         cfs_waitlink_t link;
325         
326         cfs_waitlink_init(&link);
327         cfs_waitq_add(waitq, &link);
328         cfs_waitq_wait(&link, CFS_TASK_UNINT);
329         cfs_waitq_del(waitq, &link);
330 }
331
332 /*
333  * Signal
334  */
335 typedef sigset_t        cfs_sigset_t;
336
337 #define SIGNAL_MASK_ASSERT()
338 /*
339  * Timer
340  */
341 typedef struct cfs_timer {
342         struct ktimer t;
343 } cfs_timer_t;
344
345 #define cfs_init_timer(t)       do {} while(0)
346 void cfs_timer_init(struct cfs_timer *t, void (*func)(unsigned long), void *arg);
347 void cfs_timer_done(struct cfs_timer *t);
348 void cfs_timer_arm(struct cfs_timer *t, cfs_time_t deadline);
349 void cfs_timer_disarm(struct cfs_timer *t);
350 int  cfs_timer_is_armed(struct cfs_timer *t);
351
352 cfs_time_t cfs_timer_deadline(struct cfs_timer *t);
353
354 /*
355  * Ioctl
356  * We don't need to copy out everything in osx
357  */
358 #define cfs_ioctl_data_out(a, d, l)                     \
359         ({                                              \
360                 int __size;                             \
361                 int __rc = 0;                           \
362                 assert((l) >= sizeof(*d));              \
363                 __size = (l) - sizeof(*d);              \
364                 if (__size > 0)                         \
365                         __rc = copy_to_user((void *)a + __size, \
366                              (void *)d + __size,        \
367                              __size);                   \
368                 __rc;                                   \
369         })
370
371 /*
372  * CPU
373  */
374 /* Run in PowerG5 who is PPC64 */
375 #define SMP_CACHE_BYTES                         128
376 #define __cacheline_aligned                     __attribute__((__aligned__(SMP_CACHE_BYTES)))
377 #define NR_CPUS                                 2
378
379 /* 
380  * XXX Liang: patch xnu and export current_processor()?
381  *
382  * #define smp_processor_id()                   current_processor()
383  */
384 #define smp_processor_id()                      0
385 /* XXX smp_call_function is not supported in xnu */
386 #define smp_call_function(f, a, n, w)           do {} while(0)
387 int cfs_online_cpus(void);
388 #define smp_num_cpus                            cfs_online_cpus()
389
390 /*
391  * Misc
392  */
393 extern int is_suser(void);
394
395 #ifndef likely
396 #define likely(exp) (exp)
397 #endif
398 #ifndef unlikely
399 #define unlikely(exp) (exp)
400 #endif
401
402 #define lock_kernel()                           do {} while(0)
403 #define unlock_kernel()                         do {} while(0)
404
405 #define CAP_SYS_BOOT                            0
406 #define CAP_SYS_ADMIN                           1
407 #define capable(a)                              ((a) == CAP_SYS_BOOT ? is_suser(): is_suser1())
408
409 #define USERMODEHELPER(path, argv, envp)        (0)
410
411 #define cfs_module(name, version, init, fini)                           \
412 extern kern_return_t _start(kmod_info_t *ki, void *data);               \
413 extern kern_return_t _stop(kmod_info_t *ki, void *data);                \
414 __private_extern__ kern_return_t name##_start(kmod_info_t *ki, void *data); \
415 __private_extern__ kern_return_t name##_stop(kmod_info_t *ki, void *data); \
416                                                                         \
417 kmod_info_t KMOD_INFO_NAME = { 0, KMOD_INFO_VERSION, -1,                \
418                                { "com.clusterfs.lustre." #name }, { version }, \
419                                -1, 0, 0, 0, 0, name##_start, name##_stop }; \
420                                                                         \
421 __private_extern__ kmod_start_func_t *_realmain = name##_start;         \
422 __private_extern__ kmod_stop_func_t *_antimain = name##_stop;           \
423 __private_extern__ int _kext_apple_cc = __APPLE_CC__ ;                  \
424                                                                         \
425 kern_return_t name##_start(kmod_info_t *ki, void *d)                    \
426 {                                                                       \
427         return init();                                                  \
428 }                                                                       \
429                                                                         \
430 kern_return_t name##_stop(kmod_info_t *ki, void *d)                     \
431 {                                                                       \
432         fini();                                                         \
433         return KERN_SUCCESS;                                            \
434 }                                                                       \
435                                                                         \
436 /*                                                                      \
437  * to allow semicolon after cfs_module(...)                             \
438  */                                                                     \
439 struct __dummy_ ## name ## _struct {}
440
441 #define inter_module_get(n)                     cfs_symbol_get(n)
442 #define inter_module_put(n)                     cfs_symbol_put(n)
443
444 static inline int request_module(char *name)
445 {
446         return (-EINVAL);
447 }
448
449 #ifndef __exit
450 #define __exit
451 #endif
452 #ifndef __init
453 #define __init
454 #endif
455
456 #define EXPORT_SYMBOL(s)
457 #define MODULE_AUTHOR(s)
458 #define MODULE_DESCRIPTION(s)
459 #define MODULE_LICENSE(s)
460 #define MODULE_PARM(a, b)
461 #define MODULE_PARM_DESC(a, b)
462
463 #define KERNEL_VERSION(a,b,c) ((a)*100+(b)*10+c)
464 #define LINUX_VERSION_CODE KERNEL_VERSION(2,5,0)
465
466 #define NR_IRQS                         512
467 #define in_interrupt()                  ml_at_interrupt_context()
468
469 #define KERN_EMERG      "<0>"   /* system is unusable                   */
470 #define KERN_ALERT      "<1>"   /* action must be taken immediately     */
471 #define KERN_CRIT       "<2>"   /* critical conditions                  */
472 #define KERN_ERR        "<3>"   /* error conditions                     */
473 #define KERN_WARNING    "<4>"   /* warning conditions                   */
474 #define KERN_NOTICE     "<5>"   /* normal but significant condition     */
475 #define KERN_INFO       "<6>"   /* informational                        */
476 #define KERN_DEBUG      "<7>"   /* debug-level messages                 */
477
478 static inline long PTR_ERR(const void *ptr)
479 {
480         return (long) ptr;
481 }
482
483 #define ERR_PTR(err)    ((void *)err)
484 #define IS_ERR(p)       ((unsigned long)(p) + 1000 < 1000)
485
486 #else   /* !__KERNEL__ */
487
488 typedef struct cfs_proc_dir_entry {
489         void            *data;
490 } cfs_proc_dir_entry_t;
491
492 #include <libcfs/user-prim.h>
493 #define __WORDSIZE      32
494
495 #endif  /* END __KERNEL__ */
496 /*
497  * Error number
498  */
499 #ifndef EPROTO
500 #define EPROTO          EPROTOTYPE
501 #endif
502 #ifndef EBADR
503 #define EBADR           EBADRPC
504 #endif
505 #ifndef ERESTARTSYS
506 #define ERESTARTSYS     512
507 #endif
508 #ifndef EDEADLOCK
509 #define EDEADLOCK       EDEADLK
510 #endif
511 #ifndef ECOMM
512 #define ECOMM           EINVAL
513 #endif
514 #ifndef ENODATA
515 #define ENODATA         EINVAL
516 #endif
517 #ifndef ENOTSUPP
518 #define ENOTSUPP        EINVAL
519 #endif
520
521 #if BYTE_ORDER == BIG_ENDIAN
522 # define __BIG_ENDIAN
523 #else
524 # define __LITTLE_ENDIAN
525 #endif
526
527 #endif  /* __LIBCFS_DARWIN_CFS_PRIM_H__ */