CPSC 351 Lecture 16 (D.H.)

Lecture 16

1. Race condition -review 2. Peterson’s solution 3. The TSL instruction 4. Sleep and Wakeup The producer-consumer problem 5. Semaphores

1. Race condition -review What is race condition ? Examples (lecture 16) Discussed solutions (lecture 16)

2. Peterson’s solution (software solution)

First software solution race condition was due to Dekker (1965). Peterson improved Dekker’s algorithm in 1981. Peterson’s algorithm p.37, fig 2-8 of text:

/ * variable turn and array interested are shared */

#define FALSE 0 #define TRUE 1 #define N 2 / * number of processes */

int turn; /* whose turn is it ? */ int interested[N]; /* All values initially 0 (FALSE) */

void enter_region (int process) /*Process who wants to enter critical section ( 0 or 1) */ { int other; /* number of the other process */

other = 1-process; /* the opposite process */ interested[process]= TRUE; /* the process is interested */ turn =process; /* set my turn */

while(turn ==process && interested[other] == TRUE); /* wait to enter critical section */ }

void leave_region(int process) /* process who is leaving critical section (0 or 1) */ { interested [process] = FALSE /* done with critical section */ }

Each process executes the following code: enter_region(my_number) critical section; leave_region(my_number);

3. The TSL instruction (hardware solution)

38 CPSC 351 Lecture 16 (D.H.)

TSL ( TEST and SET LOCK ) is a CPU instruction designed for controlling race conditions and critical sections. TSL reads the contents of a memory word into a register and then store a non-zero value at that memory location. The operations of reading the word and storing a non-zero values are indivisible (atomic) and cannot be interrupted.

Solution using TSL (p.39 fig. 2-9,of text): Variable flag is a shared memory location. If it is equal to 0 a process can enter critical section, otherwise not.

enter_region: tsl register, flag /* copy flag to register and set flag to 1 */ cmp register, #0 /* was flag = 0 ? */ jnz enter_region /* if it was non-zero, lock was set, loop */ ret /* return to caller, enter critical section */

leave region: mov flag, #0 /* store a 0 in flag */ ret

Each process executes the following code: enter_region critical section leave region

4. Sleep and Wakeup Both Peterson’s solution and TSL are correct, but require busy-waiting (a waiting process sits in a tight loop wasting CPU time). Primitives that do not require busy-waiting, because they block processes (move processes to the block state) are: Sleep and Wakeup and semaphores.

Sleep is a primitive (a system call) that causes the caller to block until another process wakes it up. Wakeup(process) is a primitive that sends a Wakeup signal to a process.

The producer-consumer problem: Two processes share a common, fixed size buffer. One of them, the producer, puts information into the buffer, and the other one, the consumer, takes it out. If the buffer is full, the producer has to be put to sleep until the consumer takes some items from the buffer. If the buffer is empty, the consumer has to be put to sleep until the producer places some items into the buffer. Producer and consumer have to share variable count (i.e. the number of items in the buffer). This might lead to a race condition. Additionally, wake up signals might be lost if a process which is waiting for a signal is not asleep yet. 5. Semaphores

39