Re: Synchronizing tsleep() and wakeup()
Re: Synchronizing tsleep() and wakeup()
- Subject: Re: Synchronizing tsleep() and wakeup()
- From: Nikita Danilov <email@hidden>
- Date: Mon, 2 Aug 2004 23:21:20 +0400
Eric Long writes:
>
Hi,
>
>
I've been trying to use tsleep() and wakeup() in a kernel extension, but it
>
isn't obvious to me how to enforce synchronization of these calls. (Likely,
>
this isn't the right mechanism for what I want. But, since I'm not sure
>
what I need to use, I'm bringing it up here.)
>
>
My goal is to put a thread Y to sleep until a condition is met or a time out
>
occurs. Thread Z is manipulating the condition, then calling wakeup on
>
Thread Y when it changes. But if thread Z's timing is just right (or should
>
I say wrong) thread Y may call tsleep after thread Z has decided whether or
>
not to wake it up.
Traditional UNIX tsleep/wakeup mechanism requires some external
synchronization that guarantees that thing you are describing is
impossible. For example, code in BSD portion of XNU that uses
tsleep/wakeup is usually executed under (or should I say `within'?) a
funnel, so that checking condition and entering tsleep occurs atomically
with respect to the wakeup calls (funnel is automatically released by
low-level scheduler code when thread actually blocks).
If you don't want to use funnels, you can resort to MACH synchronization
primitives, but I, personally, wouldn't recommend this, because they
seem to be designed for programming model different than one normally
employed by UNIX kernel code. For example, MACH semaphore remembers
thread that created it, and can only be destroyed by this thread. This
makes it impossible to embed such a semaphore into dynamically
allocated memory object (like inode). Moreover, all semaphores created
by a thread are automatically destroyed when thread exits. This seems to
target applications like MACH servers.
The simplest route is to create your own condition variable
implementation directly on top of MACH wait_queue_* API and usimple
locks (do _not_ use simple lock: this API is preprocessed to
nothing). If you don't need bells-and-whistles like time-outs, condition
variables (cond_init, cond_wait, cond_signal, and cond_broadcast) would
require only few dozen lines of C code.
This, by the way, reminds me of some problem: osfmk/kern/kern_types.h
doesn't export real struct wait_queue. Instead is defines a placeholder
of the same size. This means, that initializer also cannot be
provided. That is, one cannot write something like
static struct wait_queue wq = WAIT_QUEUE_INIT(&wq);
This is cumbersome, and it would be really nice if Apple people added
initializer macros for internal kernel data-structures.
Nikita.
>
>
Searching for a condition lock, I came to this page:
>
>
<http://developer.apple.com/documentation/Darwin/Conceptual/KernelProgrammin
>
g/synchronization/chapter_15_section_3.html#//apple_ref/doc/uid/TP30000905-C
>
H218-TPXREF109>
>
>
Which says:
>
>
> The BSD portion of Mac OS X provides tsleep, wakeup, and wakeup_one, which are
>
> equivalent to condition variables with the addition of an optional time-out.
>
> Since they are more commonly used for waiting a predetermined period of time,
>
> these calls are discussed in more detail in the section 3Using tsleep2 as part
>
> of the 3Miscellaneous Kernel Services2 chapter.
>
>
In my case, I'm not waiting for a predetermined amount of time. In fact, I
>
may not need to wait at all, if the other thread has changed the value, and
>
ultimately I only want to sleep until the value has changed or we time-out
>
and give up waiting for the change.
>
>
What's the best way to do this in the kernel?
>
>
>
Thanks,
>
>
>
Eri
_______________________________________________
darwin-kernel mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/darwin-kernel
Do not post admin requests to the list. They will be ignored.