Process synchronization: Barrier

Due date:

Friday 5/13/2004 by 5:00 am.

Background Material

Project Description

In this project, you will create a basic synchronization mechanism called the “barrier.”

Project Requirements

Mandatory Components:

--Design and code system calls (barrier_create and barrier join) that implements dynamically many barriers with timeouts.

--Write a user-space program that tests the functionality of barrier_create. This program should also create a stub for your new system call function.

--Write an application program to test the synchronization mechanism. It should test both the normal operation of the barrier as well as the case where a timeout occurs.


Challenge Components (all are optional):

--Support private/restricted barriers (e.g. only children of the creating pid can join)

--Add some other system calls to get info about a barrier (e.g. The number of procs it's waiting for, how many are currently waiting, the pids of those waiting, what pid created it, etc.)


Submission Requirements:

Be sure to include a README file with the following:

* Both lab partner's names, email addresses, and ID numbers.

* A brief write-up describing your approach and details about your implementation, including which of the required challenge problems you choose.

* The status of the implementation, any known drawbacks, any unimplemented features, etc. This one is especially important and should match the behavior I see when testing the code.

* Discuss any additional features you implemented

Write this in a file in plain text, HTML, or PDF format. DO NOT submit MS WORD DOCS!


Project Specifications:

Part A: Barrier Create

Design and implement a new system call function, barrier_create. The function should have the following prototype:


   int barrier_create( int num_processes, long timeout);

   Returns: Barrier number on success, -1 on failure.
       Errors include: EINVAL if num_processes is 0 or negative.
       ENOMEM if too many barriers already exist.

Write a user-space program to test barrier_create. The program should also create a stub for your new system call function.

Part B: Barrier synchronization

Design and implement a new kernel synchronization primitive that will allow multiple processes to block at the “barrier”. When the number of processes blocked at the barrier is equal to the number of processes specified by num_processes in “barrier_create”, all blocked processes that are unblocked. Implement the following system call in addition to the one in Part A.

    int barrier_join(int barrier_number);

    Returns: 0 if the process resumed due to the barrier meeting the threshold, 1 if the process resumed due to timeout timeout, -1 on failure.
    Errors include: EINVAL if barrier_number is < 0.
        ENOENT if no barrier named barrier_number exists.

    CHALLENGE PROBLEM ONLY: EPERM if current process can't join this barrier. 

In addition, processes will only remain blocked for the “timeout” period that is specified in the barrier_create system call. This period is measured from the time that the first process arrives at the barrier. On reaching the timeout period, if processes are still blocked, all processes should be unblocked.

Each barrier is used only one time. When the processes at a barrier are released, the barrier must be destroyed, and the corresponding memory freed. Further calls to barrier_join with that barrier id should return -1 and set errno to ENOENT.

Write an application program to test the synchronization mechanism. It should test both the normal operation as well as the case where the timeout occurs.

Attacking the problem

Part A: Kernel compilation

Basics

For the people working in the lab, DO NOT modify the original source tree. The directory /usr/src/linux-cs111 has been created and everybody has been given R/W access to. Create a directory there for your source tree, and chmod it to disallow any read access to everybody else. Make sure you keep a copy of your modified files on your SEASnet home directory. DO NOT use your SEASnet home directory for the full source tree, they will be very unhappy with us.

Pre-Build steps

# make clean (if you want to clean the code)

# make oldconfig

# make


Installing the kernel

You will not be able to boot the machine up if you overwrite it with your kernel and your kernel has an error in it.

/usr/src/linux-$version/arch/i386/boot/bzImage.

$mkinitrd /boot/initrd-$yourversion /lib/modules/$kernel-version



Additional Seasnet details

Part B: Adding a System Call.

.data
ENTRY(sys_call_table)
         .long sys_restart_syscall   /* 0 - old "setup()" system call*/
         .long sys_exit
         .long sys_fork
         .long sys_read
         .long sys_write
         .long sys_open          /* 5 */
         .long sys_close
         .long sys_waitpid
                        .
                        .
                        .
         .long sys_tgkill        /* 270 */
         .long sys_utimes
         .long sys_fadvise64_64
         .long sys_ni_syscall    /* sys_vserver */
         .long   sys_barrier_create   /*  cs111 project 2 */


 	/*
	 * This file contains the system call numbers.
 	*/
	 #define __NR_restart_syscall      0
	 #define __NR_exit                 1
	 #define __NR_fork                 2
	 #define __NR_read                 3
                                        .
                        		.
                        		.
	 #define __NR_tgkill             270
	 #define __NR_utimes             271
	 #define __NR_fadvise64_64       272
 	 #define __NR_vserver            273
	 #define __NR_barrier_create     274


 	 #define NR_syscalls 275   // remember to change this number

asmlinkage int sys_barrier_create(int num_processes, long timeout);

asmlinkage int sys_barrier_join(int num_processes);


printk(KERN_WARNING "This is how we use printk!!\n");


Part C: Useful calls for Barrier Synchronization

void interruptible_sleep_on( struct wait_queue **p)
{
     		SLEEP_ON_VAR

     		current-state = TASK_INTERRUPTIBLE;
     		SLEEP_ON_HEAD
     		schedule();
     		SLEEP_ON_TAIL
             }

       #define SLEEP_ON_HEAD
      		.
             __add_wait_queue ();
                .

       #define SLEEP_ON_TAIL
      		.
             __remove_wait_queue ();
      		.