/* A counting semaphore. */ struct semaphore { unsigned value; struct list waiters; }; void void bool void void sema_init (struct semaphore *, unsigned val); sema_down (struct semaphore *); sema_try_down (struct semaphore *); sema_up (struct semaphore *); sema_self_test (void); /* Lock. */ struct lock { struct thread *holder; /* For debug */ struct semaphore semaphore; }; void void bool void lock_init (struct lock *); lock_acquire (struct lock *); lock_try_acquire (struct lock *); lock_release (struct lock *); /* Condition variable. */ struct condition { struct list waiters; }; cond_init (struct condition *); cond_wait (struct condition *, struct lock *); cond_signal (struct condition *, struct lock *); cond_broadcast (struct condition *, struct lock *); /* − Locks must be used on ALL accesses (read and write) to be effective − Conditions are critical and REQUIRE a lock − Conditions ALWAYS have your custom expression to determine if the condition is true or false − Signal on a condition will only awake one thread that is ALREADY WAITING − Up on a semaphore will EVENTUALLY (slutligen/till slut) awake one thread, already waiting or not yet waiting − Down on a semaphore can be done twice by the same thread − A semaphore will allow any thread to Up it − A lock will allow only the locker to release it − A lock can never be Acqired if already held by the thread */