Synchronization I q Race condition, critical regions q Locks and concurrent data structures q Next time: Condition variables, semaphores and monitors

Similar documents
Synchronization I. To do

Synchronization I. Today. Next time. Monitors. ! Race condition, critical regions and locks. ! Condition variables, semaphores and

Synchronization I. Today. Next time. Race condition, critical regions and locks. Condition variables, semaphores and Monitors

Concurrency: Mutual Exclusion (Locks)

Locks. Dongkun Shin, SKKU

Concurrency: Locks. Announcements

CS 537 Lecture 11 Locks

C09: Process Synchronization

SYNCHRONIZATION M O D E R N O P E R A T I N G S Y S T E M S R E A D 2. 3 E X C E P T A N D S P R I N G 2018

Synchronization I. Jo, Heeseung

CSE 451: Operating Systems Winter Lecture 7 Synchronization. Steve Gribble. Synchronization. Threads cooperate in multithreaded programs

10/17/ Gribble, Lazowska, Levy, Zahorjan 2. 10/17/ Gribble, Lazowska, Levy, Zahorjan 4

Operating System Labs. Yuanbin Wu

Systèmes d Exploitation Avancés

PROCESS SYNCHRONIZATION

Lock-based Concurrent Data Structures

18-642: Race Conditions

Operating Systems. Synchronization

CSE 451: Operating Systems Winter Lecture 7 Synchronization. Hank Levy 412 Sieg Hall

CS420: Operating Systems. Process Synchronization

[537] Locks and Condition Variables. Tyler Harter

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

Lock-based Concurrent Data Structures

OPERATING SYSTEMS DESIGN AND IMPLEMENTATION Third Edition ANDREW S. TANENBAUM ALBERT S. WOODHULL. Chap. 2.2 Interprocess Communication

Synchronization I. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

Synchronization. CS61, Lecture 18. Prof. Stephen Chong November 3, 2011

CS 111. Operating Systems Peter Reiher

Operating Systems. Lecture 4 - Concurrency and Synchronization. Master of Computer Science PUF - Hồ Chí Minh 2016/2017

Multiprocessors and Locking

28. Locks. Operating System: Three Easy Pieces

Chapter 6 Process Synchronization

Section I Section Real Time Systems. Processes. 1.4 Inter-Processes Communication (part 1)

Chapter 5: Process Synchronization. Operating System Concepts 9 th Edition

CMSC421: Principles of Operating Systems

Today: Synchronization. Recap: Synchronization

Locks and semaphores. Johan Montelius KTH

Concurrency, Thread. Dongkun Shin, SKKU

Operating Systems. Designed and Presented by Dr. Ayman Elshenawy Elsefy

CS 153 Design of Operating Systems Winter 2016

Chapter 5: Process Synchronization. Operating System Concepts 9 th Edition

Lesson 6: Process Synchronization

Synchronization Spinlocks - Semaphores

Locks and semaphores. Johan Montelius KTH

250P: Computer Systems Architecture. Lecture 14: Synchronization. Anton Burtsev March, 2019

Dealing with Issues for Interprocess Communication

Chapter 5: Process Synchronization. Operating System Concepts Essentials 2 nd Edition

Implementing Locks. Nima Honarmand (Based on slides by Prof. Andrea Arpaci-Dusseau)

Last Class: CPU Scheduling! Adjusting Priorities in MLFQ!

Chapter 6: Process Synchronization

As an example, assume our critical section looks like this, the canonical update of a shared variable:

Microkernel/OS and Real-Time Scheduling

Synchronization. CSE 2431: Introduction to Operating Systems Reading: Chapter 5, [OSC] (except Section 5.10)

Lecture 5: Synchronization w/locks

CHAPTER 6: PROCESS SYNCHRONIZATION

Chapter 6: Process Synchronization

Chapter 6: Process Synchronization

Implementing Mutual Exclusion. Sarah Diesburg Operating Systems CS 3430

Process/Thread Synchronization

CS 111. Operating Systems Peter Reiher

Introduction to Embedded Systems

Review: Easy Piece 1

Chapter 6: Synchronization. Chapter 6: Synchronization. 6.1 Background. Part Three - Process Coordination. Consumer. Producer. 6.

CS533 Concepts of Operating Systems. Jonathan Walpole

Lecture #7: Implementing Mutual Exclusion

IV. Process Synchronisation

Introduction to OS Synchronization MOS 2.3

Threading and Synchronization. Fahd Albinali

CSE 4/521 Introduction to Operating Systems

Threads. Concurrency. What it is. Lecture Notes Week 2. Figure 1: Multi-Threading. Figure 2: Multi-Threading

Process/Thread Synchronization

Operating Systems. Thread Synchronization Primitives. Thomas Ropars.

Synchronization Principles I

Dept. of CSE, York Univ. 1

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

Process Coordination and Shared Data

Verification of Real-Time Systems Resource Sharing

Chapter 6: Synchronization. Operating System Concepts 8 th Edition,

Synchronization Principles

Operating Systems. Synchronisation Part I

CS5460/6460: Operating Systems. Lecture 11: Locking. Anton Burtsev February, 2014

PROCESSES & THREADS. Charles Abzug, Ph.D. Department of Computer Science James Madison University Harrisonburg, VA Charles Abzug

ECE 574 Cluster Computing Lecture 8

CS370 Operating Systems

Multiprocessor Systems. COMP s1

POSIX / System Programming

[537] Locks. Tyler Harter

Operating Systems CMPSCI 377 Spring Mark Corner University of Massachusetts Amherst

Advanced Threads & Monitor-Style Programming 1/24

Resource management. Real-Time Systems. Resource management. Resource management

CSE 451 Midterm 1. Name:

CMSC421: Principles of Operating Systems

Why We Wait. IPC, Threads, Races, Critical Sections. Correct Ordering. Approaches to Waiting. Condition Variables 4/23/2018

Page 1. Challenges" Concurrency" CS162 Operating Systems and Systems Programming Lecture 4. Synchronization, Atomic operations, Locks"

Goals. Processes and Threads. Concurrency Issues. Concurrency. Interlacing Processes. Abstracting a Process

Multiprocessor System. Multiprocessor Systems. Bus Based UMA. Types of Multiprocessors (MPs) Cache Consistency. Bus Based UMA. Chapter 8, 8.

Administrivia. Review: Thread package API. Program B. Program A. Program C. Correct answers. Please ask questions on Google group

Chapter 6: Process Synchronization. Operating System Concepts 8 th Edition,

Background. The Critical-Section Problem Synchronisation Hardware Inefficient Spinning Semaphores Semaphore Examples Scheduling.

Threads Tuesday, September 28, :37 AM

Multiprocessor Systems. Chapter 8, 8.1

Transcription:

Synchronization I q Race condition, critical regions q Locks and concurrent data structures q Next time: Condition variables, semaphores and monitors

Cooperating processes and threads Cooperating processes need to communicate They can affect/be affected by others Issues with Inter-Process Communication (IPC) 1. How to pass information to another process? 2. avoid getting in each other s ways? 3. ensure proper sequencing given dependencies? Process A produces data that B prints B must wait for A to print How about threads? 1. Easy 2 & 3. Pretty much the same 2

Accessing shared resources A common example print spooler To print a file, a thread puts file name in a spooler directory Each entry a file name in and out pointing to next free slot and next file to print Printer daemon thread periodically checks directory, prints whatever file is there, removes the name next_slot:= in; // in = 4 spooler_dir[next_slot] := file_name; // insert abc in++; Spooler directory 3 4 5 6 7 8 zzz abc Out: 3 In: 45 3

Accessing shared resources Assume preemptive scheduling Two threads, A & B, trying to print A: next_slot A in % 7 A: spooler_dir[next_slot A ] file_name A Switch A: in next_slot A + 1 % 8 B: next_slot B in % 8 Spooler directory B: spooler_dir[next_slot B ] file_name B B: in next_slot B + 1 % 9 Process A 4 5 6 abc filex taxes Out: 4 In: 7 7 fnama 8 fnamb Process B 4

Interleaved schedules Problem the execution of the two threads/processes can be interleaved Some times the result of interleaving is OK, others Switch Switch Switch A: next_slot A in % 7 A: B: spooler_dir[next_slot B in A ] % file_name 7 A A: B: in spooler_dir[next_slot next_slot A + 1 B ] file_name % 8 B B: in next_slot B in B + 1 % 8 % 8 B: A: spooler_dir[next_slot B A ] file_name BA B: A: in next_slot B A + 1 % 89 B s printout?! Process A Process B Spooler directory 4 5 6 7 8 abc filea taxes fnamb fnama Out: 4 In: 7 In: 8 5

Interleaved schedule another example next 1 struct list { 2 int data; 3 struct list *next; 4 ; 5 6 struct list *list = 0; 7 8 void 9 insert(int data) 10 { 11 struct list *l; 12 13 l = malloc(sizeof *l); 14 l->data = data; 15 l->next = list; 16 list = l; 17 l list l list list next Two threads A and B, what would happen if B executes line 15 before A executes 16? 6

Invariants and critical regions Problem threads operating on the data assume certain conditions (invariants) to hold For the linked list list points to the head of the list each element s next point to the next element Insert temporarily violates this, but fixes it before finishing True for a single thread, not for two concurrent ones Need a way to ensure invariant conditions hold when thread is going to manipulate a share item 7

Critical regions and mutual exclusion Code region where the invariants are temporarily violated Critical Region if a thread is using a shared item, i.e., in the CR, others should be excluded from doing it Mutual exclusion 8 void 9 insert(int data) 10 { 11 struct list *l; 12 13 l = malloc(sizeof *l); 14 l->data = data; 15 l->next = list; 16 list = l; 17 8

Requirements for a solution 1. Mutual exclusion At most one thread in CR at once, anyone! 2. No assumptions on speeds or num. of CPUs 3. Progress No thread outside its CR can block another 4. Bounded waiting (no starvation) No thread should wait forever to enter its CR, should eventually be let in Safety the program never enters a bad state Liveness eventually enters a good state 9

Race conditions and critical regions Race condition Two+ threads/processes in CR at once Accessing (r/w) shared data Final results depends on order of execution Some tools try to detect them helgrind http://valgrind.org/docs/manual/hg-manual.html Need mechanisms to prevent race conditions, synchronize access to shared resources 10

Locks A memory object with two operations lock()/acquire(): if available, take it else wait until you have it unlock()/release(): if threads are waiting, they will (eventually) find out (or be told) Using locks Threads check lock when entering CR, free it after Lock is either available (free) or acquired lock()/acquire() doesn t return until the caller owns it Can hold other information, e.g., which thread holds the lock, queue of lock requests 11

Locks lock_t mutex; void insert(int data) { struct list *l; lock(&mutex); l = malloc(sizeof *l); l->data = data; l->next = list; list = l; unlock(&mutex); lock(&mutex); l = malloc(sizeof *l); l->data = data; lock(&mutex); l->data = data; l->next = list; list = l; unlock(&mutex); l = malloc(sizeof *l); l->data = data; l->next = list; list = l; unlock(&mutex); 12

Pthreads locks In the POSIX library, a lock is called a mutex pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; void insert(int data) { struct list *l; Pthread_mutex_lock(&lock); /* a wrapper that checks for errors */ l = malloc(sizeof *l);... Pthread_mutex_unlock(&lock); Note the call passes a variable to lock/unlock For fine-grain locking (instead of a single coarse lock) Locks must be initialized before used, either this way or dynamically with pthread_mutex_init(&lock, NULL) 13

Lock-based concurrent data structures Making data structures thread-safe, i.e., usable by threads Two concerns correctness, obviously And performance A non-concurrent counter typedef struct counter_t { int value; counter_t; void init(counter_t *c) { c->value = 0; void increment(counter_t *c) { c->value++; void decrement(counter_t *c) { c->value--; 14

Lock-based concurrent data structures A concurrent version typedef struct counter_t { int value; pthread_lock_t lock; counter_t; void init(counter_t *c) { c->value = 0; pthread_mutex_init(&c->lock, NULL); void increment(counter_t *c) { pthread_mutex_lock(&c->lock); c->value++; pthread_mutex_unlock(&c->lock); void decrement(counter_t *c) { pthread_mutex_lock(&c->lock); c->value--; pthread_mutex_unlock(&c->lock); Not very scalable; a better option with sloppy counters S. Boyd-Wickizer et al., An analysis of Linux Scalability to Many Cores, OSDI 2010 15

Lock-based concurrent data structures A first concurrent list (part of, actually) typedef struct node_t { int key; struct node_t *next; node_t; typedef struct list_t { node_t *head; pthread_mutex_t lock; list_t; void List_Init(list_t *L) { L->head = NULL; pthread_mutex_init(&l->lock, NULL); int List_Insert(list_t *L, int key) { pthread_mutex_lock(&l->lock); node_t *new = malloc(sizeof(node_t)); if (new == NULL) { perror( malloc ); pthread_mutex_unlock(&l->lock); return -1; /* failure */ new->key = key; new->next = L->head; L->head = new; pthread_mutex_unlock(&l->lock); return 0; /* success */ int List_Lookup(list_t *L, int key) { pthread_mutex_lock(&l->lock); node_t *current = L->head; while(curr) { if (curr->key == key) { pthread_mutex_unlock(&l->lock); return 0; /* success */ curr = curr->next; pthread_mutex_unlock(&l->lock); return -1; /* failure */ Can we simplify this to avoid releasing the lock on the failure path? Very coarse locking; what s your critical section? 16

Lock-based concurrent data structures And some improvements int List_Insert(list_t *L, int key) { pthread_mutex_lock(&l->lock); node_t *new = malloc(sizeof(node_t)); if (new == NULL) { perror( malloc ); pthread_mutex_unlock(&l->lock); return -1; /* failure */ new->key = key; new->next = L->head; L->head = new; pthread_mutex_unlock(&l->lock); return 0; /* success */ int List_Lookup(list_t *L, int key) { pthread_mutex_lock(&l->lock); node_t *current = L->head; while(curr) { if (curr->key == key) { pthread_mutex_unlock(&l->lock); return 0; /* success */ curr = curr->next; pthread_mutex_unlock(&l->lock); return -1; /* failure */ int List_Insert(list_t *L, int key) { node_t *new = malloc(sizeof(node_t)); if (new == NULL) { perror( malloc ); Just lock the return -1; /* failure */ critical section new->key = key; pthread_mutex_lock(&l->lock); new->next = L->head; L->head = new; pthread_mutex_unlock(&l->lock); return 0; /* success */ int List_Lookup(list_t *L, int key) { int rv = -1; pthread_mutex_lock(&l->lock); node_t *current = L->head; while (curr) { if (curr->key == key) { rv = 0; A single return path, break; /* success */ to avoid potential bugs curr = curr->next; pthread_mutex_unlock(&l->lock); return rv; 17

And now a short break xkcd 18

Implementing locks (spinlocks) One attempt 1 void 2 lock(lock *lk) 3 { 4 while(lk->locked == 1) 5 ; /* spin-wait */ 6 lk->locked = 1; /* now set it */ 7 Context switch here and there we go again Are we done? No yet! Correctness problem: Both can concurrently test 4, see it unlocked, and grab it; now both are in the CR Continuously testing a variable for a given value is called busy waiting; a lock that uses this is a spin lock spin waiting is wasteful 19

Implementing locks hardware to help Disabling interrupts Simplest solution threads disables all interrupts when entering the CR and re-enables them at exit void lock() { DisableInterrupts(); void unlock() { EnableInterrupts(); Why does it work? No interrupts no clock interrupts no other process getting in your way 20

Implementing locks Problems with disabling interrupts Users in control grabs the CPU to never return So only available to the kernel What about multiprocessors? Each has its own interrupt mechanism And yes, it s also inefficient Useful to build higher-level constructs 21

TSL(test&set) -based solution Atomically test & modify a word TSL CPU executing the TSL locks memory bus to stop other CPUs from accessing memory until it is done In SPARC is ldstub (load & store), in x86 is xchg int TSL(int *ptr, int new) { int old = *ptr; /* fetch old value at ptr */ *ptr = new; /*store new value into ptr */ return old; Done atomically 22

TSL(test&set) -based solution Entering and leaving CR How about our requirements? Mutual exclusion Progress Bounded waiting Performance typedef struct lock_t { int flag; lock_t; void init(lock_t *loc) { lock->flag = 0; void lock(lock_t *lock) { while (TSL(&lock->flag, 1) == 1) ; /* spin-wait */ void unlock(lock_t *lock) { lock->flag = 0; 23

Busy waiting and priority inversion Problems with TSL-based approach? Waste CPU by busy waiting Can lead to priority inversion Two threads, H (high-priority) & L (low-priority) L gets into its CR H is ready to run and starts busy waiting L is never scheduled while H is running So L never leaves its critical region and H loops forever! Welcome to Mars! 24

Problems in the Mars Pathfinder* Mars Pathfinder Launched Dec. 4, 1996, landed July 4 th, 1997 Problem Periodically the system reset itself, loosing data Pathfinder software architecture An information bus with access controlled by a lock A bus management (B) high-priority thread A meteorological (M) low-priority, short-running thread If B thread was scheduled while M thread was holding the lock, B busy waited on the lock A communication (C) thread running with medium priority B (high) M (low) *As explained by D. Wilner, CTO of Wind River Systems, and narrated by Mike Jones Information bus C (medium) 25

Problems in the Mars Pathfinder* B (high) M (low) Information bus Sometimes, B (high-priority) was waiting on M (low priority) and C (medium priority) was scheduled After a bit of waiting, a watchdog timer would reset the system J How would you fix it? C (medium) Priority inheritance the M thread inherits the priority of the B thread blocked on it Actually supported by VxWork but disabled! 26

Yield rather than spin void lock(lock_t *lock) { while (TSL(&lock->flag, 1) == 1) ; /* spin-wait */ Too much spinning Two threads, first one gets the lock and is interrupted Second one wants the lock and has to wait... wait... wait Now the first one runs, frees the lock A whole time slices wasted 27

Yield rather than spin An alternative just yield void lock(lock_t *lock) { while (TSL(&lock->flag, 1) == 1) yield(); /* give up the CPU */ Better than spinning but What about the context switching cost? Imagine not one but 10s other threads, all getting scheduled just to yield Is there a chance of starvation? A thread caught in an endless yield loop Can we get some control with a queue of threads? Next lecture 28

Coming up Other mechanisms for synchronization Condition variables Semaphores slightly higher abstractions Monitors much better but need language support 29