1 #ifndef __LIBCFS_DARWIN_CFS_PRIM_H__
2 #define __LIBCFS_DARWIN_CFS_PRIM_H__
4 #ifndef __LIBCFS_LIBCFS_H__
5 #error Do not #include this file directly. #include <libcfs/libcfs.h> instead
10 #include <sys/systm.h>
12 #ifndef __APPLE_API_PRIVATE
13 #define __APPLE_API_PRIVATE
15 #undef __APPLE_API_PRIVATE
20 #include <sys/kernel.h>
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>
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>
36 #include <libcfs/darwin/darwin-types.h>
37 #include <libcfs/darwin/darwin-utils.h>
38 #include <libcfs/darwin/darwin-lock.h>
41 * Symbol functions for libcfs
43 * OSX has no facility for use to register symbol.
44 * So we have to implement it.
46 #define CFS_SYMBOL_LEN 64
49 char name[CFS_SYMBOL_LEN];
52 struct list_head sym_list;
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 *);
63 * User can register/unregister a list of sysctl_oids
64 * sysctl_oid is data struct of osx's sysctl-entry
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);
72 * Proc file system APIs, no /proc fs support in OSX
74 typedef struct cfs_proc_dir_entry{
76 }cfs_proc_dir_entry_t;
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);
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);
93 * cfs_psdev_deregister:
103 extern kern_return_t cfs_psdev_register(cfs_psdev_t *);
104 extern kern_return_t cfs_psdev_deregister(cfs_psdev_t *);
107 * Task struct and ...
109 * Using BSD current_proc in Darwin
111 extern boolean_t assert_wait_possible(void);
112 extern void *get_bsdtask_info(task_t);
114 typedef struct uthread cfs_task_t;
115 #define current_uthread() ((struct uthread *)get_bsdthread_info(current_act()))
116 #define cfs_current() current_uthread()
118 #define set_current_state(s) do {;} while (0)
119 #define reparent_to_init() do {;} while (0)
121 #define CFS_DECL_JOURNAL_DATA
122 #define CFS_PUSH_JOURNAL do {;} while(0)
123 #define CFS_POP_JOURNAL do {;} while(0)
125 #define THREAD_NAME(comm, fmt, a...)
129 * OSX kernel thread can not be created with args,
130 * so we have to implement new APIs to create thread with args
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.
138 typedef int (*cfs_thread_t)(void *);
140 extern task_t kernel_task;
142 struct kernel_thread_arg
150 extern struct kernel_thread_arg cfs_thread_arg;
151 extern void cfs_thread_agent(void);
153 #define THREAD_ARG_FREE 0
154 #define THREAD_ARG_HOLD 1
155 #define THREAD_ARG_RECV 2
157 #define set_targ_stat(a, v) atomic_set(&(a)->inuse, v)
158 #define get_targ_stat(a) atomic_read(&(a)->inuse)
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.
165 #define thread_arg_hold(pta, _func, _arg) \
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); \
175 spin_unlock(&(pta)->lock); \
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.
187 #define thread_arg_release(pta) \
189 spin_lock(&(pta)->lock); \
190 if (get_targ_stat(pta) == THREAD_ARG_RECV) { \
192 (pta)->func = NULL; \
193 set_targ_stat(pta, THREAD_ARG_FREE); \
194 spin_unlock(&(pta)->lock); \
197 spin_unlock(&(pta)->lock); \
202 * Receive thread argument (Used in child thread), set the status
203 * of thread_args to THREAD_ARG_RECV.
205 #define __thread_arg_recv_fin(pta, _func, _arg, fin) \
207 spin_lock(&(pta)->lock); \
208 if (get_targ_stat(pta) == THREAD_ARG_HOLD) { \
210 set_targ_stat(pta, THREAD_ARG_RECV);\
212 _func = (pta)->func; \
213 spin_unlock(&(pta)->lock); \
216 spin_unlock(&(pta)->lock); \
221 * Just set the thread_args' status to THREAD_ARG_RECV
223 #define thread_arg_fin(pta) \
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); \
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)
235 * cloning flags, no use in OSX, just copy them from Linux
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? */
249 #define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
251 extern int cfs_kernel_thread(cfs_thread_t func, void *arg, int flag);
255 * Wait Queue implementation
257 * Like wait_queue in Linux
259 typedef struct cfs_waitq {
260 struct ksleep_chan wq_ksleep_chan;
263 typedef struct cfs_waitlink {
264 struct cfs_waitq *wl_waitq;
265 struct ksleep_link wl_ksleep_link;
268 void cfs_waitq_init(struct cfs_waitq *waitq);
269 void cfs_waitlink_init(struct cfs_waitlink *link);
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);
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);
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);
287 * Thread schedule APIs.
289 #define MAX_SCHEDULE_TIMEOUT ((long)(~0UL>>12))
291 static inline int schedule_timeout(int64_t timeout)
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)
314 if (assert_wait_possible()) \
315 schedule_timeout(1); \
317 schedule_timeout(0); \
320 #define __wait_event(wq, condition) \
322 struct cfs_waitlink __wait; \
324 cfs_waitlink_init(&__wait); \
326 cfs_waitq_add(&wq, &__wait); \
329 cfs_waitq_wait(&__wait); \
330 cfs_waitq_del(&wq, &__wait); \
332 cfs_waitq_del(&wq, &__wait); \
335 #define wait_event(wq, condition) \
339 __wait_event(wq, condition); \
342 #define wait_event_interruptible(wq, condition) \
344 wait_event(wq, condition); \
348 extern void wakeup_one __P((void * chan));
349 /* only used in tests */
350 #define wake_up_process(p) \
355 /* used in couple of places */
356 static inline void sleep_on(cfs_waitq_t *waitq)
360 cfs_waitlink_init(&link);
361 cfs_waitq_add(waitq, &link);
362 cfs_waitq_wait(&link);
363 cfs_waitq_del(waitq, &link);
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)
374 #define cfs_siginitset(pmask, sigs) \
376 sigset_t __sigs = sigs & (~sigcantmask); \
380 #define cfs_siginitsetinv(pmask, sigs) \
382 sigset_t __sigs = ~(sigs | sigcantmask); \
386 #define cfs_recalc_sigpending(ut) \
388 (ut)->uu_siglist = (ut)->uu_siglist & ~(ut)->uu_sigmask;\
390 #define cfs_sigfillset(s) \
392 memset((s), -1, sizeof(sigset_t)); \
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)
398 #define SIGNAL_MASK_ASSERT()
404 typedef struct cfs_timer {
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);
415 cfs_time_t cfs_timer_deadline(struct cfs_timer *t);
419 * We don't need to copy out everything in osx
421 #define cfs_ioctl_data_out(a, d, l) \
425 assert((l) >= sizeof(*d)); \
426 __size = (l) - sizeof(*d); \
428 __rc = copy_to_user((void *)a + __size, \
429 (void *)d + __size, \
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 ? */
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)
452 #define likely(exp) (exp)
455 #define unlikely(exp) (exp)
458 #define lock_kernel() do {} while(0)
459 #define unlock_kernel() do {} while(0)
461 #define exit_mm(t) do {} while(0)
462 #define exit_files(t) do {} while(0)
464 #define CAP_SYS_ADMIN 0
465 #define capable(a) suser(current_proc()->p_ucred, &(current_proc()->p_acflag))
467 #define USERMODEHELPER(path, argv, envp) (0)
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); \
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 }; \
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__ ; \
483 kern_return_t name##_start(kmod_info_t *ki, void *d) \
488 kern_return_t name##_stop(kmod_info_t *ki, void *d) \
491 return KERN_SUCCESS; \
495 * to allow semicolon after cfs_module(...) \
497 struct __dummy_ ## name ## _struct {}
499 #define inter_module_get(n) cfs_symbol_get(n)
500 #define inter_module_put(n) cfs_symbol_put(n)
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)
516 #define KERNEL_VERSION(a,b,c) ((a)*100+(b)*10+c)
517 #define LINUX_VERSION_CODE (2*200+5*10+0)
520 #define in_interrupt() (0)
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 */
531 static inline long PTR_ERR(const void *ptr)
536 #define ERR_PTR(err) ((void *)err)
539 #define IS_ERR(p) (0)
544 #define EBADR EBADRPC
545 #define ERESTARTSYS ERESTART
546 #define EDEADLOCK EDEADLK
548 #define ENODATA EINVAL
551 #define __WORDSIZE 32
552 #endif /* __KERNEL__ */
554 #endif /* __LINUX__ */