1 / 17

CS444/CS544 Operating Systems

Learn about the various synchronization primitives used in operating systems, including semaphores and spinlock semaphores. Understand their implementations and how they block the waiting process or thread.

bpearl
Download Presentation

CS444/CS544 Operating Systems

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CS444/CS544Operating Systems Synchronization 2/19/2007 Prof. Searleman jets@clarkson.edu

  2. CS444/CS544 Spring 2007 • Synchronization Primitives • Implementations that block the waiting process/thread • Semaphores • Binary semaphores • Counting semaphores • Spinlock semaphores Reading assignment: • Chapter 6

  3. Recap: Implementing a semaphore with a lock struct semaphore_t { int value; queue waitingQueue; lock_t l; } void signal( semaphore_t *s){ lock(&s->l); s->value++; if (s->value <=0) { P = remove process from s->waitingQueue unlock(&s->l); wakeup (P) } else { unlock(&s-l); } } void wait( semaphore_t *s){ lock(&s->l); s->value--; if (s->value < 0){ add self to s->waitingQueue unlock(&s->l); block } else { unlock(&s->l); } }

  4. Recap: Binary & Counting Semaphores • Binary semaphore: value is either 0 or 1 • Used to guarantee exclusive access to shared resource • semaphore mutex = 1; • down(mutex); /* critical section */; up(mutex); • Counting semaphore: value is any int • Useful to control access to a resource with N interchangeable units available; Allow threads to enter semaphore as long as sufficient resources are available • semaphore Nsem = N; • down(Nsem); /* use one unit */; up(Nsem);

  5. Is busy-waiting eliminated? • Threads block on the queue associated with the semaphore instead of busy waiting • Busy waiting is not gone completely • When accessing the semaphore’s critical section, thread holds the semaphore’s lock and another process that tries to call wait or signal at the same time will busy wait • Semaphore’s critical section is normally much smaller than the critical section it is protecting so busy waiting is greatly minimized • Also avoid context switch overhead when just checking to see if can enter critical section and know all threads that are blocked on this object

  6. Are spin locks always bad? • Adaptive Locking in Solaris • Adaptive mutexes • Multiprocessor system if can’t get lock • And thread with lock is not running, then sleep • And thread with lock is running, spin wait • Uniprocessor if can’t get lock • Immediately sleep (no hope for lock to be released while you are running) • Programmers choose adaptive mutexes for short code segments and semaphores or condition variables for longer ones • Blocked threads placed on separate queue for desired object • Thread to gain access next chosen by priority and priority inversion is implemented

  7. Binary, Counting & Spinlock Semaphores “spinlock” semaphore: wait(s){ while (s->value <= 0); s.value--; } signal(s){ s->value++; } typedef struct { int value; struct p* queue; } semaphore ; current = running proc/thread wait()/signal() MUST be indivisible! “binary” semaphore: only 0/1 wait(s) { if (s->value > 0) s->value--; else { add current to s->queue; block current; } } signal(s){ if (s->queue ≠ empty) { remove t from s->queue; wakeup(t); } else s->value++; } “counting” semaphore: any int wait(s) { s->value--; if (s->value < 0) { add current to s->queue; block current; } } signal(s){ s->value++; if (s->value <= 0) { remove t from s->queue; wakeup(t); } }

  8. Pthread’s Locks (Mutex) • Create/destroy int pthread_mutex_init (pthread_mutex_t *mut, const pthread_mutexattr_t *attr); int pthread_mutex_destroy (pthread_mutex_t *mut); • Lock int pthread_mutex_lock (pthread_mutex_t *mut); • Non-blocking Lock int pthread_mutex_trylock (pthread_mutex_t *mut); • Unlock int pthread_mutex_unlock (pthread_mutex_t *mut);

  9. Semaphores • Not part of pthreads per se • #include <semaphore.h> • Support for use with pthreads varies (sometime if one thread blocks whole process does!) • Create/destroy int sem_init (sem_t *sem, int sharedBetweenProcesses , int initalValue); Int sem_destory(sem_t *sem) • Wait int sem_wait (sem_t *sem) int sem_trywait(sem_t * sem) • Signal int sem_post(sem_t *sem); • Get value int sem_getvalue(sem_t *, int * value);

  10. Window’s Locks (Mutex) • Create/destroy HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpsa,  // optional security attributes   BOOL bInitialOwner           // TRUE if creator wants ownership   LPTSTR lpszMutexName )       // object’s name BOOL CloseHandle( hObject ); • Lock DWORD WaitForSingleObject( HANDLE hObject,         // object to wait for                           DWORD dwMilliseconds ); • Unlock BOOL ReleaseMutex( HANDLE hMutex );

  11. Window’s Locks (CriticalSection) • Create/Destroy VOID InitializeCriticalSection( LPCRITICAL_SECTION lpcs ); VOID DeleteCriticalSection( LPCRITICAL_SECTION lpcs ); • Lock VOID EnterCriticalSection( LPCRITICAL_SECTION lpcs ); • Unlock VOID LeaveCriticalSection( LPCRITICAL_SECTION lpcs );

  12. Window’s Semaphores • Create HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpsa,  // optional security attributes   LONG lInitialCount,          // initial count (usually 0)   LONG lMaxCount,              // maximum count (limits # of threads)   LPTSTR lpszSemName );        // name of the semaphore (may be NULL) BOOL CloseHandle( hObject ); • Lock DWORD WaitForSingleObject( HANDLE hObject,         // object to wait for                           DWORD dwMilliseconds ); • Unlock BOOL ReleaseSemaphore(   HANDLE hSemaphore,   LONG lRelease,          // amount to increment counter on release                           // (usually 1)   LPLONG lplPrevious );   // variable to receive the previous count

  13. Sharing Window’s Synchronization Objects • Threads in the same process can share handle through a global variable • Critical sections can only be used within the same process • Much faster though • Handles to mutexes and semaphores can be shared across processes • One process creates another and the child inherits the handle (must specifically mark handle for inheritance) • Unrelated processes can share through DuplicateHandle function or OpenMutex or OpenSemaphore (based on knowledge of the name – like a shared file name)

  14. Windows 2000 Synchronization • Uses interrupt masks to protect access to global resources on uniprocessor systems. • Uses spinlocks on multiprocessor systems. • Also provides dispatcher objects which may act as wither mutexes and semaphores. • Dispatcher objects may also provide events. An event acts much like a condition variable.

  15. Problems with Locks and Semaphores • There is no syntactic connection between the semaphore ( or lock or event) and the shared data/resources it is protecting • Thus the “meaning” of the semaphore is defined by the programmer’s use of it • Poor software design • Semaphores basically global variables accessed by all threads • Easy for programmers to make mistakes • Also no separation between use for mutual exclusion and use for resource management and use for expressing ordering/scheduling constraints

  16. Programming Language Support • Add programming language support for synchronization • Declare a section of code to require mutually exclusive access (like Java’s synchronized) • Associate the shared data itself with the locking automatically • Monitor = programming language support to enforce synchronization • Mutual exclusion code added by the compiler!

  17. Monitors • A monitor is a software module that encapsulates: • Shared data structures • Procedures that operated on them • Synchronization required of processes that invoke these procedures • Like a public/private data interface prevents access to private data members; Monitors prevent unsynchronized access to shared data structures

More Related