Xinu Semaphore & Mutex

2016, Sep 11    

Xinu Semaphore API

  • each semaphore has a count:
    • initial count when created
    • current count during use(held in a kernel var)
  • sid32 semid = semcreate(int inicount); //Xinu syscall
  • sid32 wait(semid): decrement sem’s count, blocks the callers(caller waits) if new count < 0 a process “blocks”(only happens via OS action) meaning it waits without using CPU(OS runs other process)
  • sid32 signal(semid): increment sem’s count, allow one blocked process to run (if any waiters)
  • sid32 count = semcount(semid): get semaphore’s current count
  • sid32 status = delete(semid)

Mutex is easy

  • sid32 mutex = semcreate(1)
  • sid32 wait(mutex) //acquire lock
  • sid32 signal(mutex) //release lock

Producer & consumer example

/* prodcons.c - main, prod2, cons2, with N spots in shared buffer  */
#include <stdio.h>
#define N 10
/* Note that this simple queue is meant to be used with semaphores--
 * on its own, it doesn't know if it's empty or full!  Both cases
 * have head == tail.  One semaphore is enough to keep track of this.
 * Two semaphores are needed for control of both producer and consumer.
 */
int a[N];  /* shared buffer */
int head, tail; /* for buffer used as queue */
void prod2(int consumed, int produced, int mutex);
void cons2(int consumed, int produced, int mutex);
 
/*--------------------------------------------------------------------------
 *    main --  producer and consumer process synchronized with semaphores
 *--------------------------------------------------------------------------
*/
void main(void)
{
  int produced, consumed, mutex;
 
  consumed = screate(N);        /* scount = number of empty spots in buffer */
  produced = screate(0);        /* scount = number of filled spots in buffer */
  mutex = screate(1);
  head = tail = 0;              /* initialize buffer as queue */
  resume( create(cons2, 1000, 20, "cons", 3, consumed, produced, mutex));
  resume( create(prod2, 1000, 20, "prod", 3, consumed, produced, mutex));
}
 
/*----------------------------------------------------------------------------
 *    prod2   --  increment n 200 times, waiting for space in buffer
 *----------------------------------------------------------------------------
 */
void prod2(int consumed, int produced, int mutex)
{
    int i, n = 0;
 
    for( i=1; i<=200; i++ )  {
        wait(consumed);
        n++;                    /* "produce" another number */
        wait(mutex);
        a[head++] = n;          /* enqueue(n) */
        if (head >= N)          /* ... */
            head = 0;           /* ... */
        signal(mutex);
        signal(produced);
    }
}
 
/*----------------------------------------------------------------------------
 *  cons2 -- print 200 times, waiting as needed for some numbers to be produced
 *----------------------------------------------------------------------------
 */
void cons2(int consumed, int produced, int mutex)
{
    int i, n;
 
    for( i=1;  i<=200; i++ )  {
        wait(produced);
        wait(mutex);
        n = a[tail++];          /* n = dequeue() */
        if (tail >= N)          /* ... */
            tail = 0;           /* ... */
        signal(mutex);
        printf("number consumed is %d \n",  n);
        signal(consumed);
    }
}