1 / 24

Process Synchronization

Process Synchronization. COS 431 Fall, 2000. process A. process B. numStudents = 3. Joe. 0 1 2 3 4 5. Mary. interrupt. interrupt. Zelda. Students[num] = “Joey”;. Henry. Joey. Students[num] = “Henry”;. Students. Coordination of Processes.

yaakov
Télécharger la présentation

Process Synchronization

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Process Synchronization COS 431 Fall, 2000

  2. process A process B numStudents = 3 Joe 0 1 2 3 4 5 Mary interrupt interrupt Zelda Students[num] = “Joey”; Henry Joey Students[num] = “Henry”; Students Coordination of Processes • Often, processes need to synchronize their activities • sharing resources • when cooperating • Unfortunately, processes are asynchronous by nature • Without some means of synchronization: race condition num = numStudents; num = numStudents; num++; numStudents = num; num++; numStudents = num;

  3. Critical Sections/Regions • Solution: mutual exclusion • Critical regions (critical sections) • Criteria for solution to race conditions: • mutual exclusion • make no assumption about speed, num. CPUs • no process outside its critical region can block another • no starvation

  4. A Naïve Approach: Disable Interrupts • One CPU, if process can disable all interrupts, can guarantee no race conditions • have to disable interrupts from I/O • have to disable timer interrupts • Problem: • too much power for user process -- usurps kernel’s power • if anything goes wrong -- may hang entire computer! • doesn’t work for multiple CPUs • Kernel needs the ability to do this, though • In some multithreaded applications, this can be used (e.g., Lisp)

  5. Another Simple Approach: Locks • Use a single shared variable as a lock • Could also be a shared file • Process looks at variable -- if 0, busy waits, if not set to 0 • Problems • May not be atomic • Processes may cheat • Some processors have special instructions (TSL) that help this out, though

  6. Turn-Taking: Strict Alternation • Idea: …non-critical section… while (turn != my-turn) ; /* busy wait */ critical_section(); turn = next_turn(turn); …non-critical section… • What if one of the processes is faster than the others? • What if a process is I/O bound? • Processes block others when not in its critical region

  7. Turn-Taking: Alternation with Interest(Peterson’s Solution) • Idea -- process declares its interest before it tries for critical region • Other processes that are interested block if it’s not their turn and if someone else who is interested is in critical section • If only one process ready… • If two processes ready, one in its critical section… • Two processes both simultaneously call enter_region... #define FALSE 0 #define TRUE 1 #define N 2 /* num processes */ int turn int interested[N]; void enter_region(int process) { int other; other = 1 - process; interested[process] = TRUE; turn = process; while (turn == process && interested[other] == TRUE); } void leave_region(int process) { interested[process] = FALSE; }

  8. “Bakery” Algorithm • For multiple processes • Every process that wants to enter critical section given a number • Lowest number goes first • Can’t guarantee that two won’t have same number… • …in that case, use tie-breaking convention BOOLEAN choosing[MAXPROC]; /* picking number or not */ int number[MAXPROC]; /* each element corresponds to a process */ void enter(i) { choosing[i] = TRUE; /* we’re picking a number */ number[i] = find_max(number) + 1; /* select next highest number */ choosing[i] = FALSE; /* done */ for (j=0; j<n; j++) { while (choosing[j]) ; /* busy wait if something is choosing number */ /* busy wait till lower proc. with lower number is done */ while ( (number[j] != 0) && customer_lt(j,i) ); } } void leave(i) { number[i] = 0; } • What if just one process...? • What if n, with one in critical region...? • What if n try to enter critical region at same time...?

  9. Hardware Support for Synchronization • Locks don’t work in general: • atomicity • multiple processors? • Some processors : test-and-set-lock (TSL) instruction • When TSL executed: • locks memory bus • then: • sets a register to the value of some memory location (the lock) • sets the lock to a value meaning “locked” (e.g., 1) • then unlocks the memory bus • Why does this work?

  10. Mutual Exclusion Using TSL enter: tsl r1,LOCK ! check LOCK cmp r1,#0 ! compare old value to 0 jnz enter ! if not zero, then it was locked, ! so loop ret ! otherwise, return leave: mov LOCK,#0 ! just clear the lock ret

  11. What’s Wrong with Busy Waiting? • Wastes processor time • Priority inversion problem • Example: • Processes busy wait when can’t enter critical region • H: high-priority job • L: low-priority job • Policy: always run high-priority jobs when possible • Scenario: • H: waiting on I/O • L: runs, enters critical region • H: I/O completes - context switch to H • H: tries to enter its critical region • What does H do? • What does L do?

  12. Better Idea: Blocking • Make process not runnable instead of busy waiting • How is this done? • When does the process wake up? • Traditional example: the bounded buffer problem • Buffer: storage area with n slots • One process is a producer • Other is a consumer • Buffer full: producer blocks • Buffer empty: consumer • Example: queues • Relies on producer waking consumer and vice versa

  13. Producer/Consumer Problem #define N 100 int count 0; int buffer[N]; pid_t producer, consumer; void producer() { int item; while (TRUE) { item = produce_item(); if (count == N) sleep(); enter_item(item); count++; if (count == 1) wakeup(consumer); } } void consumer() { int item; if (count == 0) sleep(); item = remove_item(); count--; if (count == N-1) wakeup(producer); consume_item(item); } } void consume_item(int item) { printf(“item=%d\n”,item); } int produce_item() { int item; printf(“\nNext item? “); scanf(“%d”,&item); return(item); }

  14. Problems with Sleep/Wakeup • Signals can be lost due to timing • producer sees buffer full, but interrupted before sleep • consumer takes something from buffer, sends signal -- which is lost • producer goes to sleep • consumer continues taking stuff out, ultimately ==> sleeps • both are sleeping! • Can add some machinery to kernel -- bit in PCB, e.g. -- tells when signal is waiting • But with > 2 processes, need more bits for the processes ==> arbitrary number of bits needed

  15. Semaphores • Motivation: problems with blocking • Idea: • standard way to block processes • data structure (semaphores) + two functions defined on them • Semaphores: • enforce mutual exclusion • can be used for producer-consumer problems • Data structure: essentially just an integer -- say, S • Operations: • P(S) -- also known as Down(S) -- decrement S • V(S) -- also known as Up(S) -- increment S • Down(S) and S=0: block caller. • Up(S) and process blocked on S => unblock it • Down and Up have to be atomic ==> system calls

  16. Semaphores • One way to implement: typedef structure semaphore { int count = 1; queue procs; }; void Down(semaphore S) { S.count--; if (S.count < 0) { enqueue(current_proc(),S.procs); block(current_proc()); } } void Up(semaphore S) { process P; S.count++; if (S.count <= 0) { P = dequeue(S.queue); wakeup(P); } }

  17. Using Semaphores for Mutual Exclusion • Traditional name for mutual exclusion semaphore is mutex • Example from the student roster program before: int num_students; int roster[MAXSTUDENTS]; semaphore mutex; ... void add_student(int id) { int currno; Down(mutex); /* critical region starts here */ currno = num_students; roster[currno] = id; currno++; num_students = currno; /* end critical region */ Up(mutex); return; } ...

  18. Semaphores and Bounded Buffers • Single-bounded buffer • Ex: a print queue • Something else (we won’t worry about what right now) takes items out of the queue • What if the queue is full? • What if the queue is empty? • Semaphores needed: • mutex - a binary semaphore • empty - • counts empty slots • initialized to number of slots in queue

  19. Print Queue Example filename buffer[SLOTS]; int next_slot = 0; semaphore mutex, empty; set_count(empty,SLOTS); /* would really be set by daemon */ ... void print_file(filename file) { Down(empty); Down(mutex); /* within critical region now */ buffer[next_slot] = file; next_slot++; Up(mutex); } • Why is there no Up(empty)? • What if buffer is empty? • What if buffer is full?

  20. Producer/Consumer Problems and Semaphores • Complete bounded buffer problem • Ex.: Message queue: • process A writes to it • process B reads from it • limited size • Synchronization problem? • Solution uses three semaphores: • mutex, a binary semaphore • empty: a counting semaphore -- keeps track of empty slots • full: a counting semaphore -- keeps track of full slots

  21. Producer/Consumer message buffer[BUFFSIZE]; semaphore empty, full, mutex; set_count(empty,BUFFSIZE); set_count(full,0); void producer() { message msg; while (TRUE) { msg = compose_message(); Down(empty); Down(mutex); /* critical region */ put_message(buffer,msg); /* end critical region */ Up(mutex); Up(full); } } void consumer() { message msg; while (TRUE) { Down(full); Down(mutex); /* critical region */ msg = get_message(buffer); /* end critical region */ Up(mutex); Up(empty); use_message(msg); } }

  22. Common Problems When Using Semaphores • Careful not to get carried way with mutex calls! Don’t: void fcn1() { Down(mutex); fcn2(); Up(mutex); } void fcn2() { Down(mutex); ... Up(mutex); }

  23. T S 1 1 0 0 -1 blocked -1 blocked Problems Using Semaphores • Careful not to cross semaphore calls: P1: Down(S); Down(T); ... Up(T); Up(S); • P2: • Down(T); • Down(S); • ... • Up(S); • Up(T);

  24. Semaphores in Unix • POSIX-compliant Unix: • sem_t is the semaphore type • sem_wait ==> Down • sem_post ==> Up • Used for threads (or processes, if shared) • Some Unix systems: only allocate arrays of semaphores • semget -- creates a set of semaphores as shared memory objects, or returns an identifier for such a set • semop--perform operations on the semaphore set

More Related