On 2012/3/20 1:50, John Baldwin wrote:
On Monday, March 19, 2012 11:41:53 am David Xu wrote:
On 2012/3/19 20:33, John Baldwin wrote:
On Saturday, March 17, 2012 8:22:29 pm David Xu wrote:
Author: davidxu
Date: Sun Mar 18 00:22:29 2012
New Revision: 233103
URL: http://svn.freebsd.org/changeset/base/233103
Log:
Some software think a mutex can be destroyed after it owned it, for
example, it uses a serialization point like following:
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&muetx);
They think a previous lock holder should have already left the mutex and
is no longer referencing it, so they destroy it. To be maximum compatible
with such code, we use IA64 version to unlock the mutex in kernel, remove
the two steps unlocking code.
But this means they destroy the lock while another thread holds it? That
seems wrong. It's one thing if they know that no other thread has a reference
to the lock (e.g. it's in a refcounted object and the current thread just
dropped the reference count to zero). However, in that case no other thread
can unlock it after this thread destroys it. Code that does this seems very
buggy, since if the address can be unmapped it can also be remapped and
assigned to another lock, etc., so you could have a thread try to unlock a
lock it doesn't hold.
They have handshake code to indicate that the mutex is no longer used by
previous
holder. e.g:
thread 1:
pthread_mutex_lock(&mutex);
done = 1;
pthread_mutex_unlock(&mutex);
thread 2:
pthread_mutex_lock(&mutex);
temp = done;
pthread_mutex_unlock(&mutex);
if (temp == 1)
pthread_mutex_destroy(&mutex);
Hmm, so how does this result in the crash you fixed? That is, thread 1 has
to fully finish pthread_mutex_unlock() before thread2's pthread_mutex_lock()
can succeed, so I don't see how thread 1 could still be in
pthread_mutex_unlock() when thread 2 calls pthread_mutex_destroy().
This is implementation detail,thread1 does unlocking in two steps:
first it clears lock bit, but leaves contention bit there,
then thread2 enters and sets lock bit, and then destroy it.
T1:
clear lock bit, contention bit is still set.
T2:
lock the mutex by setting lock bit.
do some work.
unlock the mutex by clearing lock it,
enters kernel, and see no waiters, clears contention bit.
destroy the mutex, unmap memory
T1:
enter kernel to clear contention bit, because the memory
is unmmaped, it returns EINVAL.
I guess one crash of Python is also caused by the logic, though they use
semaphore
instead of mutex + condition variable to mimic lock.
POSIX even explicitly requires a condition variable to be destroyable
after broadcast,
once you have correct teardown code. Please read its example section:
http://pubs.opengroup.org/onlinepubs/007904975/functions/pthread_cond_destroy.html
This is quite different as assuming a broadcast marks all the threads as
runnable
and removes them from the cv's queue, none of the threads will have references
to
the cv so it will be safe to destroy. It would not be safe to destroy the mutex
in that case though (and the example does not destroy the mutex, only the cv).
Please see section "Destroying mutexes":
http://pubs.opengroup.org/onlinepubs/007904875/functions/pthread_mutex_init.html
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"