The course that gives CMU its Zip! Concurrency II: Synchronization Nov 14, 2000

Similar documents
Programming with Threads Dec 7, 2009"

! What is the memory model for threads? ! How are variables mapped to memory instances? ! How many threads reference each of these instances?

for (i = 0; i < 2; i++)

Shared Variables in Threaded C Programs. Systemprogrammering Föreläsning 11 Programming with Threads

Synchronization April 29, 2008

Carnegie Mellon. Bryant and O Hallaron, Computer Systems: A Programmer s Perspective, Third Edition

Synchronization: Basics

Synchronization: Basics

Programming with Threads

Today. Threads review Sharing Mutual exclusion Semaphores

Carnegie Mellon Synchronization: Advanced

Lecture #24 Synchronization

Carnegie Mellon Concurrency and Synchronization

Process Synchroniza/on

Synchronization: Advanced

Carnegie Mellon. Synchroniza+on : Introduc+on to Computer Systems Recita+on 14: November 25, Pra+k Shah (pcshah) Sec+on C

Synchronization Mechanisms

Multithreading Programming II

Synchronization and Semaphores. Copyright : University of Illinois CS 241 Staff 1

Locks and semaphores. Johan Montelius KTH

Locks and semaphores. Johan Montelius KTH

CSC 1600: Chapter 6. Synchronizing Threads. Semaphores " Review: Multi-Threaded Processes"

CS 153 Lab6. Kishore Kumar Pusukuri

recap, what s the problem Locks and semaphores Total Store Order Peterson s algorithm Johan Montelius 0 0 a = 1 b = 1 read b read a

Synchronization and Semaphores. Copyright : University of Illinois CS 241 Staff 1

Ricardo Rocha. Department of Computer Science Faculty of Sciences University of Porto

Real Time Operating Systems and Middleware

Concurrency. Alan L. Cox Some slides adapted from CMU slides

Process Synchronization(2)

Threads. Jo, Heeseung

Condition Variables CS 241. Prof. Brighten Godfrey. March 16, University of Illinois

Process Synchronization(2)

The course that gives CMU its Zip! Concurrency I: Threads April 10, 2001

Concurrent Server Design Multiple- vs. Single-Thread

Faculté Polytechnique

Synchronization II. Today. ! Condition Variables! Semaphores! Monitors! and some classical problems Next time. ! Deadlocks

Network Programming TDC 561

Synchronization Primitives

POSIX Threads. Paolo Burgio

CS 220: Introduction to Parallel Computing. Condition Variables. Lecture 24

Process Synchronization(2)

In class we examined the need for concurrent execution paths like a consumer and a producer to synchronize their access to a shared ring buffer.

Data Races and Deadlocks! (or The Dangers of Threading) CS449 Fall 2017

real time operating systems course

Parallel Programming with Threads

Week 3. Locks & Semaphores

Introduction to parallel computing

Posix Threads (Pthreads)

CSci 4061 Introduction to Operating Systems. Synchronization Basics: Locks

CS-345 Operating Systems. Tutorial 2: Grocer-Client Threads, Shared Memory, Synchronization

POSIX Threads. HUJI Spring 2011

Programming in Parallel COMP755

Resource Access Control (2) Real-Time and Embedded Systems (M) Lecture 14

Threads. Jo, Heeseung

Process Synchronization (Part I)

Condition Variables. Dongkun Shin, SKKU

Note: The following (with modifications) is adapted from Silberschatz (our course textbook), Project: Producer-Consumer Problem.

CS 470 Spring Mike Lam, Professor. Semaphores and Conditions

Warm-up question (CS 261 review) What is the primary difference between processes and threads from a developer s perspective?

Synchronization II. q Condition Variables q Semaphores and monitors q Some classical problems q Next time: Deadlocks

Programming RT systems with pthreads

Introduction to PThreads and Basic Synchronization

Process Synchronization. studykorner.org

Condition Variables. Dongkun Shin, SKKU

Process Synchronization

Introduction to Threads

PRINCIPLES OF OPERATING SYSTEMS

Concurrency, Parallel and Distributed

Lecture 4. Threads vs. Processes. fork() Threads. Pthreads. Threads in C. Thread Programming January 21, 2005

Threads need to synchronize their activities to effectively interact. This includes:

Programming RT systems with pthreads

Shared Memory Programming Models III

Lecture 9: Thread Synchronizations. Spring 2016 Jason Tang

KING FAHD UNIVERSITY OF PETROLEUM & MINERALS. Information and Computer Science Department. ICS 431 Operating Systems. Lab # 9.

Pre-lab #2 tutorial. ECE 254 Operating Systems and Systems Programming. May 24, 2012

Paralleland Distributed Programming. Concurrency

Concurrency, Thread. Dongkun Shin, SKKU

ANSI/IEEE POSIX Standard Thread management

Sistemi in tempo reale Anno accademico

Final Examination (Fall 2016) (Section 1)

Lecture Outline. CS 5523 Operating Systems: Concurrency and Synchronization. a = 0; b = 0; // Initial state Thread 1. Objectives.

Concurrent Programming

HPCSE - I. «Introduction to multithreading» Panos Hadjidoukas

TCSS 422: OPERATING SYSTEMS

Parallel Programming Languages COMP360

Threading and Synchronization. Fahd Albinali

CS3733: Operating Systems

Pthreads. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

CSC Systems Programming Fall Lecture - XIV Concurrent Programming. Tevfik Ko!ar. Louisiana State University. November 2nd, 2010

CS 3723 Operating Systems: Final Review

Thread. Disclaimer: some slides are adopted from the book authors slides with permission 1

W4118 Operating Systems. Instructor: Junfeng Yang

Synchronization. CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han

High Performance Computing Lecture 21. Matthew Jacob Indian Institute of Science

Operating Systems CMPSC 473. Synchronization February 26, Lecture 12 Instructor: Trent Jaeger

COSC 6374 Parallel Computation. Shared memory programming with POSIX Threads. Edgar Gabriel. Fall References

Real Time Operating System Support for Concurrency

Operating Systems. Thread Synchronization Primitives. Thomas Ropars.

20-EECE-4029 Operating Systems Fall, 2015 John Franco

Concurrent Programming

Transcription:

5-3 The course that gives CMU its Zip! Concurrency II: Synchronization Nov 4, 000 Topics Progress graphs Semaphores Mutex and condition variables Barrier synchronization Timeout waiting

A version of badcnt.c with a simple counter loop int ctr = 0; /* shared */ /* main routine creates*/ /* two count threads */ /* count thread */ void *count(void *arg) { int i; for (i=0; i<niters; i++) ctr++; return NULL; note: counter should be equal to 00,000,000 linux> badcnt BOOM! ctr=988483 linux> badcnt BOOM! ctr=98680 linux> badcnt BOOM! ctr=986967 What went wrong?

Assembly code for counter loop C code for counter loop for (i=0; i<niters; i++) ctr++; Head (H i ) Load ctr (L i ) Update ctr (U i ) Store ctr (S i ) Tail (T i ).L9:.L:.L:.L0: Corresponding asm code (gcc -O0 -fforce-mem) movl -4(%ebp),%eax cmpl $99999999,%eax jle.l jmp.l0 movl ctr,%eax # Load leal (%eax),%edx # Update movl %edx,ctr # Store movl -4(%ebp),%eax leal (%eax),%edx movl %edx,-4(%ebp) jmp.l9 3

Concurrent execution Key thread idea: In general, any sequentially consistent interleaving is possible, but some are incorrect! I i denotes that thread i executes instruction I %eax i is the contents of %eax in thread i s context i (thread) instr i %eax %eax ctr H L U S H L U S T T - 0 - - - - - - - - - - - 0 0 0 OK 4

Concurrent execution (cont) Incorrect ordering: two threads increment the counter, but the result is instead of. i (thread) instr i ctr H L U H L S T U S T %eax %eax - - 0 - - - - - 0 - - - - - 0 0 0 0 0 Oops! 5

Concurrent execution (cont) How about this ordering? i (thread) instr i ctr %eax %eax H L H L U S U S T T We can clarify our understanding of concurrent execution with the help of the progress graph 6

Progress graphs Thread T A progress graph depicts the discrete execution state space of concurrent threads. S (L, S ) Each axis corresponds to the sequential order of instructions in a thread. U L Each point corresponds to a possible execution state (Inst, Inst ). H (O,O) H L U S T Thread E.g., (L, S ) denotes state where thread has completed L and thread has completed S. 7

Legal state transitions Interleaved concurrent execution (one processor): or Parallel concurrent execution (multiple processors) or or (parallel execution) Key point: Always reason about concurrent threads as if each thread had its own CPU. 8

Trajectories Thread T S U L A trajectory is a sequence of legal state transitions that describes one possible concurrent execution of the threads. Example: H, L, U, H, L, S, T, U, S, T H (O,O) H L U S T Thread 9

Critical sections and unsafe regions critical section wrt shared variable ctr Thread T S U L H Unsafe region L, U, and S form a critical section with respect to the shared variable ctr. Instructions in critical sections (wrt to some shared variable) should not be interleaved. Sets of states where such interleaving occurs form unsafe regions. (O,O) H L U S T Thread critical section wrt shared variable ctr 0

Safe trajectories critical section Thread T S U L Unsafe region Def: A safe trajectory is a sequence of legal transitions that does not touch any states in an unsafe region. Claim: Any safe trajectory results in a correct value for the shared variable ctr. H (O,O) H L U S T critical section Thread

Unsafe trajectories critical section Thread T S U L Touching a state of type x is always incorrect. Touching a state of type y may or may not be OK: Unsafe region y y y correct because store completes before load. x x x x y y incorrect because order of load and store are indeterminate. H (O,O) H L U S T Thread critical section Moral: be conservative and disallow all unsafe trajectories.

Semaphore operations Question: How can we guarantee a safe trajectory? We must synchronize the threads so that they never enter an unsafe state. Classic solution: Dijkstra's P and V operations on semaphores. semaphore: non-negative integer synchronization variable. P(s): [ while (s == 0) wait(); s--; ] Dutch for "Proberen" (test) V(s): [ s++; ] Dutch for "Verhogen" (increment) OS guarantees that operations between brackets [ ] are executed indivisibly. Only one P or V operation at a time can modify s. When while loop in P terminates, only that P can decrement s. Semaphore invariant: (s >= 0) 3

Sharing with semaphores Thread T V(s) ctr++; P(s) H s = s = 0 s = s = 0 s = s = - (forbidden region) s = 0 s = 0 s = (O,O) H P(s) ctr++; V(s) T Thread Initially, s = Provide mutually exclusive access to shared variable by surrounding critical section with P and V operations on semaphore s (initially set to ). Semaphore invariant creates a forbidden region that encloses unsafe region and is never touched by any trajectory. Semaphore used in this way is often called a mutex (mutual exclusion). 4

Posix semaphores /* initialize semaphore sem to value */ /* pshared=0 if thread, pshared= if process */ void Sem_init(sem_t *sem, int pshared, unsigned int value) { if (sem_init(sem, pshared, value) < 0) unix_error("sem_init"); /* P operation on semaphore sem */ void P(sem_t *sem) { if (sem_wait(sem)) unix_error("p"); /* V operation on semaphore sem */ void V(sem_t *sem) { if (sem_post(sem)) unix_error("v"); 5

Sharing with Posix semaphores /* goodcnt.c - properly synch'd */ /* version of badcnt.c */ #include <ics.h> #define NITERS 0000000 void *count(void *arg); struct { int ctr; /* shared ctr */ sem_t mutex; /* semaphore */ shared; /* counter thread */ void *count(void *arg) { int i; for (i=0; i<niters; i++) { P(&shared.mutex); shared.ctr++; V(&shared.mutex); return NULL; int main() { pthread_t tid, tid; /* init mutex semaphore to */ Sem_init(&shared.mutex, 0, ); /* create ctr threads and wait */... 6

Progress graph for goodcnt.c Thread V(m) P(m) f.r. V(m) P(m) f.r. V(m) P(m) f.r. P(m) V(m) P(m) V(m) P(m) V(m) Thread Initially, mutex = 7

Deadlock Thread V(s) V(t) P(s) P(t) forbidden region for s deadlock region forbidden region for t deadlock state Semaphores introduce the potential for deadlock: waiting for a condition that will never be true. Any trajectory that enters the deadlock region will eventually reach the deadlock state, waiting for either s or t to become nonzero. Other trajectories luck out and skirt the deadlock region. P(s) Initially, s=t= P(t) V(s) V(t) Thread Unfortunate fact: deadlock is often non-deterministic. 8

A deterministic deadlock Thread V(t) P(t) V(s) P(s) f.r. for s deadlock state f.r. for t deadlock region... f.r. for t... Sometimes though, we get "lucky" and the deadlock is deterministic. Here is an example of a deterministic deadlock caused by improperly initializing semaphore t. Problem: correct this program and draw the resulting forbidden regions. P(s) V(s) Initially, s =, t = 0. P(t) V(t) Thread 9

Signaling with semaphores producer thread shared buffer consumer thread Common synchronization pattern: Producer waits for slot, inserts item in buffer, and signals consumer. Consumer waits for item, removes it from buffer, and signals producer. Examples Multimedia processing: producer creates MPEG video frames, consumer renders the frames Graphical user interfaces producer detects mouse clicks, mouse movements, and keyboard hits and inserts corresponding events in buffer. consumer retrieves events from buffer and paints the display. 0

Producer-consumer (-buffer) /* buf.c - producer-consumer on -element buffer */ #include <ics.h> #define NITERS 5 void *producer(void *arg); void *consumer(void *arg); struct { int buf; /* shared var */ sem_t full; /* sems */ sem_t empty; shared; int main() { pthread_t tid_producer; pthread_t tid_consumer; /* initialize the semaphores */ Sem_init(&shared.empty, 0, ); Sem_init(&shared.full, 0, 0); /* create threads and wait */ Pthread_create(&tid_producer, NULL, producer, NULL); Pthread_create(&tid_consumer, NULL, consumer, NULL); Pthread_join(tid_producer, NULL); Pthread_join(tid_consumer, NULL); exit(0);

Producer-consumer (cont) Initially: empty =, full = 0. /* producer thread */ void *producer(void *arg) { int i, item; for (i=0; i<niters; i++) { /* produce item */ item = i; printf("produced %d\n", item); /* consumer thread */ void *consumer(void *arg) { int i, item; for (i=0; i<niters; i++) { /* read item from buf */ P(&shared.full); item = shared.buf; V(&shared.empty); /* write item to buf */ P(&shared.empty); shared.buf = item; V(&shared.full); return NULL; /* consume item */ printf("consumed %d\n", item); return NULL;

Producer-consumer progress graph Consumer V(e) P(f) V(e) P(f) V(e) P(f) The forbidden regions prevent the producer from writing into a full buffer. They also prevent the consumer from reading an empty buffer. Problem: Write version for n-element buffer with multiple producers and consumers. P(e) V(f) P(e) V(f) P(e) V(f) Producer Initially, empty =, full = 0. 3

Limitations of semaphores Semaphores are sound and fundamental, but they have limitations. Difficult to broadcast a signal to a group of threads. e.g., barrier synchronization: no thread returns from the barrier function until every other thread has called the barrier function. Impossible to do timeout waiting. e.g., wait for at most second for a condition to become true. For these we must use Pthreads mutex and condition variables. 4

Basic operations on mutex variables int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr) Initializes a mutex variable (mutex) with some attributes (attr). attributes are usually NULL. like initializing a mutex semaphore to. int pthread_mutex_lock(pthread_mutex_t *mutex) Indivisibly waits for mutex to be unlocked and then locks it. like P(mutex) int pthread_mutex_unlock(pthread_mutex_t *mutex) Unlocks mutex. like V(mutex) 5

Basic operations on condition variables int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr) Initializes a condition variable (cond) with some attributes (attr). attributes are usually NULL. int pthread_cond_signal(pthread_cond_t *cond) Awakens one thread waiting on condition cond. if no threads waiting on condition, then it does nothing. key point: signals are not queued! int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) Indivisibly unlocks mutex and waits for signal on condition cond When awakened, indivisibly locks mutex. 6

Advanced operations on condition variables int pthread_cond_broadcast(pthread_cond_t *cond) Awakens all threads waiting on condition cond. if no threads waiting on condition, then it does nothing. int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *abstime) Waits for condition cond until absolute wall clock time is abstime Unlocks mutex on entry, locks mutex on awakening. Use of absolute time rather than relative time is strange. 7

Signaling and waiting on conditions Basic pattern for signaling Pthread_mutex_lock(&mutex); Pthread_cond_signal(&cond); Pthread_mutex_unlock(&mutex); Basic pattern for waiting Pthread_mutex_lock(&mutex); Pthread_cond_wait(&cond, &mutex); Pthread_mutex_unlock(&mutex); A mutex is always associated with a condition variable. Guarantees that the condition cannot be signaled (and thus ignored) in the interval when the waiter locks the mutex and waits on the condition. 8

#include <ics.h> static pthread_mutex_t mutex; static pthread_cond_t cond; static int nthreads; static int barriercnt = 0; void barrier_init(int n) { nthreads = n; Pthread_mutex_init(&mutex, NULL); Pthread_cond_init(&cond, NULL); void barrier() { Pthread_mutex_lock(&mutex); if (++barriercnt == nthreads) { barriercnt = 0; Pthread_cond_broadcast(&cond); else Pthread_cond_wait(&cond, &mutex); Pthread_mutex_unlock(&mutex); Barrier synchronization Call to barrier will not return until every other thread has also called barrier. Needed for tightlycoupled parallel applications that proceed in phases. E.g., physical simulations. 9

timebomb.c: timeout waiting example A program that explodes unless the user hits a key within 5 seconds. #include <ics.h> #define TIMEOUT 5 /* function prototypes */ void *thread(void *vargp); struct timespec *maketimeout(int secs); /* condition variable and its associated mutex */ pthread_cond_t cond; pthread_mutex_t mutex; /* thread id */ pthread_t tid; 30

timebomb.c (cont) A routine for building a timeout structure for pthread_cond_timewait. /* * maketimeout - builds a timeout object that times out * in secs seconds */ struct timespec *maketimeout(int secs) { struct timeval now; struct timespec *tp = (struct timespec *)malloc(sizeof(struct timespec)); gettimeofday(&now, NULL); tp->tv_sec = now.tv_sec + secs; tp->tv_nsec = now.tv_usec * 000; return tp; 3

int main() { int i, rc; Main routine for timebomb.c /* initialize the mutex and condition variable */ Pthread_cond_init(&cond, NULL); Pthread_mutex_init(&mutex, NULL); /* start getchar thread and wait for it to timeout */ Pthread_mutex_lock(&mutex); Pthread_create(&tid, NULL, thread, NULL); for (i=0; i<timeout; i++) { printf("beep\n"); rc = pthread_cond_timedwait(&cond, &mutex, maketimeout()); if (rc!= ETIMEDOUT) { printf("whew!\n"); exit(0); printf("boom!\n"); exit(0); 3

Thread routine for timebomb.c /* * thread - executes getchar in a separate thread */ void *thread(void *vargp) { (void) getchar(); Pthread_mutex_lock(&mutex); Pthread_cond_signal(&cond); Pthread_mutex_unlock(&mutex); return NULL; 33

Threads summary Threads provide another mechanism for writing concurrent programs. Threads are growing in popularity Somewhat cheaper than processes. Easy to share data between threads. However, the ease of sharing has a cost: Easy to introduce subtle synchronization errors. For more info: man pages (man -k pthreads) D. Butenhof, Programming with Posix Threads, Addison-Wesley, 997. 34