How to reach owner SWITCHING but no waiters in 10.5.8 pthread_mutex_lock?
site_archiver@lists.apple.com Delivered-To: Darwin-kernel@lists.apple.com Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:mime-version:received:from:date :message-id:subject:to:content-type:content-transfer-encoding; bh=gqlVlAenaa0UKE9UivMfQz8ZD2K6JqHVJVKcFaQSWh4=; b=H5ainNh4PJ8Kcs4e2uYl2tt4AnwyUBrYGoDOtW4hPYH2l37dkcnZfKWo+jMx14rV0+ Q8fD4OKDSClpOgOs9fxzBisPa+pfTBaAgr7Qb5U5H5eoJshh+vIEyfI2QWLXFr6tsbvv AbmC8ci8m8oeP/klsUDMZctITt9sNIkO+Mems= Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:from:date:message-id:subject:to:content-type :content-transfer-encoding; b=h8foolS+944OoNvsV3BOMkMH86bX2ja23Z1Vr2DCnAWL2OScneZhuC8eadU80h3L7h xlslo1J/v0NEKQvcKA/nts8prvbSJ2mEA5h4UfsftUoHigF2o0nzH2wjj90xcESYFi7E mie6VP/h/oTVZDxbTjKjLoQ0SQKrvIHkPgSYY= 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 (Darwin-kernel@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-kernel/site_archiver%40lists.a... This email sent to site_archiver@lists.apple.com
participants (1)
-
Jeremy W. Sherman