Synchronization: Basics

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

Synchronization: Basics

Carnegie Mellon Concurrency and Synchronization

Today. Threads review Sharing Mutual exclusion Semaphores

Synchronization: Advanced

Programming with Threads Dec 7, 2009"

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

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

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

Lecture #24 Synchronization

Synchronization April 29, 2008

Process Synchroniza/on

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

Concurrency on x86-64; Threads Programming Tips

CS 5523 Operating Systems: Midterm II - reivew Instructor: Dr. Tongping Liu Department Computer Science The University of Texas at San Antonio

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

CS3733: Operating Systems

Programming with Threads

CS 3723 Operating Systems: Final Review

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

Introduction to Threads

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

CS 5523: Operating Systems

CS 5523 Operating Systems: Thread and Implementation

CS Operating Systems: Threads (SGG 4)

Threads (SGG 4) Outline. Traditional Process: Single Activity. Example: A Text Editor with Multi-Activity. Instructor: Dr.

Concurrent Programming is Hard! Concurrent Programming. Reminder: Iterative Echo Server. The human mind tends to be sequential

Carnegie Mellon Synchronization: Advanced

CS 475. Process = Address space + one thread of control Concurrent program = multiple threads of control

Example. Example. Threading Language and Support. CS528 Multithreading: Programming with Threads. The boss/worker model. Thread Programming models

Concurrent Programming

Concurrent Programming

CSC 252: Computer Organization Spring 2018: Lecture 26

Computer Systems Laboratory Sungkyunkwan University

Multithreading Programming II

Approaches to Concurrency

Concurrent Programming

Process Synchronization. studykorner.org

Carnegie Mellon Performance of Mul.threaded Code

Total Score is updated. The score of PA4 will be changed! Please check it. Will be changed

Proxy: Concurrency & Caches

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

Concurrent Programming

Lecture #23 Concurrent Programming

POSIX threads CS 241. February 17, Copyright University of Illinois CS 241 Staff

Synchroniza+on II COMS W4118

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

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

Concurrent Programming

Locks and semaphores. Johan Montelius KTH

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

call connect call read call connect ret connect call fgets Client 2 blocks waiting to complete its connection request until after lunch!

Concurrent Servers Dec 2, 2009"

Concurrent Programming

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

W4118 Operating Systems. Instructor: Junfeng Yang

Programming in Parallel COMP755

Process Synchronization

CSE 306/506 Operating Systems Threads. YoungMin Kwon

CS 333 Introduction to Operating Systems. Class 3 Threads & Concurrency. Jonathan Walpole Computer Science Portland State University

CS 3305 Intro to Threads. Lecture 6

What is concurrency? Concurrency. What is parallelism? concurrency vs parallelism. Concurrency: (the illusion of) happening at the same time.

Concurrency. Johan Montelius KTH

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

Locks and semaphores. Johan Montelius KTH

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

Lecture 8: September 30

CS 471 Operating Systems. Yue Cheng. George Mason University Fall 2017

Recitation 14: Proxy Lab Part 2

Thread-Level Parallelism. Instructor: Adam C. Champion, Ph.D. CSE 2431: Introduction to Operating Systems Reading: Section 12.

CS 333 Introduction to Operating Systems. Class 3 Threads & Concurrency. Jonathan Walpole Computer Science Portland State University

CS510 Operating System Foundations. Jonathan Walpole

CS 3723 Operating Systems: Midterm II - Review

Synchroniza+on: Advanced

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

Sistemi in tempo reale Anno accademico

Dealing with Issues for Interprocess Communication

Concurrent Programming April 21, 2005

Week 3. Locks & Semaphores

Parallel Programming Languages COMP360

POSIX Semaphores. Operations on semaphores (taken from the Linux man page)

Concurrent programming

Concurrent Server Design Multiple- vs. Single-Thread

Concurrent Programming. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

ANKARA UNIVERSITY COMPUTER ENGINEERING DEPARTMENT BLM334-COM334 PROJECT

Threading Language and Support. CS528 Multithreading: Programming with Threads. Programming with Threads

CS 333 Introduction to Operating Systems Class 4 Concurrent Programming and Synchronization Primitives

Achieving Synchronization or How to Build a Semaphore

Threading and Synchronization. Fahd Albinali

Concurrent Programming

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

Lecture 5 Threads and Pthreads II

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

Concurrent Programming

IV. Process Synchronisation

CS333 Intro to Operating Systems. Jonathan Walpole

Three Basic Mechanisms for Creating Concurrent Flows. Systemprogrammering 2009 Föreläsning 10 Concurrent Servers. Process-Based Concurrent Server

Global Environment Model

Recitation 14: Proxy Lab Part 2

[537] Semaphores. Tyler Harter

Transcription:

Synchronization: Basics 53: Introduction to Computer Systems 4 th Lecture, April 8, 7 Instructor: Seth Copen Goldstein, Franz Franchetti

Today Threads review Sharing Mutual exclusion Semaphores

Traditional View of a Process Process = process context + code, data, and stack Process context Code, data, and stack Program context: Data registers Condition codes Stack pointer (SP) Program counter (PC) Kernel context: VM structures Descriptor table brk pointer SP brk PC Stack Shared libraries Runtime heap Read/write data Readonly code/data 3

Alternate View of a Process Process = thread + code, data, and kernel context Thread (main thread) Code, data, and kernel context SP Stack Thread context: Data registers Condition codes Stack pointer (SP) Program counter (PC) brk PC Shared libraries Runtime heap Read/write data Readonly code/data Kernel context: VM structures Descriptor table brk pointer 4

A Process With Multiple Threads Multiple threads can be associated with a process Each thread has its own logical control flow Each thread shares the same code, data, and kernel context Each thread has its own stack for local variables but not protected from other threads Each thread has its own thread id (TID) Thread (main thread) Thread (peer thread) Shared code and data stack Thread context: Data registers Condition codes SP PC stack Thread context: Data registers Condition codes SP PC shared libraries runtime heap read/write data readonly code/data Kernel context: VM structures Descriptor table brk pointer 5

Shared Variables in Threaded C Programs Question: Which variables in a threaded C program are shared? The answer is not as simple as global variables are shared and stack variables are private Def: A variable x is shared if and only if multiple threads reference some instance of x. Requires answers to the following questions: What is the memory model for threads? How are instances of variables mapped to memory? How many threads might reference each of these instances? 6

Threads Memory Model Conceptual model: Multiple threads run within the context of a single process Each thread has its own separate thread context Thread ID, stack, stack pointer, PC, condition codes, and GP registers All threads share the remaining process context Code, data, heap, and shared library segments of the process virtual address space Open files and installed handlers Operationally, this model is not strictly enforced: Register values are truly separate and protected, but Any thread can read and write the stack of any other thread The mismatch between the conceptual and operation model is a source of confusion and errors 7

Example Program to Illustrate Sharing char **ptr; /* global var */ int main(int argc, char *argv[]) { long i; pthread_t tid; char *msgs[] = { "Hello from foo", "Hello from bar" }; } ptr = msgs; for (i = ; i < ; i++) Pthread_create(&tid, NULL, thread, (void *)i); Pthread_exit(NULL); sharing.c void *thread(void *vargp) { long myid = (long)vargp; static int cnt = ; } printf("[%ld]: %s (cnt=%d)\n", myid, ptr[myid], ++cnt); return NULL; Peer threads reference main thread s stack indirectly through global ptr variable 8

Mapping Variable Instances to Memory Global variables Def: Variable declared outside of a function Virtual memory contains exactly one instance of any global variable Local variables Def: Variable declared inside function without static attribute Each thread stack contains one instance of each local variable Local static variables Def: Variable declared inside function with the static attribute Virtual memory contains exactly one instance of any local static variable. 9

Mapping Variable Instances to Memory Global var: instance (ptr [data]) Local vars: instance (i.m, msgs.m, tid.m) char **ptr; /* global var */ int main(int main, char *argv[]) { long i; pthread_t tid; char *msgs[] = { "Hello from foo", "Hello from bar" }; } ptr = msgs; for (i = ; i < ; i++) Pthread_create(&tid, NULL, thread, (void *)i); Pthread_exit(NULL); sharing.c Local var: instances ( myid.p [peer thread s stack], myid.p [peer thread s stack] ) void *thread(void *vargp) { long myid = (long)vargp; static int cnt = ; } printf("[%ld]: %s (cnt=%d)\n", myid, ptr[myid], ++cnt); return NULL; Local static var: instance (cnt [data])

Shared Variable Analysis Which variables are shared? Variable Referenced by Referenced by Referenced by instance main thread? peer thread? peer thread? ptr cnt i.m msgs.m myid.p myid.p yes yes yes no yes yes yes no no yes yes yes no yes no no no yes char **ptr; /* global */ int main(int argc, char *argv[]) { int i; pthread_t tid; char *msgs[] = { Hello from foo", } Answer: A variable x is shared iff multiple threads reference at least one instance of x. Thus: ptr, cnt, and "Hello msgs from are bar"}; shared i and myid are not shared ptr = msgs; for (i = ; i < ; i++) Pthread_create(&tid,, (void *)i); Pthread_exit(NULL); /* thread routine */ void *thread(void *vargp) { int myid = (int)vargp; static int cnt = ; } printf("[%d]: %s (cnt=%d)\n", myid, ptr[myid], ++cnt);

Shared Variable Analysis Which variables are shared? Variable Referenced by Referenced by Referenced by instance main thread? peer thread? peer thread? ptr cnt i.m msgs.m myid.p myid.p yes yes yes no yes yes yes no no yes yes yes no yes no no no yes Answer: A variable x is shared iff multiple threads reference at least one instance of x. Thus: ptr, cnt, and msgs are shared i and myid are not shared

Synchronizing Threads Shared variables are handy... but introduce the possibility of nasty synchronization errors. 3

badcnt.c: Improper Synchronization /* Global shared variable */ volatile long cnt = ; /* Counter */ int main(int argc, char **argv) { long niters; pthread_t tid, tid; } niters = atoi(argv[]); Pthread_create(&tid, NULL, thread, &niters); Pthread_create(&tid, NULL, thread, &niters); Pthread_join(tid, NULL); Pthread_join(tid, NULL); /* Check result */ if (cnt!= ( * niters)) printf("boom! cnt=%ld\n", cnt); else printf("ok cnt=%ld\n", cnt); exit(); badcnt.c /* Thread routine */ void *thread(void *vargp) { long i, niters = *((long *)vargp); } for (i = ; i < niters; i++) cnt++; return NULL; linux>./badcnt OK cnt= linux>./badcnt BOOM! cnt=35 linux> cnt should equal,. What went wrong? 4

Assembly Code for Counter Loop C code for counter loop in thread i for (i = ; i < niters; i++) cnt++; Asm code for thread i movq (%rdi), %rcx testq %rcx,%rcx jle.l movl $, %eax.l3: movq cnt(%rip),%rdx addq $, %rdx movq %rdx, cnt(%rip) addq $, %rax cmpq %rcx, %rax jne.l3.l: H i : Head L i : Load cnt U i : Update cnt S i : Store cnt T i : Tail 5

Concurrent Execution Key idea: In general, any sequentially consistent interleaving is possible, but some give an unexpected result! I i denotes that thread i executes instruction I %rdx i is the content of %rdx in thread i s context i (thread) instr i %rdx %rdx cnt H L U S H L U S T T OK 6

Concurrent Execution Key idea: In general, any sequentially consistent interleaving is possible, but some give an unexpected result! I i denotes that thread i executes instruction I %rdx i is the content of %rdx in thread i s context i (thread) instr i %rdx %rdx cnt H L U S H L U S T T OK Thread critical section Thread critical section 7

Concurrent Execution (cont) Incorrect ordering: two threads increment the counter, but the result is instead of i (thread) instr i %rdx %rdx cnt H L U H L S T U S T Oops! 8

Concurrent Execution (cont) How about this ordering? i (thread) instr i %rdx %rdx cnt H L H L U S U S T T Oops! We can analyze the behavior using a progress graph 9

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

Trajectories in Progress Graphs Thread T S U 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 L H H L U S T Thread

Trajectories in Progress Graphs Thread T S U 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 L H H L U S T Thread

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

Critical Sections and Unsafe Regions Thread safe T Def: A trajectory is safe iff it does not enter any unsafe region critical section wrt cnt S U L Unsafe region unsafe Claim: A trajectory is correct (wrt cnt) iff it is safe H H L U S T Thread critical section wrt cnt 4

badcnt.c: Improper Synchronization /* Global shared variable */ volatile long cnt = ; /* Counter */ int main(int argc, char **argv) { long niters; pthread_t tid, tid; } niters = atoi(argv[]); Pthread_create(&tid, NULL, thread, &niters); Pthread_create(&tid, NULL, thread, &niters); Pthread_join(tid, NULL); Pthread_join(tid, NULL); /* Check result */ if (cnt!= ( * niters)) printf("boom! cnt=%ld\n", cnt); else printf("ok cnt=%ld\n", cnt); exit(); badcnt.c /* Thread routine */ void *thread(void *vargp) { long i, niters = *((long *)vargp); } for (i = ; i < niters; i++) cnt++; return NULL; Variable main thread thread cnt yes* yes yes niters.m yes no no tid.m yes no no i. no yes no i. no no yes niters. no yes no niters. no no yes 5

Enforcing Mutual Exclusion Question: How can we guarantee a safe trajectory? Answer: We must synchronize the execution of the threads so that they can never have an unsafe trajectory. i.e., need to guarantee mutually exclusive access for each critical section. Classic solution: Semaphores (Edsger Dijkstra) Other approaches (out of our scope) Mutex and condition variables (Pthreads) Monitors (Java) 6

Semaphores Semaphore: nonnegative global integer synchronization variable. Manipulated by P and V operations. P(s) If s is nonzero, then decrement s by and return immediately. Test and decrement operations occur atomically (indivisibly) If s is zero, then suspend thread until s becomes nonzero and the thread is restarted by a V operation. After restarting, the P operation decrements s and returns control to the caller. V(s): Increment s by. Increment operation occurs atomically If there are any threads blocked in a P operation waiting for s to become nonzero, then restart exactly one of those threads, which then completes its P operation by decrementing s. Semaphore invariant: (s >= ) 7

Semaphores Semaphore: nonnegative global integer synchronization variable Manipulated by P and V operations: P(s): [ while (s == ) wait(); s; ] Dutch for "Proberen" (test) V(s): [ s++; ] Dutch for "Verhogen" (increment) OS kernel 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 >= ) 8

C Semaphore Operations Pthreads functions: #include <semaphore.h> int sem_init(sem_t *s,, unsigned int val);} /* s = val */ int sem_wait(sem_t *s); /* P(s) */ int sem_post(sem_t *s); /* V(s) */ CS:APP wrapper functions: #include "csapp.h void P(sem_t *s); /* Wrapper function for sem_wait */ void V(sem_t *s); /* Wrapper function for sem_post */ 9

badcnt.c: Improper Synchronization /* Global shared variable */ volatile long cnt = ; /* Counter */ int main(int argc, char **argv) { long niters; pthread_t tid, tid; niters = atoi(argv[]); Pthread_create(&tid, NULL, thread, &niters); Pthread_create(&tid, NULL, thread, &niters); Pthread_join(tid, NULL); Pthread_join(tid, NULL); /* Thread routine */ void *thread(void *vargp) { long i, niters = *((long *)vargp); } for (i = ; i < niters; i++) cnt++; return NULL; } /* Check result */ if (cnt!= ( * niters)) printf("boom! cnt=%ld\n", cnt); else printf("ok cnt=%ld\n", cnt); exit(); badcnt.c How can we fix this using semaphores? 3

Using Semaphores for Mutual Exclusion Basic idea: Associate a unique semaphore mutex, initially, with each shared variable (or related set of shared variables). Surround corresponding critical sections with P(mutex) and V(mutex) operations. Terminology: Binary semaphore: semaphore whose value is always or Mutex: binary semaphore used for mutual exclusion P operation: locking the mutex V operation: unlocking or releasing the mutex Holding a mutex: locked and not yet unlocked. Counting semaphore: used as a counter for set of available resources. 3

goodcnt.c: Proper Synchronization Define and initialize a mutex for the shared variable cnt: volatile long cnt = ; /* Counter */ sem_t mutex; /* Semaphore that protects cnt */ sem_init(&mutex,, ); /* mutex = */ Surround critical section with P and V: for (i = ; i < niters; i++) { P(&mutex); cnt++; V(&mutex); } goodcnt.c linux>./goodcnt OK cnt= linux>./goodcnt OK cnt= linux> Warning: It s orders of magnitude slower than badcnt.c. 3

goodcnt.c: Proper Synchronization Define and initialize a mutex for the shared variable cnt: volatile long cnt = ; /* Counter */ sem_t mutex; /* Semaphore that protects cnt */ sem_init(&mutex,, ); /* mutex = */ Surround critical section with P and V: OK cnt= BOOM! cnt=3655 Slowdown for (i = ; i < niters; i++) { P(&mutex); real cnt++; m.38s m.7s X user V(&mutex); m.s m.8s 5X sys } m.8s m.s goodcnt.c NaN linux>./goodcnt OK cnt= linux>./goodcnt OK cnt= linux> And slower means much slower! Warning: It s orders of magnitude slower than badcnt.c. 33

Why Mutexes Work Thread T V(s) Provide mutually exclusive access to shared variable by surrounding critical section with P and V operations on semaphore s (initially set to ) S U Unsafe region L P(s) H Initially s = H P(s) L U S V(s) T Thread 34

Why Mutexes Work Thread T V(s) Provide mutually exclusive access to shared variable by surrounding critical section with P and V operations on semaphore s (initially set to ) S U L P(s) Unsafe region Semaphore invariant creates a forbidden region that encloses unsafe region and that cannot be entered by any trajectory. H Initially s = H P(s) L U S V(s) T Thread 35

Why Mutexes Work Thread T V(s) Provide mutually exclusive access to shared variable by surrounding critical section with P and V operations on semaphore s (initially set to ) S U L Unsafe region Semaphore invariant creates a forbidden region that encloses unsafe region and that cannot be entered by any trajectory. P(s) H Initially s = H P(s) L U S V(s) T Thread 36

Why Mutexes Work Thread T V(s) S U L Forbidden region Unsafe region 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 that cannot be entered by any trajectory. P(s) H Initially H P(s) L U S V(s) T s = Thread 37

Summary Programmers need a clear model of how variables are shared by threads. Variables shared by multiple threads must be protected to ensure mutually exclusive access. Semaphores are a fundamental mechanism for enforcing mutual exclusion. 38