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