Synchronization Semaphores implementation
Possible implementations There are seeral possible implementations (standard and non standard)of a semaphore Semaphores through pipe POSIX semaphores Linux semaphores Pthread Mutex (Mutual exclusion) Condition Variable Notice that semaphores are Global objects (refer to sem_init) They do not belong to a particular process
Semaphores through pipe Summarising A semaphore is a ariable of the type counter The wait operation Decreases the counter alue Is blocking if the counter is equal to 1 The signal operation Increases the counter alue Such behaior can be realized using a pipe between a father process and a child process
Semaphores through pipe From a pipe The sempahore counter is realized using the concept of token The signal is performed by a write operation of a token on the pipe (non blocking) The wait is performed through a read operation of a token from the pipe (blocking) write/signal Pipe read/wait
semaphoreinit (s) #include <unistd.h> oid semaphoreinit (int *S) { if (pipe (S) == -1) { printf ( Error ); exit (-1); } return; } Initialize the sempahore
semaphoresignal (s) #include <unistd.h> oid semaphoresignal (int *S) { char ctr = X ; if (write(s[1], &ctr, sizeof(char))!= 1) { printf ( Error ); exit (-1); } return; } Writes a character (any) on the pipe
semaphorewait (s) #include <unistd.h> oid semaphorewait (int *S) { char ctr; if (read (S[0], &ctr, sizeof(char))!= 1) { printf ( Error ); exit (-1); } return; } Reads a character from the pipe (blocking read)
Esempio int main() { int S[2]; pid_t pid; semaphoreinit (S); pid = fork(); // Check for correctness if (pid == 0) { // child semaphorewait (S); printf("wait done.\n"); } else { // parent printf("sleep 3s.\n"); sleep (3); semaphoresignal (S); printf("signal done.\n"); } return 0; }
POSIX sempahores Semaphores implementation independent from the operating system (standard POSIX) Header file semaphore.h Insert into the.c files #include <semaphore.h> A semaphore is a ariable of type sem_t sem_t *sem1, *sem2,...;
POSIX semaphores All functions Are called sem_* In case of error they return the alue -1 Basic functions sem_init sem_wait sem_try sem_post sem_getalue sem_destroy
sem_init () int sem_init ( sem_t *sem, int pshared, unsigned int alue ); Inatialize the semaphore to the alue alue The alue of pshared identifies the type of semaphore If it's equal to 0, the the semaphore is local to the current process Otherwise, the sempahore can be shared between different processes (father that initizlizes and children created later)
sem_wait () int sem_wait ( sem_t *sem ); Standard wait operation If the semaphore is equal to 0, it blocks the caller until it can decrease the semaphore alue
sem_try () int sem_trywait ( sem_t *sem ); Wait operation without block (non-blocking wait) If the sempahore has a alue different from 0 (>0), the sempahore decreases it and returns to 0 If the semaphore is euqal to 0, returns -1 (instead of blocking the caller it calls a wait)
sem_post () int sem_post ( sem_t *sem ); Classical signal operation Increases the semaphore alue
sem_getalue () int sem_getalue ( sem_t *sem, int *alp ); Allows to examine the alue of a semaphore The semaphore alue is assigned to *alp (i.e., alp is the inside pointer which indicates the sempahore alue after the call) If there are waiting processes, to *alp is assigned the alue 0 or a negatie number whose absolute alue is equal to the number of waiting processes
sem_destroy () int sem_destroy ( sem_t *sem ); Destroys a semaphore preiously created Can return -1 if someone tries to destroy a sempahore used by another process
... #include "semaphore.h"... sem_t *sem;... sem = (sem_t *) malloc(sizeof(sem_t)); sem_init (sem, 0, 0);...... create sub processes or threads...... sem_wait (sem);... SC... sem_post (sem); Example
Linux semaphores Uses the system calls in sys/sem.h semget Accesses or creates a set (array) of semaphores semop Increases, decreases or controls a specific semaphore semctl Allows other operations (e.g. init, reading a semaphore ariable, etc.) It's use is uselessly complicated
Mutex Pthread Implementation of binary semaphores (mutex) The basic type of a mutex is pthread_mutex_t Basic functions pthread_mutex_init pthread_mutex_lock pthread_mutex_trylock pthread_mutex_unlock pthread_mutex_destroy
pthread_mutex_init () int pthread_mutex_init ( pthread_mutex_t *mutex, const pthread_mutexattr_t *attr ); Creates a new lock (mutex ariable) mutex Returns mutex to the caller attr specifies the attributes of mutex (default=null) Return alue If the operation was successful 0 The error code otherwise
pthread_mutex_lock () int pthread_mutex_lock ( pthread_mutex_t *mutex ); Controls the alue of the lock mutex and Blocks the caller if it's already locked Acquires the lock if it isn't locked Return alue If the operation was successful 0 The error code otherwise
pthread_mutex_trylock () int pthread_mutex_trylock ( pthread_mutex_t *mutex ); Similar to pthread_mutex_lock but in case the lock has been already acquired it returns without blocking the caller Return alue If the lock has been acquired 0 If the mutex was held by another thread, error code EBUSY
pthread_mutex_unlock () int pthread_mutex_unlock ( pthread_mutex_t *mutex ); Releases the lock mutex at the end of the SC Return alue If the operation was 0 The error code otherwise
pthread_mutex_destroy () int pthread_mutex_destroy ( pthread_mutex_t *mutex ); Releases the memory occupied by the lock mutex That lock won't be usable anymore Return alue If the operation was successful 0 The error code otherwise
Conditional Variable Pthread The control the access according to the alue of a ariable Basic functions pthread_cond_init pthread_cond_wait pthread_cond_signal pthread_cond_broadcast pthread_cond_destroy They are always used together with mutexes