Plan Demos ! Project: Due ! Next next Wednesday Demos » Demos following week (Wednesday during class time) ! Preparation (show & tell) ! Next Week – » 3 precompiled kernels (original, lottery, stride, dynamic) » New phase of presentations » 1 prepared document to tell me what is working what is not – overview what you did (5 minutes), script, and » Deadlock, finish synchronization hand-in Tuesday ! Course Progress: ! How will it work (details) » History, Structure, Processes, Threads, IPC, » Show Data Structures in code Synchronization » Show Functionality added in code/kernel » Remainder: Deadlock, Memory and File » Show that it runs » Demonstrates your testing & evaluation strategy » Compile (not) & run (this will be done last) Maria Hybinette, UGA Maria Hybinette, UGA Next Project ! Add System Call (again, yes) CSCI [4|6]730 ! Add a service (see how this fit in shortly) Operating Systems » It is a synchronization service (semaphore or monitor) » Waking up and putting processes to sleep Synchronization Part 2 ! Write a simple application program that use this new service. Maria Hybinette, UGA Maria Hybinette, UGA Process Synchronization Part II Hardware Primitives Many modern operating systems provide special synchronization hardware to provide more powerful atomic operations ! How does hardware facilitate synchronization? ! testAndSet( lock ) ! What are problems of the hardware » atomically reads the original value of lock and then sets it to true. primitives? ! Swap( a, b ) ! What is a spin lock and when is it » atomically swaps the values appropriate? ! compareAndSwap( a, b ) ! What is a semaphore and why are they » atomically swaps the original value of lock and sets it to true when they values are different needed? ! fetchAndAdd( x, n ) ! What is the Dining Philosophers Problem and » atomically reads the original value of x and adds n to it. what is ‘ a good ’ solution? Maria Hybinette, UGA Maria Hybinette, UGA
Hardware: testAndSet(); Hardware: Swap(); void Swap( boolean *a, boolean *b ) boolean testAndSet ( boolean *lock ) { { // initialization boolean temp = *a ; boolean old_lock = lock ; lock = false ; // global shared -- lock is available *a = *b; lock = true; // initialization void deposit( int amount ) *b = temp; return old_lock; lock = false ; // shared -- lock is available { } } void deposit( int amount ) // entry critical section - get local variable key { key = true; // key is a local variable // entry to critical section - get the lock while( key == true ) Swap( &lock, &key ); while( testAndSet( &lock ) == true ) {} ; balance += amount // critical section balance += amount // critical section // exit critical section - release the lock // exit critical section - release the lock lock = false; lock = false; } } ! Two Parameters: a global and local (when lock is ! If someone has the lock (it returns TRUE) and wait available (false) get local key (false)). until it is available (until some-one gives it up, sets it ! Atomicity guaranteed - even on multiprocessors to false). ! Bounded waiting? ! Atomicity guaranteed - even on multiprocessors » No! How to provide? Maria Hybinette, UGA Maria Hybinette, UGA Hardware with Bounded Waiting Hardware with Bounded Waiting // initialization lock = false ; // shared -- lock is available ! Need to create a waiting line. waiting[0.. n-1] = {false} ; // shared -- no one is waiting void deposit( int amount ) ! Idea: “ Dressing Room ” is the critical section, { only one person can be in the room at one time, // entry to critical section waiting[tid] = true; // signal tid is waiting and one waiting line outside dressing room that key = true; // local variable serves customer first come first serve. while( ( waiting[tid] == true ) and ( key == true ) ) key = testAndSet( &lock ); » waiting[n] : Global shared variable waiting[tid] = false; // got lock done waiting balance += amount // critical section » lock : Global shared variable ! Entry get a local variable ‘ key ’ and check via // exit critical section - release the lock j = (tid + 1) mod n; // j is possibly waiting next in line testAndSet() if someone is ‘ in ’ the dressing while( ( j != tid ) and ( waiting[j] == false ) ) room j = (j + 1) mod n; // check next if waiting if( j == tid ) // no one is waiting unlock room lock = false; else waiting[j] = false // hand over the key to j } Maria Hybinette, UGA Maria Hybinette, UGA Hardware Solution: Proof “ Intuition ” Synchronization Layering ! Build higher-level synchronization primitives in OS ! Mutual Exclusion: » Operations that ensure correct ordering of instructions » A thread enters only if it is waiting or if the dressing room across threads is unlocked ! Motivation: Build them once and get them right – First thread to execute testAndSet( &lock ) gets the lock all others will wait » Don ’ t make users write entry and exit code – Waiting becomes false only if the thread with the lock leaves its CS and only one waiting is set to false. Monitors ! ! Progress: *Locks ! » Since an exiting thread either unlocks the dressing room or hands the ‘ lock ’ to another thread progress is Condition Variables ! *Semaphores ! guaranteed because both allow a waiting thread access to the dressing room Loads ! ! Bounded Waiting: Test&Set ! Stores ! » Leaving threads scans the waiting array in cyclic order thus any waiting thread enters the critical section within Disable Interrupts ! n-1 turns. Maria Hybinette, UGA Maria Hybinette, UGA
Locks Lock Examples ! Goal: Provide mutual exclusion (mutex) ! After lock has been allocated and initialized » The other criteria for solving the critical section problem may be violated void deposit( int amount ) ! Three common operations: { pthread_mutex_lock( &my_lock ); Allocate and Initialize balance += amount; // critical section pthread_mutex_unlock( &my_lock ); pthread_mutex_t mylock; } mylock = PTHREAD_MUTEX_INITIALIZER; Acquire ! One lock for each bank account (maximize Acquire exclusion access to lock; Wait if lock is not available concurrency) pthread_mutex_lock( &mylock ); Release � void deposit( int account_tid, int amount ) { Release exclusive access to lock pthread_mutex_lock( &locks[account_tid] ); pthread_mutex_unlock( &mylock ); balance[account_tid] += amount; // critical section pthread_mutex_unlock( &locks[account_tid] ); } Maria Hybinette, UGA Maria Hybinette, UGA Implementing Locks: Implementing Locks: Atomic loads and stores Hardware Instructions (now) typedef boolean lock_s; typedef struct lock_s void acquire( lock_s *lock ) bool lock[2] = {false, false}; while( true == testAndSet( theLock ) ) {} ; // wait int turn = 0; void release( lock_s lock ) void acquire( lock_s *lock ) lock = false; lock->lock[tid] = true; turn = 1-tid; while( lock->lock[1-tid] && lock->turn ==1-tid ) ! Advantage: Supported on multiple processors ! Disadvantages: void release( lock_s lock ) » Spinning on a lock may waste CPU cycles lock->lock[tid] = false; » The longer the CS the longer the spin – Greater chance for lock holder to be interrupted too! ! Disadvantage: Two threads only Maria Hybinette, UGA Maria Hybinette, UGA Implementing Locks: Spin Locks and Disabling Disable/Enable Interrupts Interrupts void acquire( lock_s *lock ) ! Spin locks and disabling interrupts are useful only for disableInterrupts(); short and simple critical sections (not computational or I/O intensive): � void release( lock_s lock ) » Wasteful otherwise � enableInterrupts(); » These primitives are primitive -- don ’ t do anything besides mutual exclusion (doesn ʼ t ʻ solve ʼ the critical section problem). � ! Advantage: Supports mutual exclusion for many ! Need a higher-level synchronization primitives that: � threads (prevents context switches) – Block waiters � ! Disadvantages: – Leave interrupts enabled within the critical section � » Not supported on multiple processors, » All synchronization requires atomicity � » Too much power given to a thread (may not release lock_ – So we ’ ll use our “ atomic ” locks as primitives to implement them � » May miss or delay important events Maria Hybinette, UGA Maria Hybinette, UGA
Recommend
More recommend