Re: Synchronizing tsleep() and wakeup()
Re: Synchronizing tsleep() and wakeup()
- Subject: Re: Synchronizing tsleep() and wakeup()
- From: Jim Magee <email@hidden>
- Date: Mon, 2 Aug 2004 20:00:21 -0400
On Aug 2, 2004, at 3:21 PM, Nikita Danilov wrote:
>
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).
Yep.
>
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.
Not quite. Mach semaphores are associated with tasks, not threads, and
can be destroyed by any thread which has a handle to the task in
question.
>
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.
The simplest route is to use the mechanism provided by the subsystem
your KEXT lives in. What kind of kext are you writing?
>
>
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.
This was on purpose. Initialization may not be possible with a macro
in some situations - and we don't want to have to get a recompiled kext
when it isn't. That's why there is a wait_queue_init() function
instead. But that is marked as OBSOLETE. You should be using
wait_queue_alloc() if you are going to use any of these interfaces at
all - but doing so will require you to link against a specific version
of the kernel and/or have to recompile more often that you may like.
That's because the raw wait queue mechanisms are NOT part of the Kernel
Programming Interfaces (KPIs) recently announced for Darwin 8 and
beyond. Sure, the wait_queue_alloc() interface is not going away
anytime soon. But to access it you will have to link against the
legacy kernel symbol set (Darwin 6 symbols) and nothing else. Either
that or against each specific kernel version if you need any of the
new kernel interfaces beyond those in Darwin 6 (and will not be able to
load against subsequent kernel versions without a recompile/relink of
your kext).
--Jim
[demime 0.98b removed an attachment of type application/pkcs7-signature which had a name of smime.p7s]
_______________________________________________
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.