Update for October 2012:
Synchronization constructs allow for concurrent processes to operate correctly. The kernel provides semaphores as a synchronization primitive. Some programming languages have support for a more usable form of synchronization called monitors. This project will use kernel level semaphores to implement user level monitors.
To give a head-start, I provide an example of a new kernel system call. It provides access to a single (globally defined) semaphore. The system call has two arguments. The first is an operation, the second is a mid, a monitor ID. In this example, the mid isn't used, and the operation codes are for semaphore operations, not monitor operations.
Your code will implement mid's, and monitor operations. First we experiment with semaphores.
A semaphore system call was implemented. This code is in subversion. Find it in the class account, under the proj5 subdirectory.
================================================ === /usr/src/linux-2.6.26.2/kernel/sched.c ===== ================================================ /* static DECLARE_MUTEX(my_monitor) ; */ static DEFINE_SEMAPHORE(my_monitor) ; /* see http://lwn.net/Articles/304725/ */ #define MONITOR_DOWN 0 #define MONITOR_UP 1 #define MONITOR_REACQUIRE 2 SYSCALL_DEFINE2(monitor, int, action, int, mid) { int result ; printk( KERN_DEBUG "sys_monitor: entered") ; switch(action){ case MONITOR_DOWN: printk( KERN_DEBUG "sys_monitor: action 0") ; result = down_interruptible(&my_monitor) ; break ; case MONITOR_UP: printk( KERN_DEBUG "sys_monitor: action 1") ; up(&my_monitor) ; break ; case MONITOR_REACQUIRE: printk( KERN_DEBUG "sys_monitor: action 2") ; up(&my_monitor) ; /*yield() ;*/ /* unnneeded, Linux implements fairness */ result = down_interruptible(&my_monitor) ; break ; default: printk( KERN_DEBUG "sys_monitor: unknown action") ; } return 0 ; }
The experiments use the following user codes:
================================================ ============== monitortest-up.c ================ ================================================ #include<stdio.h> #include<stdlib.h> #include<unistd.h> #define __NR_monitor 31 #define MONITOR_DOWN 0 #define MONITOR_UP 1 int main(int argc, char * argv[]) { printf("calling up on monitor ...") ; syscall(__NR_monitor, MONITOR_UP) ; printf("done.\n") ; return 0 ; } ================================================ ============ monitortest-down.c ================ ================================================ #include<stdio.h> #include<stdlib.h> #include<unistd.h> #define __NR_monitor 31 #define MONITOR_DOWN 0 #define MONITOR_UP 1 int main(int argc, char * argv[]) { printf("calling down on monitor ...") ; syscall(__NR_monitor, MONITOR_DOWN) ; printf("done.\n") ; return 0 ; } ================================================ ============= monitortest-reacq.c ============== ================================================ #include<stdio.h> #include<stdlib.h> #include<unistd.h> #define __NR_monitor 31 #define MONITOR_DOWN 0 #define MONITOR_UP 1 #define MONITOR_REACQUIRE 2 int main(int argc, char * argv[]) { int i ; printf("calling up on monitor ...") ; syscall(__NR_monitor, MONITOR_DOWN) ; printf("in monitor\n") ; // in monitor for (i=0;i<10;i++) { // leave and reenter monitor syscall(__NR_monitor, MONITOR_REACQUIRE) ; printf("in monitor i=%d\n",i) ; sleep(3) ; } syscall(__NR_monitor, MONITOR_UP) ; // leave monitor printf("done.\n") ; return 0 ; }
These experiments use monitortest-down and monitortest-up in two separate shells to experiment with the semaphore.
The project is to use semaphores to implement a monitor as a kernel API. You will add two system calls, monitor_create which takes a single argument and monitor_op which takes two arguments.
In designing your monitor, consider:
To get this project up and running, here is a sample solution to creating a monitor with semaphores. It uses two semaphores: one to lock the critical sections of the code, and another to implement the wait queue.
// solution to monitor project // burt rosenberg, oct 2010 // updated: oct 2011 // REMEMBER THIS IS PSEUDO-CODE! semaphore lock_sema semaphore wait_sema integer wait_count init: lock_sema unlocked (1) wait_sema locked (0) wait_count = 0 enter: assume: not holding lock_sema down on lock_sema leave: assume: holding lock_sema up on lock_sema wait: assume: holding lock_sema // increment must be atomic wait_count++ up on lock_sema // no critical race because wait_count // registers interest in waiting down on wait_sema // contend to reenter down on lock_sema notify: assume: holding lock_sema // if and decrement must be atomic to be SMP safe if wait_count>0 wait_count-- up on wait_sema //*let waiting thread run //*up on lock_sema //*down on lock_sema notify_all: assume: holding lock_sema while wait_count>0 wait_count-- up on wait_sema //*up on lock_sema //*down on lock_sema The wait_count++ and -- have to be done in a critical section to make the increment/decrement atomic. Also, the check of the wait_count and the decrement have to be in the critical section to prevent two thread both finding wait_count positive (but say equal to one) both doing the decrement (leaving wait_count negative). I do place the wait_count++ under the lock so that there is not a race between the decision to wait and the test by notify of wait_count of process intending to wait The lines marked //* were commented out to make this a Mesa style monitor
Once you get this up and running, use your monitor. Implement a solution to the Producer-Consumer problem; implement a solution to the Dining-Philosophers problem.
Helpful hints: Given the discussion in class today, let me elucidate a bit.
As Paul Erdos says: If there is a problem you can't solve, then there is an even simpler problem that you also can't solve. Find that problem.
Getting a simplified monitor to work, with a single global monitor is a simpler problem than the full monitor, with several monitors, and initialization routines that automatically dole out monitors. That is the first problem to solve.
A number of people are having trouble with the macros. Mostly this is just struggling with C. I think a review of static, of structures, and so on, by reading H&S would be very helpful. There are a lot of misconceptions about structures, static, arrays, and so forth.
Forget you ever knew them and read H&S.