Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Kernel Recursive mutexes 10.4.9 ++



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: http://lists.apple.com/mailman/options/darwin-dev/email@hidden

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: http://lists.apple.com/mailman/options/darwin-dev/email@hidden

This email sent to email@hidden
References: 
 >Kernel Recursive mutexes 10.4.9 ++ (From: Erez Kaplan <email@hidden>)
 >Re: Kernel Recursive mutexes 10.4.9 ++ (From: Terry Lambert <email@hidden>)
 >Re: Kernel Recursive mutexes 10.4.9 ++ (From: Erez Kaplan <email@hidden>)
 >Re: Kernel Recursive mutexes 10.4.9 ++ (From: Terry Lambert <email@hidden>)
 >Re: Kernel Recursive mutexes 10.4.9 ++ (From: Erez Kaplan <email@hidden>)
 >Re: Kernel Recursive mutexes 10.4.9 ++ (From: Terry Lambert <email@hidden>)
 >Re: Kernel Recursive mutexes 10.4.9 ++ (From: Erez Kaplan <email@hidden>)
 >Re: Kernel Recursive mutexes 10.4.9 ++ (From: Terry Lambert <email@hidden>)



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.