How to reach owner SWITCHING but no waiters in 10.5.8 pthread_mutex_lock?
How to reach owner SWITCHING but no waiters in 10.5.8 pthread_mutex_lock?
- Subject: How to reach owner SWITCHING but no waiters in 10.5.8 pthread_mutex_lock?
- From: "Jeremy W. Sherman" <email@hidden>
- Date: Fri, 22 Oct 2010 00:17:21 -0400
I was reading through the 10.5.8 pthread mutex implementation
(Libc-498.1.7/xnu-1228.15.4). I am stumped by a couple things, and I
hope that someone here can shed some light on them.
First: How might a thread enter this else-if clause in
pthread_mutex_lock() (Libc/pthreads/pthread_mutex.c:333)?
if (mutex->owner != (pthread_t)NULL) {
if (mutex->waiters || mutex->owner != _PTHREAD_MUTEX_OWNER_SWITCHING)
{
…
}
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);
}
}
In order to enter this clause, the mutex's owner would have to be
_PTHREAD_MUTEX_OWNER_SWITCHING, but it would have to have no waiters.
But the mutex's owner is only set to SWITCHING by
pthread_mutex_unlock() when there are waiters. Further, the mutex
structure's lock is used to protect changes to owner and waiters, so
there would seem to be no way any thread could ever enter this clause.
The clause's code assumes that mutex->sem's value is 1 (because it
waits on it in order to restore its value to 0) and that the thread in
the clause is the last waiter on the semaphore (because it returns the
semaphore to the pool). But it seems to leave the mutex->order
semaphore hanging.
I assume this is a lack of imagination on my part: somehow, the
mutex's state has become uncertain, mutex->sem has been signaled more
times than expected (as far as I can tell, its value only ever veers
between 0 and -1), and a waiter died somewhere unexpectedly. But try
as I might, I can't imagine a set of threads and sequence of events
that would result in this code being executed.
Second: When might semaphore_wait_signal() return KERN_ABORTED? That
is to say (per semaphore_convert_wait_result()), what might cause
thread_block() to return THREAD_INTERRUPTED when assert_wait()ing with
interruptible state THREAD_ABORTSAFE? This question is prompted by
this bit from pthread_mutex_lock() (starting at line 316):
PTHREAD_MACH_CALL(semaphore_wait_signal(sem, order), kern_res);
while (kern_res == KERN_ABORTED)
{
PTHREAD_MACH_CALL(semaphore_wait(sem), kern_res);
}
This appears to be intended to ensure sem gets waited on no matter
what. Blocking on mutex->sem is essential to the mutex implementation:
mutex->order appears to ensure threads reach this section one-by-one
and queue up on mutex->sem in FIFO order. In order to block waiting
for the mutex to be unlocked, the thread has to wait on mutex->sem.
Perhaps this is just standard Mach kernel defensive coding? Or, more
likely, is there some essential contextual information I am unaware
of?
Thank you for your help,
—Jeremy
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden