- UNLOCK(mutex->lock);
- do {
- PTHREAD_MACH_CALL(semaphore_wait(mutex->sem), kern_res);
- } while (kern_res == KERN_ABORTED);
- LOCK(mutex->lock);
- mutex->waiters--;
- if (mutex->waiters == 0) {
- restore_sem_to_pool(mutex->sem);
- mutex->sem = MACH_PORT_NULL;
+ } else
+ self = _PTHREAD_MUTEX_OWNER_SELF;
+
+ if (mutex->owner != (pthread_t)NULL) {
+ if (mutex->waiters || mutex->owner != _PTHREAD_MUTEX_OWNER_SWITCHING)
+ {
+ semaphore_t sem, order;
+
+ if (++mutex->waiters == 1)
+ {
+ mutex->sem = sem = new_sem_from_pool();
+ mutex->order = order = new_sem_from_pool();
+ }
+ else
+ {
+ sem = mutex->sem;
+ order = mutex->order;
+ do {
+ PTHREAD_MACH_CALL(semaphore_wait(order), kern_res);
+ } while (kern_res == KERN_ABORTED);
+ }
+ UNLOCK(mutex->lock);
+
+ PTHREAD_MACH_CALL(semaphore_wait_signal(sem, order), kern_res);
+ while (kern_res == KERN_ABORTED)
+ {
+ PTHREAD_MACH_CALL(semaphore_wait(sem), kern_res);
+ }
+
+ LOCK(mutex->lock);
+ if (--mutex->waiters == 0)
+ {
+ PTHREAD_MACH_CALL(semaphore_wait(order), kern_res);
+ mutex->sem = mutex->order = SEMAPHORE_NULL;
+ restore_sem_to_pool(order);
+ restore_sem_to_pool(sem);
+ }
+ }
+ else if (mutex->owner == _PTHREAD_MUTEX_OWNER_SWITCHING)
+ {
+ semaphore_t sem = mutex->sem;
+ do {
+ PTHREAD_MACH_CALL(semaphore_wait(sem), kern_res);
+ } while (kern_res == KERN_ABORTED);
+ mutex->sem = SEMAPHORE_NULL;
+ restore_sem_to_pool(sem);