/* waitQ.c * * Bug: I gotta actually create the waitQ object. How do I do that? * Here I just declare the variable but don't create the object. * * This third version uses one kernel wait queue as I presume * it is intended to be used. The code is straight from sleep_on * and wake_up in sched.h and sched.c but without the macros * so the code is easier to directly see. * * I still don't get the flags argument in the locking calls or * the specific intent of locking with irq save and restore. * * Derived from mod-syscall-242 sample system code illustrating * how to add system calls using a kernel module. * System calls use printk for debugging messages. * System calls here only pass and return simple stack values. * so copy_to_user, copy_from_user are not needed. * * Derived from the no-parameter or result hello-1 example in the * Linux Kernel Module Programmer's Guide for 2.4 Kernel. * * Uses existing unused syscall entries in the sys_call_table. * eventWait is sched_setaffinity 241 * eventSig is sched_getaffinity 242 * * Include file locations * is /usr/src/linux/include/linux * is /usr/src/linux/include/asm * is /usr/include/sys * * Source file locations * sys_call_table[] /usr/src/linux/arch/i386/kernel/entry.S */ /* kernel module programming */ #ifndef MODULE #define MODULE #endif #ifndef LINUX #define LINUX #endif #ifndef __KERNEL__ #define __KERNEL__ #endif #define MAX_BUF 80 #include /* needed by all modules */ #include /* for KERN_ALERT */ #include /* for __NR_futex & other system call numbers */ #include /* current, wake_up_process, schedule, TASK_UNIN and all the locking stuff */ /* The kernel will fill in the call table at dynamic load (insmod) */ extern void *sys_call_table[]; /* prototypes */ asmlinkage int my_eventSig_syscall(void); asmlinkage int my_eventWait_syscall(void); int init_module(void); void cleanup_module(void); /* Wait Queue data structure * where the heck is this macro? */ /* wait_queue_head_t my_waitQ; */ static DECLARE_WAIT_QUEUE_HEAD(my_waitQ); /* My event signal system call */ asmlinkage int my_eventSig_syscall(void) { printk(KERN_ALERT "my_eventSig_syscall: entering.\n"); wake_up(&my_waitQ); printk(KERN_ALERT "my_eventSig_syscall: leaving.\n"); return 0; } /* My event wait system call */ asmlinkage int my_eventWait_syscall(void) { printk(KERN_ALERT "my_eventWait_syscall: entering.\n"); sleep_on(&my_waitQ); printk(KERN_ALERT "my_eventWait_syscall: leaving after waking up from block.\n"); return 0; } /* Original system call for NR_sched_setaffinity sys.c of src/linux/kernel */ asmlinkage long (*original_call_241) (void); /* Original system call for NR_sched_getaffinity sys.c of src/linux/kernel */ asmlinkage long (*original_call_242) (void); /* Initialize the module at insmod - insert the new system calls */ int init_module(void) { printk(KERN_ALERT "waitOne module loaded\n"); /* save the original syscall entry and insert our own entry */ original_call_241 = sys_call_table[__NR_sched_setaffinity]; original_call_242 = sys_call_table[__NR_sched_getaffinity]; sys_call_table[__NR_sched_setaffinity] = my_eventWait_syscall; sys_call_table[__NR_sched_getaffinity] = my_eventSig_syscall; /* A non-zero return means init_module failed; module can't be loaded */ return 0; } /* Restore the preious system calls at rmmod. * Check to see if someone else tried to replace our * system calls while we were loaded. */ void cleanup_module(void) { if ( sys_call_table[__NR_sched_setaffinity] != my_eventWait_syscall || sys_call_table[__NR_sched_getaffinity] != my_eventSig_syscall) { printk(KERN_ALERT "syscall module entry has been corrupted\n"); } /* restore the original syscall entries */ sys_call_table[__NR_sched_setaffinity] = original_call_241; sys_call_table[__NR_sched_getaffinity] = original_call_242; printk(KERN_ALERT "waitOne module unloaded\n"); } MODULE_LICENSE("GPL");