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