csynchronizationmutexkernel-extensionxnu

Using synchronization efficiently in macOS kernel extension


I'm using synchronization KPI in my macOS kernel extension to verify that one function is fully performed before the other function starts (both functions are performed in different threads of course).

These are the synchronization methods :

msleep(void *channel,lck_mtx_t *mtx,int priority,const char *wmesg,  struct  timespec *timeout);
wakeup(void *channel);

So channel is a pointer to boolean value that represent first function was fully performed.

Here's my implementation in the first function:

OSIncrementAtomic(channel);
wakeup(channel);

And on the other function I wait for channel to be set:

msleep(channel, NULL, 0, "", ts);

However, in case the first function terminated before the second one (which is the common case), I shell wait for the timeout in ts for vein.

My question is whether there's a way to skip the msleep in case the wakeup already occurred ?

thanks,


Solution

  • Use lck_mtx_sleep_deadline() (or the IOLockSleepDeadline() wrapper) in connection with a mutex. On the thread that waits:

    1. Lock mutex
    2. Check wait condition (is first function still running?)
    3. If yes, call lck_mtx_sleep_deadline()
    4. Unlock mutex

    You may want to make steps 2+3 a while() loop depending on your situation.

    In your "first function":

    1. Lock mutex
    2. Clear wait condition (increment channel)
    3. Send wakeup to event. (e.g. thread_wakeup_prim((event_t) event, oneThread, THREAD_AWAKENED);)
    4. Unlock mutex.

    You can probably also do all of this with the lower-level msleep()/wakeup() directly somehow, but I'm not so familiar with that API.