Fair reader writer problem
Reader preference
lock(2)     lock(1)                 
//do write    if (readcount++)       
unlock(2)       lock(2)              
            unlock(1)               
    	// do read                      
    	lock(1)                 
              if (!readcount--)     
                unlock(2)          
            unlock(1)                                                               
Writer preference
 lock(1)                 lock(2)               
   if !(writecount++)    if (!readcount++)     
      lock(2)               lock(3)            
 unlock(1)               unlock(2)             
 lock(3)                 //                    
 unlock(3)                                     
 lock(1)                lock(2)                
   if !(--writecount)   if !(--readcount)      
      unlock(2)            unlock(3)           
 unlock(1)              unlock(2)
Neither preferred
 lock(4)        lock(4); lock(3)	 
 lock(2)        if !(readcount++)	 
 unlock(4)        lock(2)		 
 //             unlock(3); unlock(4)	 
 unlock(2)      // 			 
                lock(3)		 
                if !(--readcount)	 
                   unlock(2)		 
                unlock(3)              
Producer consumer problem (using semaphores)
 sem_init(resources, 0)
 sem_init(places, n)
    
 producer                  consumer
  
 sem_down(places)          sem_down(resources)
 enqueue_locked(item)      enqueue_locked(item)
 sem_up(resources)         sem_up(places)
Producer consumer problem using condition variables
- a state variable is essential to prevent missed wakeups, state variable indicates if signalling happened before wait was called.
 - primitives:
- wait(condition, mutex) [mutex must be locked at the time of calling, it is released on sleep and retaken on wakeup]
 - signal(condition) - [taking mutex is recommended during signal, eg. in the simple case, state variable checking might be interleaved in a way such that there is still missed signal.]
 - broadcast(condition) - like signal but wakes all process and not only head.
 
 
producer() 
lock(mutex)                                                               	
while (full)                        // while ensures state check 	  		
     wait(condition_nonfull, mutex)    after wakeup which is necessary    	
put()                                  if there are multiple signalees    	
signal(condition_nonempty) 
unlock(mutex)
consumer()
lock(mutex)			
	    while (empty)		
    wait(condition_nonempty, mutex) 
get()				 
signal(condition_nonfull)		 
unlock(mutex) 
compare_exchange primitive
compare_exchange(target, expected, desired) - if target = expected, target = desired else return value of target in expected.
Bakery algorithm
 bakery algorithm - read writes are atomic, entering[i] = 0 & ticket[i] = 0 for i  = 1 to n
 entering[i] = true 
 ticket[i] = max (ticket[i] for all i)
 entering[i] = false
 for all j
     while (entering[j]);
     while((ticket[j] != 0) && ((ticket[i] > ticket[j]) || (ticket[i] == ticket[j] && i > j)  )
RCU locks
- key idea: on all systems load and store to pointers are atomic. any_t *ptr = something;
 - make a copy of shared data, update, swap pointers and free old copy.
 - additional work required (publish/subscribe) to ensure consistency wrt compiler and CPU reordering.
 - publish - rcu_assign_pointer()
 - subscribe - rcu_dereference()
 - waiting for things to finish before cleaning up - synchronize_rcu() freeing the old structure - some readers might have references and hence cannot be freed however, after all processors undergo one schedule, old structure can be freed the free is done with this function call_rcu(struct rcu_head head, void (func)(void *arg), void *arg); func is callback that gets called after all processors undergo schedule
 - rcu_read_[un]lock = preempt disable. Also means no sleeping while under lock.
 
Seq locks
- has associated sequence number. Readers log sequence number before critical section and match afterwards else retry.
 - reader
do { seq = read_seqbegin(&the_lock); /* Do what you need to do */ } while read_seqretry(&the_lock, seq); - writer
void write_seq[un]lock(seqlock_t *lock);