Subject: CVS commit: [wrstuden-fixsa] src/lib/libpthread
To: None <source-changes@NetBSD.org>
From: Bill Stouder-Studenmund <wrstuden@netbsd.org>
List: source-changes
Date: 11/04/2007 04:27:00
Module Name:	src
Committed By:	wrstuden
Date:		Sun Nov  4 04:27:00 UTC 2007

Modified Files:
	src/lib/libpthread [wrstuden-fixsa]: pthread.c pthread_cond.c
	    pthread_int.h pthread_lock.c pthread_mutex.c pthread_run.c
	    pthread_rwlock.c pthread_sa.c pthread_sig.c pthread_sleep.c sem.c

Log Message:
Check in changes to locking behavior.

pthread__sched() now takes a parameter indicating if the run queue is
already locked. Useful in cases where we already hold pthread__runqueue_lock.

pthread__suspend() now requires callers explicitly lock pthread__runqueue_lock
so we avoid issues with locking order regarding pt_statelock.

Adjsut our lock hierarchy. pthread__runqueue_lock is now above
pt_statelock, triggering the above adjustments. Adjust a lot of routines
as a result. Also move pt_siglock way up in the hierarchy, making
pthread__kill() not violate locking. Add a few extra locks to the list.

Adjust a botch in how pthread_join() used pthread-spintrylock().

pthread_cancel() now correctly walks up the locks with thread->pt_sleeplock.
We can't just lock it, as it points to a lock in the top locking rung. So
try locking, and if it fails, unlock and re-lock. Add code to cope with
the target thread not being in the expected state (which was on a
blocked queue) after we get all the locks.

Add comments to describe what's going on in places that I got confused.

Now that pt_statelock is lower in the locking order than
pthread__runqueue_lock, we can explicitly lock a thread's state before
we take it off the run queue. Adjust sched_yield() accordingly and
add some locking calls that were commented out before (as they'd have
been locking violations).

pthread_next(): now that we can lock the state lock while holding the run
queue lock, do so. Set a thread's state to PT_STATE_RUNNING before we
pull it off the run queue. Since we always are going to switch to it,
set pt_vpid and pt_lastlwp while setting the state. pthread_next
callers now _don't_ set these values.

pthread__kill(): grab pthread__runqueue_lock before target->pt_statelock.
If we want to target a thread that is on a blocked queue, do the
pthread_spintrylock() dance. Unlock all three locks we're running around
with, lock target->pt_sleeplock, then re-lock them all. After we lock,
make sure that the thread's still on a blocked queue before proceeding. If
it's not, either exit (if we wanted to wake out of sigtimedwait())
or start it all over. If the thread has gone live, it may have blocked
our signal and it'd be quite weird to get a signal you'd disabled, just
because the signaller had been running before you blocked it.


To generate a diff of this commit:
cvs rdiff -r1.48.6.3 -r1.48.6.4 src/lib/libpthread/pthread.c
cvs rdiff -r1.18.12.1 -r1.18.12.2 src/lib/libpthread/pthread_cond.c
cvs rdiff -r1.34.4.3 -r1.34.4.4 src/lib/libpthread/pthread_int.h
cvs rdiff -r1.14 -r1.14.6.1 src/lib/libpthread/pthread_lock.c
cvs rdiff -r1.22.4.1 -r1.22.4.2 src/lib/libpthread/pthread_mutex.c
cvs rdiff -r1.18.12.3 -r1.18.12.4 src/lib/libpthread/pthread_run.c
cvs rdiff -r1.13.6.1 -r1.13.6.2 src/lib/libpthread/pthread_rwlock.c
cvs rdiff -r1.37.6.3 -r1.37.6.4 src/lib/libpthread/pthread_sa.c
cvs rdiff -r1.47.4.5 -r1.47.4.6 src/lib/libpthread/pthread_sig.c
cvs rdiff -r1.7.6.1 -r1.7.6.2 src/lib/libpthread/pthread_sleep.c
cvs rdiff -r1.9.6.1 -r1.9.6.2 src/lib/libpthread/sem.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.