//Analyze these implementations of the various sync primitives //Assume a correct implementation of locks is provided for you //Do these implementations satisfy the safety and liveness requirements? //Condition Variables void condition_wait(lock_t *lock, condition_t *cond){ lock_release(lock); enter_critical(); block(&cond->wait_queue); leave_critical(); lock_acquire(lock); } //Semaphores void semaphore_up(semaphore_t *sem){ enter_critical(); ++sem->value; unblock_one(&sem->wait_queue); leave_critical(); } void semaphore_down(semaphore_t *sem) { enter_critical(); if(sem->value <= 0){ block(&sem->wait_queue); } --sem->value; leave_critical(); } //Barriers void barrier_wait(barrier_t *bar){ enter_critical(); if(--bar->value > 0){ block(&bar->wait_queue); ++bar->value; } else{ unblock_all(&bar->wait_queue); ++bar->value; } leave_critical(); }