CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 11: Thread-safe Data Structures, Semaphores.

Slides:



Advertisements
Similar presentations
Operating Systems Semaphores II
Advertisements

More on Semaphores, and Classic Synchronization Problems CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han.
Prepared By Sarath S Menon S6 CSE.  Imagine a scenario in which there exists two Distinct processes both operating on a single shared data area.  One.
EEE 435 Principles of Operating Systems Interprocess Communication Pt II (Modern Operating Systems 2.3)
Enforcing Mutual Exclusion, Semaphores. Four different approaches Hardware support Disable interrupts Special instructions Software-defined approaches.
Concurrency, Race Conditions, Mutual Exclusion, Semaphores, Monitors, Deadlocks Chapters 2 and 6 Tanenbaum’s Modern OS.
U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts Amherst Operating Systems CMPSCI 377 Lecture.
Chapter 6: Process Synchronization. 6.2 Silberschatz, Galvin and Gagne ©2005 Operating System Concepts – 7 th Edition, Feb 8, 2005 Objectives Understand.
Concurrency: Mutual Exclusion, Synchronization, Deadlock, and Starvation in Representative Operating Systems.
8-1 JMH Associates © 2004, All rights reserved Windows Application Development Chapter 10 - Supplement Introduction to Pthreads for Application Portability.
Semaphores CSCI 444/544 Operating Systems Fall 2008.
Race Conditions CS550 Operating Systems. Review So far, we have discussed Processes and Threads and talked about multithreading and MPI processes by example.
Semaphores Questions answered in this lecture: Why are semaphores necessary? How are semaphores used for mutual exclusion? How are semaphores used for.
CS 241 Section Week #4 (2/19/09). Topics This Section  SMP2 Review  SMP3 Forward  Semaphores  Problems  Recap of Classical Synchronization Problems.
CS252: Systems Programming Ninghui Li Final Exam Review.
Pthread (continue) General pthread program structure –Encapsulate parallel parts (can be almost the whole program) in functions. –Use function arguments.
Semaphores. Readings r Silbershatz: Chapter 6 Mutual Exclusion in Critical Sections.
The University of Adelaide, School of Computer Science
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 10: Threads and Thread Synchronization.
4061 Session 23 (4/10). Today Reader/Writer Locks and Semaphores Lock Files.
ICS 145B -- L. Bic1 Project: Process/Thread Synchronization Textbook: pages ICS 145B L. Bic.
CS345 Operating Systems Threads Assignment 3. Process vs. Thread process: an address space with 1 or more threads executing within that address space,
What is a thread? process: an address space with 1 or more threads executing within that address space, and the required system resources for those threads.
Copyright ©: Nahrstedt, Angrave, Abdelzaher1 Semaphore and Mutex Operations.
4061 Session 21 (4/3). Today Thread Synchronization –Condition Variables –Monitors –Read-Write Locks.
CS252: Systems Programming
Chapter 6 – Process Synchronisation (Pgs 225 – 267)
1 Pthread Programming CIS450 Winter 2003 Professor Jinhua Guo.
POSIX Synchronization Introduction to Operating Systems: Discussion Module 5.
Synchronizing Threads with Semaphores
IT 325 Operating systems Chapter6.  Threads can greatly simplify writing elegant and efficient programs.  However, there are problems when multiple.
2.3 interprocess communcation (IPC) (especially via shared memory & controlling access to it)
1 CMSC421: Principles of Operating Systems Nilanjan Banerjee Principles of Operating Systems Acknowledgments: Some of the slides are adapted from Prof.
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science Software Systems Advanced Synchronization Emery Berger and Mark Corner University.
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 12: Thread-safe Data Structures, Semaphores.
1 Synchronization Threads communicate to ensure consistency If not: race condition (non-deterministic result) Accomplished by synchronization operations.
1 Condition Variables CS 241 Prof. Brighten Godfrey March 16, 2012 University of Illinois.
Chapter 6 P-Threads. Names The naming convention for a method/function/operation is: – pthread_thing_operation(..) – Where thing is the object used (such.
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 13: Condition Variable, Read/Write Lock, and Deadlock.
Barriers and Condition Variables
PThread Synchronization. Thread Mechanisms Birrell identifies four mechanisms commonly used in threading systems –Thread creation –Mutual exclusion (mutex)
CSCI1600: Embedded and Real Time Software Lecture 17: Concurrent Programming Steven Reiss, Fall 2015.
Semaphores Reference –text: Tanenbaum ch
Working with Pthreads. Operations on Threads int pthread_create (pthread_t *thread, const pthread_attr_t *attr, void * (*routine)(void*), void* arg) Creates.
Mutual Exclusion -- Addendum. Mutual Exclusion in Critical Sections.
Web Server Architecture Client Main Thread for(j=0;j
pThread synchronization
CS 311/350/550 Semaphores. Semaphores – General Idea Allows two or more concurrent threads to coordinate through signaling/waiting Has four main operations.
Case Study: Pthread Synchronization Dr. Yingwu Zhu.
Chien-Chung Shen CIS/UD
Semaphores Reference text: Tanenbaum ch
Chapter 5: Process Synchronization – Part 3
Background on the need for Synchronization
Chapter 5: Process Synchronization – Part II
PThreads.
Principles of Operating Systems Lecture 11
Operating Systems CMPSC 473
CS252: Systems Programming
Lecture 14: Pthreads Mutex and Condition Variables
Threading And Parallel Programming Constructs
Synchronization and Semaphores
Concurrency: Mutual Exclusion and Process Synchronization
Lecture 14: Pthreads Mutex and Condition Variables
CSE 153 Design of Operating Systems Winter 19
CSE 153 Design of Operating Systems Winter 2019
CSCI1600: Embedded and Real Time Software
Semaphores Reference text: Tanenbaum ch
CS 144 Advanced C++ Programming May 7 Class Meeting
“The Little Book on Semaphores” Allen B. Downey
Lab #9 Semaphores Operating System Lab.
Presentation transcript:

CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 11: Thread-safe Data Structures, Semaphores

Pthread Overview Pthreads: POSIX threads Mutual exclusion and synchronization tools that we cover Mutex locks Spin locks Read/write locks Semaphores (not part of pthreads, but part of POSIX standards) Condition variables: Suspend the execution of a thread until some pre-defined condition occurs

Type of Mutex Locks Depends on behavior in the following 2 cases A: a thread that holds lock calls lock again B: a thread that does not hold lock calls unlock Recursive lock: A succeeds (locking n times requires unlocking n times); B returns error pthread_mutexattr_init(&Attr); pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&Mutex, &Attr); Error checking lock: returns error on A,B Normal (fast) lock: deadlock on A; undefined on B Implementation does not require remembering A,B Default lock: undefined on A,B

Which Type to Use It is recommended to use Recursive in production systems when available. When one has high confidence and full control of code, then using normal (fast) is fine i.e., when one is certain that A and B cannot occur

Behavior When Lock Blocked until the lock is available. Behavior of mutex lock Yield CPU and try to obtain lock when scheduled, return when lock is available Seems to be undesirable, since thread is off CPU, might as well wait until lock is available Busy-waiting when lock is unavailable. Behavior of SpinLock; don’t use one single CPU Return “unable to obtain lock” immediately To get this behavior in pthreads, use trylock E.g., pthread_mutex_trylock()

Threads and Fork Example: In Solaris one process creates 5 threads using thr_create and then calls fork() then the child will also have a copy of the 5 threads so we have a total of 10 threads In Solaris (or other UNIX flavors) one process creates 5 threads using pthread create and then calls fork() therefore the child will only get one thread that is the thread that called fork so we have a total of 6 threads Solaris has a system call fork1() that only copies the calling thread in the child process. Modern UNIX use the pthread_create semantics that only copies the calling thread.

Thread Safe and Race Condition Data structures and functions that are able to handle multiple threads are called “Thread Safe” or “Multi- Threaded (MT), or “Concurrent”. A Thread Unsafe function or data structure is one that when executed by multiple threads can result in logical errors. A bug related to having multiple threads modifying a data structure simultaneously is called a “Race Condition”. Race Conditions are difficult to debug because they are often difficult to reproduce.

A Thread Unsafe List Class #include struct ListEntry { int _val; ListEntry *_next; }; class List{ ListEntry *_head; public: List(); void insert(int val); int remove(); } List::List(){ _head = NULL; } List::insert(int val){ ListEntry *e = new ListEntry; e->_val = val; a) e->_next = _head; b) _head = e; }

A Thread Unsafe List Class int List::remove(){ ListEntry *tmp; c) tmp = _head; if(tmp == NULL) { return -1; } d) _head=tmp->_next; int val=tmp->_val; delete tmp; return val; }

Race Conditions in List We can have the following race condition: Assume T1 calls remove() and T2 calls insert(). Initially 1_head2 NULL

Race Conditions in List 2. T2 insert(5) 1_head T2: a) e2->next=_head NULL 1. T1 remove() 1_head2 tmp1 1. T1: c) tmp=_head NULL tmp1 3. T2 insert(5) 1_head T2: b) _head = e2 NULLtmp1 4. T1 remove() 1 _head T1: d)_head=tmp->_next; Node 5 is lost!!! tmp1NULL ctxswitch E2

Race Conditions in List Now find a race condition involving two insert. Now find a race condition involving two remove. Initially 1_head2 NULL

An Thread Safe List Class #include struct ListEntry { int _val; ListEntry *_next; }; class MTList{ ListEntry *_head; pthread_mutex_t _mutex; public: MTList(); void insert(int val); int remove(); } MTList::MTList(){ _head = NULL; pthread_mutex_init( &_mutex, NULL ); } MTList::insert(int val){ ListEntry *e = new ListEntry; e->_val = val; pthread_mutex_lock(&_mutex); a) e->_next = _head; b)_head = e; pthread_mutex_unlock(&mutex); }

A Thread Safe List int MTList::remove(){ ListEntry *tmp; pthread_mutex_lock(&_mutex); c) tmp = _head; if(tmp == NULL) { pthread_mutex_unlock(&_mutex); return -1; } d) _head=tmp->_next; pthread_mutex_unlock(&mutex); int val=tmp->_val; delete tmp; return val; }

An Additional Requirement in the List Class The MT List implementation described before returns -1 if the list is empty. Suppose that we would like an implementation where the remove waits if the List is empty. This behavior is naturally implemented using semaphores.

Semaphores Semaphores are a signaling mechanism. A semaphore is initialized with an initial counter that is greater or equal to 0. Conceptually indicating # of available resources A sem_wait call decreases the counter, and block the thread if the value is negative. A sem_post call increases the counter, and unblock one waiting thread

Semaphore Calls Declaration: #include sem_t sem; Initialization: sem_init (sem_t *sem, int pshared, unsigned int value); Decrement Semaphore: sem_wait ( sem_t *sem); Increment Semaphore sem_post (sem_t *sem); Man pages man sem_wait

Semaphore Calls Semantics Pseudocode: sem_init(sem_t *sem, counter){ sem -> count = counter; } sem_wait(sem_t *sem){ sem -> count--; if(sem ->count < 0){ wait(); }

Semaphore Calls Semantics sem_post(sem_t *sem){ sem ->count++; if(there is a thread waiting){ wake up the thread that has been waiting the longest. } // one out and can let one in } Note: The mutex lock calls are omitted in the pseudocode for simplicity.

Semaphores vs. Mutex Semaphores are a signaling mechanism; not specifically for mutual exclusion Semaphore can be initialized to any positive integer, and mutex is binary Binary semaphore vs. Mutex With mutex, only the thread holding the lock is supposed to unlock With semaphore, any thread can call sem_post to wake up a blocking thread In general, semaphore and mutex are different One can use a binary semaphore to achieve the effect of mutex, if one is careful to ensure that sem_post is only called after sem_wait succeeds

Use of Semaphore Counter Mutex Lock Case: initial counter == 1 Can achieve effect of Mutex Lock N Resources Case: initial counter is n > 1 Control access to a fixed number n of resources. Example: Access to 5 printers. 5 computers can use them. 6 th computer will need to wait. Wait for an Event Case: initial counter == 0 Synchronization. Wait for an event. A thread calling sem_wait will block until another threads sends an event by calling sem_post.

Example Semaphore count=1 (Mutex Lock Case) Assume sem_t sem; sem_init(&sem, 1); T1 T2 sem_wait(&sem) sem->count--(==0) Does not wait.. ctxswitch sem_wait(&sem) sem->count--(==-1) if (sem->count < 0) wait (ctxswitch).. sem_post(&sem) sem->count++(==0) wakeup T2 continue

Example Semaphore count=3 (N Resources Case) Assume sem_t sem; sem_init(&sem, 3); (3 printers) T1 T2 T3 sem_wait(&sem) sem->count--(==2) Does not wait print.. sem_wait(&sem) sem->count--(==1) Does not wait print.. sem_wait(&sem) sem->count--(==0) Does not wait print

Example Semaphore count=3 (N Resources Case) T4 T5 T1 sem_wait(&sem) sem->count--(==-1) wait sem_wait(&sem) sem->count--(==-2) Wait Finished printing sem_post(&sem) sem->count++(==-1) Wakeup T4 print

Example Semaphore count=0 Wait for an Event Case Assume sem_t sem; sem_init(&sem, 0); T1 T2 // wait for event sem_wait(&sem) sem->count--(==-1) wait //Send event to t1 sem_post(&sem) sem->count++(==0) Wakeup T1.. T1 continues

A Synchronized List Class We want to implement a List class where remove() will block if the list is empty. To implement this class, we will use a semaphore “_emptySem” that will be initialized with a counter of 0. Remove() will call sem_wait(&_emptySem) and it will block until insert() calls sem_post(&emptySem). The counter in semaphore will be equivalent to the number of items in the list.

A Synchronized List Class SyncList.h #include struct ListEntry { int _val; ListEntry *_next; }; class SyncList{ ListEntry *_head; pthread_mutex_t _mutex; sem_t _emptySem; public: SyncList(); void insert(int val); int remove(); }; SynchList.cc SyncList:: SyncList(){ _ _head = NULL; pthread_mutex_init( &_mutex, NULL ); sem_init(&_emptySem,0, 0); } SyncList ::insert(int val){ ListEntry *e = new ListEntry; e->_val = val; pthread_mutex_lock(&_mutex); a)e->_next = _head; b)_head = e; pthread_mutex_unlock(&_mutex); sem_post(&_emptySem); }

A Synchronized List int SyncList ::remove(){ ListEntry *tmp; // Wait until list is not empty sem_wait(&_emptySem); pthread_mutex_lock(&_mutex); c)tmp = _head; d)head=tmp->_next; pthread_mutex_unlock(&mutex); int val=tmp->_val; delete tmp; return val; }

Example: Removing Before Inserting T1 T2 remove() sem_wait(&_emptySem) (count==-1) wait insert(5) pthread_mutex_lock() a) b) pthread_mutex_unlock() sem_post(&_emptySem) wakeup T1 T1 continues pthread_mutex_lock() c) d) pthread_mutex_unlock()

Example: Inserting Before Removing T1 T2 insert(7) pthread_mutex_lock() a) b) pthread_mutex_unlock() sem_post(&_emptySem)(count==1) Starts running remove() sem_wait(_emptySem); continue (count==0) pthread_mutex_lock() c) d) pthread_mutex_unlock()

Notes on Synchronized List Class We need the mutex lock to enforce atomicity in the critical sections a) b) and c) d). The semaphore is not enough to enforce atomicity.

Notes on Synchronized List Class int MTList::remove(){ ListEntry *tmp; sem_wait(&_emptySem); pthread_mutex_lock(&_mutex); c)tmp = _head; d)head=tmp->_next; pthread_mutex_unlock(&mutex); int val=tmp->_val; delete tmp; return val; } N (N= items in list) >N 1

Notes on Synchronized List Class The sem_wait() call has to be done outside the mutex_lock/unlock section. Otherwise we can get a deadlock. Example: pthread_mutex_lock(&_mutex); sem_wait(&_empty); c)tmp = _head; d)head=tmp->_next; pthread_mutex_unlock(&mutex);

Notes on Synchronized List Class T1 T2 remove() mutex_lock sem_wait(&_empty) wait for sem_post from T2 insert(5) pthread_mutex_lock() wait for mutex_unlock in T1 Deadlock!!!!

Review Questions How do Recursive Mutex locks differ from regular Mutex locks? Why one may prefer to use a mutex lock that is not resursive? How to implement recursive mutex locks (part of Project 4)? Why one should not use spin locks on a single CPU machone? When a process with multiple threads call fork(), what threads are created in child process, under pthread semantics?

Review Questions What is a race condition? (When given simple codes, should be able to come up with race condition scenario.) What happens when calling sem_wait(), sem_post? (Should be able to produce pseudo-code.) Different usage of semaphore when initiating it with different values. What are the key difference between binary semaphore and mutex lock? How to implement a synchronized list? Why we need both mutex and semaphore?