Re: Kernel Recursive mutexes 10.4.9 ++
Re: Kernel Recursive mutexes 10.4.9 ++
- Subject: Re: Kernel Recursive mutexes 10.4.9 ++
- From: Alexei Kosut <email@hidden>
- Date: Thu, 19 Jul 2007 09:30:32 -0700
On Jul 19, 2007, at 12:26 AM, Terry Lambert wrote:
I avoided that solution because it fosters a reliance on recursive
mutexes, and you tend to end up with subtle bugs in your code, if
you depend on them. But yes, it's possible to build a recursive
mutex construct from non-recursive mutexes.
Erez doesn't mention what type of kernel code he's writing, but it
might be worth pointing out that IOKit has a recursive mutex
implementation (IORecursiveLock) that is available.
Alexei
I'd caution you on a couple of things:
(1) your increments and decrements need to use atomic instructions
(2) the mutex should be held over an increment/decrement; if it's
not, you will need to set up a retry, probably with a condition
variable
(3) it's possible to not hold the mutex over the decrement, but
your objects would need to be create-once (it's probably too rough
to go down that path, unless you are going to refactor your code
anyway).
(4) you are not going to be able to just declare static instances
of these things; you will need an initializer function of some kind
(minimally, you will need to initialize the interior mutex).
-- Terry
On Jul 19, 2007, at 12:12 AM, Erez Kaplan wrote:
Terry,
OK, got the idea of that solution.
I found another reference to this issue, is it a good one and does
it cover my needs?
>
> typedef struct pthread_mutex_recursive_np_t {
> pthread_mutex_t mutex;
> pthread_t owner;
> UInt32 count;
> } pthread_mutex_recursive_np_t;
>
> void pthread_mutex_lock_recursive_np
(pthread_mutex_recursive_np_t *mutex)
> {
> pthread_t self;
>
> self = pthread_self();
> if (mutex->owner != self)
> {
> pthread_mutex_lock(&mutex->mutex);
> mutex->owner = self;
> mutex->count = 1;
> }
> else
> mutex->count += 1;
> }
>
> void pthread_mutex_unlock_recursive_np(pthread_mutex_recursive_np_t
> *mutex)
> {
> if (--mutex->count == 0)
> {
> mutex->owner = NULL;
> pthread_mutex_unlock(&mutex->mutex);
> }
> }
======= Cheers, Erez
On Jul 19, 2007, at 10:01 AM, Terry Lambert wrote:
If funcB has to be callable unlocked somewhere, then:
funcA() {
lock mutex
funcB_locked()
do stuff...
unlock mutex
}
funcB() {
lock mutex
funcB_locked()
unlock mutex
}
/* MUST be called with mutex held! */
funcB_locked()
{
do stuff...
}
We do this sort of thing in the kernel in a number of places,
where reference counts would be inappropriate.
-- Terry
On Jul 18, 2007, at 9:36 PM, Erez Kaplan wrote:
Terry,
Thanks for the explanation.
I am facing a some what strange sequence of calling (forced by
PC porting) which looks something like this:
Currently I get a deadlock situation.
How would you outline handling this deadlock?
funcA() {
lock mutex
funcB()
do stuff...
unlock mutex
}
funcB() {
lock mutex
do stuff...
unlock mutex
}
Cheers, Erez
On Jul 19, 2007, at 7:24 AM, Terry Lambert wrote:
On Jul 18, 2007, at 8:54 PM, Erez Kaplan wrote:
On Jul 18, 2007, at 10:00 PM, Terry Lambert wrote:
On Jul 18, 2007, at 2:37 AM, Erez Kaplan wrote:
Hi,
10.4.9+ 10.5
How do I obtain a Kernel Recursive mutexe?
The available api does not support this.
lck_mtx_alloc_init(gmutex_grp_m, LCK_ATTR_NULL)
You don't; this is what reference and use counts are for.
Can you explain a bit more or give reference to an example.
For example, all thread reentrant FSs will take an I/O
reference on a vnode, and use that reference to prevent the FS
from being unmounted out from under an operation in progress,
rather than holding a lock over the complete operation (thus
unnecessarily serializing all other I/O to the vnode). Here is
a simplified design pattern:
some function(object)
lock mutex
atomic increment reference count
unlock mutex
... long duration operation ...
lock mutex
atomic decrement reference count
unlock mutex
/* wake up destroy routine; destroy routine may fail
acquisition race */
if !reference count
wakeup(object)
...
destroy(object)
lock mutex
again:
/* Don't destroy the object while someone is using it */
if reference count
msleep(mutex, object)
goto again /* avoid race */
/* last reference gone, OK to kill it */
destroy object
unlock mutex
-- Terry
//======================
Erez Kaplan
Senior software engineer OSX
email@hidden
//======================
//======================
Erez Kaplan
Senior software engineer OSX
email@hidden
//======================
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden