Synchronization Primitives – Semaphore and Mutex

Slides:



Advertisements
Similar presentations
Operating Systems Semaphores II
Advertisements

CS Lecture 4 Programming with Posix Threads and Java Threads George Mason University Fall 2009.
Ch. 7 Process Synchronization (1/2) I Background F Producer - Consumer process :  Compiler, Assembler, Loader, · · · · · · F Bounded buffer.
Enforcing Mutual Exclusion, Semaphores. Four different approaches Hardware support Disable interrupts Special instructions Software-defined approaches.
Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.
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.
Semaphores Questions answered in this lecture: Why are semaphores necessary? How are semaphores used for mutual exclusion? How are semaphores used for.
Condition Variables Revisited Copyright ©: University of Illinois CS 241 Staff1.
CS 241 Section Week #4 (2/19/09). Topics This Section  SMP2 Review  SMP3 Forward  Semaphores  Problems  Recap of Classical Synchronization Problems.
Pthread (continue) General pthread program structure –Encapsulate parallel parts (can be almost the whole program) in functions. –Use function arguments.
Introduction to Pthreads. Pthreads Pthreads is a POSIX standard for describing a thread model, it specifies the API and the semantics of the calls. Model.
The University of Adelaide, School of Computer Science
Multi-threaded Programming with POSIX Threads CSE331 Operating Systems Design.
Threads and Thread Control Thread Concepts Pthread Creation and Termination Pthread synchronization Threads and Signals.
Copyright ©: University of Illinois CS 241 Staff1 Synchronization and Semaphores.
CS345 Operating Systems Threads Assignment 3. Process vs. Thread process: an address space with 1 or more threads executing within that address space,
Copyright ©: Nahrstedt, Angrave, Abdelzaher1 Semaphore and Mutex Operations.
Programming with POSIX* Threads Intel Software College.
Pthreads: A shared memory programming model
Threads CSCE Thread Motivation Processes are expensive to create. Context switch between processes is expensive Communication between processes.
S -1 Posix Threads. S -2 Thread Concepts Threads are "lightweight processes" –10 to 100 times faster than fork() Threads share: –process instructions,
1 Pthread Programming CIS450 Winter 2003 Professor Jinhua Guo.
POSIX Synchronization Introduction to Operating Systems: Discussion Module 5.
Synchronizing Threads with Semaphores
Pthreads.
Lecture 15 Semaphore & Bugs. Concurrency Threads Locks Condition Variables Fixing atomicity violations and order violations.
2.3 interprocess communcation (IPC) (especially via shared memory & controlling access to it)
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 11: Thread-safe Data Structures, Semaphores.
Pthreads #include pthread_t tid ; //thread id. pthread_attr_t attr ; void *sleeping(void *); /* thread routine */ main() { int time = 2 ; pthread_create(&tid,
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science Software Systems Advanced Synchronization Emery Berger and Mark Corner University.
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.
PThread Synchronization. Thread Mechanisms Birrell identifies four mechanisms commonly used in threading systems –Thread creation –Mutual exclusion (mutex)
Working with Pthreads. Operations on Threads int pthread_create (pthread_t *thread, const pthread_attr_t *attr, void * (*routine)(void*), void* arg) Creates.
1 COMP 3500 Introduction to Operating Systems Project 3 – Synchronization Overview Dr. Xiao Qin Auburn University
pThread synchronization
回到第一頁 What are threads n Threads are often called "lightweight processes” n In the UNIX environment a thread: u Exists within a process and uses the process.
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
Synchronization and Semaphores
CS 537 – Introduction to Operating Systems
Semaphores Synchronization tool (provided by the OS) that does not require busy waiting. Logically, a semaphore S is an integer variable that, apart from.
Process Synchronization: Semaphores
PARALLEL PROGRAM CHALLENGES
PThreads.
Principles of Operating Systems Lecture 11
סמפורים.
Pthreads – Create and Join
Threads Threads.
Chapter 5: Process Synchronization
POSIX Threads 1. Background 2. Threads vs. Processes
Thread synchronization
Lecture 14: Pthreads Mutex and Condition Variables
BOOM! count is [ ], should be
Synchronization and Semaphores
Concurrency: Mutual Exclusion and Synchronization
Jonathan Walpole Computer Science Portland State University
UNIVERSITY of WISCONSIN-MADISON Computer Sciences Department
Lecture 2 Part 2 Process Synchronization
Pthread Prof. Ikjun Yeom TA – Mugyo
Lecture 14: Pthreads Mutex and Condition Variables
CSE 153 Design of Operating Systems Winter 19
Synchronization.
Synchronization.
Lecture 20: Synchronization
Lecture 12 CV and Semaphores
POSIX Threads(pthreads)
Lab #9 Semaphores Operating System Lab.
Presentation transcript:

Synchronization Primitives – Semaphore and Mutex

Outline Using Semaphores – Examples Thread Synchronization Mutex Synchronization Primitive Operations on Mutex Examples

Example 1 on Semaphore (RR: 497) We want a shared variable ‘shared’ (critical section) to be protected by semaphore to allow for two functions getshared – is a function that returns the current value of the shared variable ‘shared’ incshared – is a function that that atomically increments the ‘shared’ variable.

Example, creating shared variable #include <errno.h> #include <semaphore.h> static int shared = 0; static sem_t sharedsem; int initshared(int val) { if (sem_init(&sharedsem, 0, 1) == -1) return -1; shared = val; return 0; }

Example – shared variable int getshared(int *sval) { while (sem_wait(&sharedsem) == -1) if (errno != EINTR) return -1; *sval = shared; return sem_post(&sharedsem); } int incshared() { shared++;

Example 2 on Semaphore (RR:500) A program to generate a set of threads and each thread writes to standard error Standard error (stderr) is a shared resource, hence if a thread outputs an informative message to standard error one character at the time, it becomes a critical region and we must protect it.

Thread with Critical Section (Example RR:500) - #include <errno.h> #include <pthread.h> #include <semaphore.h> #include <stdio.h> #include <unistd.h> #define TEN_MILLION 10000000L #define BUFSIZE 1024

Thread with Critical Section void *threadout(void *args) { char buffer[BUFSIZE]; char *c; sem_t *semlockp; struct timespec sleeptime; semlockp = (sem_t *)args; sleeptime.tv_sec = 0; sleeptime.tv_nsec = TEN_MILLION; snprintf(buffer, BUFSIZE, "This is a thread from process %ld\n", (long) getpid()); c = buffer;

Thread with Critical Section /****************** entry section *************************/ while (sem_wait(semlockp) == -1) /* Entry section */ if(errno != EINTR) { fprintf(stderr, "Thread failed to lock semaphore\n"); return NULL; } /****************** start of critical section ***********/ while (*c != '\0') { fputc(*c, stderr); c++; nanosleep(&sleeptime, NULL); /****************** exit section ******************/ if (sem_post(semlockp) == -1) /* Exit section */ fprintf(stderr, "Thread failed to unlock semaphore\n"); /****************** remainder section ****************/ return NULL; }

Main program (Example RR:501) #include <pthread.h> #include <semaphore.h> #include <stdio.h> #include <stdlib.h> #include <string.h> void *threadout(void *args); int main(int argc, char *argv[]) { int error; int i; int n; sem_t semlock; pthread_t *tids;

Main program (Example RR:501) if (argc != 2){/* check for valid number of command-line arguments */ fprintf (stderr, "Usage: %s numthreads\n", argv[0]); return 1; } n = atoi(argv[1]); tids = (pthread_t *)calloc(n, sizeof(pthread_t)); if (tids == NULL) { perror("Failed to allocate memory for thread IDs"); if (sem_init(&semlock, 0, 1) == -1) { perror("Failed to initialize semaphore");

Main program for (i = 0; i < n; i++) if (error = pthread_create(tids + i, NULL, threadout, &semlock)) { fprintf(stderr, "Failed to create thread:%s\n", strerror(error)); return 1; } if (error = pthread_join(tids[i], NULL)) { fprintf(stderr, "Failed to join thread:%s\n", return 0; }

Mutex (Locks, Latches) Useful for short-term locking Simplest and most efficient thread synchronization mechanism A special variable that can be either in locked state: a distinguished thread that holds or owns the mutex; or unlocked state: no thread holds the mutex When several threads compete for a mutex, the losers block at that call The mutex also has a queue of threads that are waiting to hold the mutex. POSIX does not require that this queue be accessed FIFO.

POSIX Mutex-related Functions int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); int pthread_mutex_destroy(pthread_mutex_t *mutex); int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);

Mutex and Shared Variables Mutex locks are usually used to protect access to a shared variable. The idea: lock the mutex     critical section unlock the mutex Unlike a semaphore, a mutex does not have a value, it has states (locked and unlocked). Only the owner of the mutex should unlock the mutex. Do not lock a mutex that is already locked. Do not unlock a mutex that is not already locked.

A Typical Way to Use Mutex Create and initialize a mutex variable Several threads attempt to lock the mutex Only one succeeds and that thread owns the mutex The owner thread performs some set of actions The owner unlocks the mutex Another thread acquires the mutex and repeats the process Finally the mutex is destroyed

Use pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; A mutex has type pthread_mutex_t Since a mutex is meant to be used by multiple threads, it is usually declared to have static storage class. It can be defined inside a function using the static qualifier if it will only be used by that function or it can be defined at the top level. A mutex must be initialized before it is used. This can be done when the mutex is defined, as in: pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

Mutex vs. Semaphore Differences/similarity between the two? Mutex is also called binary semaphore in contrast to general counting semaphore Counter is initialized to ??? pthread_mutex_lock = ??? pthread_mutex_unlock = ???

Binary Semaphore Primitives struct binary_semaphore { enum {0,1} value; queueType queue; }; void semWaitB(binary_semaphore s) { if (s.value == 1) s.value = 0; else { place this process in s.queue; block this process; } void semSignalB(binary_semaphore s) { if (s.queue is empty()) s.value = 1; else remove a process P from s.queue; place process P on ready list; } These primitives could be used to implement pthread_thread_lock and unlock

So Which One is More Powerful? Is semaphore more powerful? Is there anything that semaphores can implement but mutex cannot? The answer: they are equivalent! But sometimes one may be more convenient than the other Due to this reason, some systems support only mutex, not general counting semaphores.

Pair Discussion Can you discuss with another student to find out How to use a mutex to implement a general counting semaphore?

Definition of Semaphore Primitives (Counting Semaphore) – PseudoCode from Previous Lecture struct semaphore{ int count; queueType queue; }; void semWait(semaphore s) { s.count--; if (s.count < 0) { place this process in s.queue; block this process; } void semSignal(semaphore s) { s.count++; if (s.count ≤ 0) remove a process P from s.queue; place process P on ready list; }

Busy Wait Counting Semaphore Implementation (1) typedef struct { mutex m; // Mutual exclusion to do ??? int count; // Resource count. }semaphore; int sem_init (semaphore *sem, int count); { mutex *m = &(sem->m); mutex_lock(m); sem->count = count; mutex_unlock(m); return 0; }

Busy Wait Counting Semaphore Implementation(2) Int sem_post(semaphore *sem) { mutex *m = &(sem->m); mutex_lock(m); sem->count++; mutex_unlock(m); } int sem_wait( semaphore *sem) { mutex *m = &(sem->m); mutex_lock(m); sem->count--; while ( sem->count < 0 ) mutex_unlock(m); /* do nothing */ } what is the limitation? Answer: busy polling  wasting CPU time

Summary Mutex and Semaphore are very powerful synchronization primitives Both allow set of instructions to be executed atomically Mutex is a very simple primitive used only for short time usage of data structure updates Counting semaphores are powerful if one wants to allow for example only ‘count ≥ 1’ number of processes/threads into the critical region