Re: Synchronizing tsleep() and wakeup()
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 | darwin-kernel@lists.apple.com Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/darwin-kernel Do not post admin requests to the list. They will be ignored.
participants (1)
-
Jim Magee