Semaphores Last Time Semaphores wait n n 1

  • Slides: 14
Download presentation
Semaphores Last Time: Semaphores wait(): n = n - 1; if n < 0

Semaphores Last Time: Semaphores wait(): n = n - 1; if n < 0 then sleep() (atomic until asleep) signal(): n = n + 1; if n <= 0 then wakeup() (all atomic) Today: More on Semaphores 159. 302 1

What does the value of a semaphore mean? For a semaphore s with value

What does the value of a semaphore mean? For a semaphore s with value n If n is positive then its value is: The number of wakeups that have been performed on s with out sleeps is n If n is negative then its value is: The number of threads sleeping on s is -n 159. 302 2

What are the main uses of semaphores? Two main uses For mutual exclusion For

What are the main uses of semaphores? Two main uses For mutual exclusion For communication mutex=create(1); . . wait(mutex) Critical section signal(mutex). . . ready=create(0); . . Thread 1: wait(ready). . Thread 2: signal(ready). . 159. 302 3

Semaphores in Windows? Create: HANDLE Create. Semaphore(NULL(security attribs), long initval, long maxcount(MAXLONG), char *name(NULL));

Semaphores in Windows? Create: HANDLE Create. Semaphore(NULL(security attribs), long initval, long maxcount(MAXLONG), char *name(NULL)); Wait: Wait. For. Single. Object(HANDLE h, DWORD timeout(maxlong)); Signal: Release. Semaphore(handle h, long inccount(1), long * prevcount(NULL)); 159. 302 4

Some useful definitions #define semaphore HANDLE void wait(semaphore h) { Wait. For. Single. Object(

Some useful definitions #define semaphore HANDLE void wait(semaphore h) { Wait. For. Single. Object( h, MAXLONG); } void signal(semaphore h) { Release. Semaphore(h, 1, NULL); } semaphore create(int v) { return Create. Semaphore(NULL, (long)v, MAXLONG, NULL); } 159. 302 5

Producer-Consumer int global; // used to hold number being sent semaphore sendsem, receivesem; //

Producer-Consumer int global; // used to hold number being sent semaphore sendsem, receivesem; // for communication int main() { unsigned long id; sendsem=create(0); // initialise to zero receivesem=create(0); Create. Thread(NULL, 0, producer, 0, 0, &id); Create. Thread(NULL, 0, consumer, NULL, 0, &id); Sleep(100000); return 0; } 159. 302 6

Producer-Consumer unsigned long CALLBACK consumer(void *s) { int val; while(1) { wait(sendsem); // wait

Producer-Consumer unsigned long CALLBACK consumer(void *s) { int val; while(1) { wait(sendsem); // wait till producer has made something val=global; // get it signal(receivesem); // say we have got it printf("t%04 dn", val); fflush(stdout); } } unsigned long CALLBACK producer(void *s) { int val; while(1) { val=rand()%1000+1000*(int)s; // make something global=val; // put it somewhere the consumer can see it printf("%04 dn", val); fflush(stdout); signal(sendsem); // say we have made it wait(receivesem); // wait till consumer has got it } } 159. 302 7

Is this OK? This will work for one producer but not for many producers.

Is this OK? This will work for one producer but not for many producers. While the producer is waiting for the consumer it could be producing. Solution: use a lock instead of receivesem A lock is a semaphore initialised to 1 and used to control access to a global variable. 159. 302 8

New Main int global; // used to hold number being sent semaphore sendsem, lock;

New Main int global; // used to hold number being sent semaphore sendsem, lock; // for communication int main() { unsigned long id; sendsem=create(0); // initialise to zero lock=create(1); Create. Thread(NULL, 0, producer, 0, 0, &id); Create. Thread(NULL, 0, consumer, NULL, 0, &id); Sleep(100000); return 0; } 159. 302 9

New Producer-Consumer unsigned long CALLBACK consumer(void *s) { int val; while(1) { wait(sendsem); //

New Producer-Consumer unsigned long CALLBACK consumer(void *s) { int val; while(1) { wait(sendsem); // wait till producer has made something val=global; // get it signal(lock); // release the lock printf("t%04 dn", val); fflush(stdout); } } unsigned long CALLBACK producer(void *s) { int val; while(1) { val=rand()%1000+1000*(int)s; // make something wait(lock); // get the lock global=val; // put val somewhere the consumer can see it printf("%04 dn", val); fflush(stdout); signal(sendsem); // say we have made it } } 159. 302 10

Can we use semaphores for Producer Consumer with a buffer? Yes (also called the

Can we use semaphores for Producer Consumer with a buffer? Yes (also called the bounded buffer problem) use two semaphores thingsinbuffer – initialised to zero spaceinbuffer – initialised to the buffer size The consumer waits on thingsinbuffer and signals spaceinbuffer after it has consumed. The producer waits on spaceinbuffer and signals thingsinbuffer after it has produced. 159. 302 11

Main int buffer[N]; int in=0, out=0; int count=0; semaphore thingsinbuffer, spaceinbuffer, mutex; int main()

Main int buffer[N]; int in=0, out=0; int count=0; semaphore thingsinbuffer, spaceinbuffer, mutex; int main() { unsigned long id; thingsinbuffer=create(0); spaceinbuffer=create(N); mutex=create(1); Create. Thread(NULL, 0, producer, 0, 0, &id); Create. Thread(NULL, 0, consumer, NULL, 0, &id); Sleep(100000); return 0; } 159. 302 12

Producer unsigned long CALLBACK producer(void * s) { int val; } while(1) { val=rand()%1000;

Producer unsigned long CALLBACK producer(void * s) { int val; } while(1) { val=rand()%1000; Sleep(25); wait(spaceinbuffer); // wait for space in the buffer wait(mutex); buffer[in]=val; in=(in+1)%N; // critical section count=count+1; signal(mutex); signal(thingsinbuffer); // say there are things in the buffer } 159. 302 13

Consumer unsigned long CALLBACK consumer(void * s) { int val; while(1) { wait(thingsinbuffer); //

Consumer unsigned long CALLBACK consumer(void * s) { int val; while(1) { wait(thingsinbuffer); // wait till something in buffer wait(mutex); val=buffer[out]; out=(out+1)%N; // critical section count=count-1; signal(mutex); signal(spaceinbuffer); // say there is space in the buffer Sleep(20); wait(mutex); printf("%4 d %d %dn", val, count, (in-out+N)%N); signal(mutex); } } 159. 302 14