Re: gthread-win32.c

On Tue, 15 May 2001, Steven Brooks wrote:

> > There is no reliable way to control another thread with suspends and
> > resumes, because you have no idea what it's doing. This type of
> > technique is best left to debuggers and garbage collectors.
> Actually, you can know what it was doing.  For example, after signalling
> ``make me wait on this event'', it would enter a while loop examining a
> volatile variable which the event manager controls.  It would be
> suspended while in this while loop, and woken up with the variable
> changed so it would exit the while loop and continue executing:
> wait_for_event(event):
> 	1. volatile var <- true
> 	2. msg <- { this_thread, "wait-for-event", &event, &var }
> 	3. send msg to manager
> 	4. while var
> 		5. give up timeslice

Okay. But here the suspend and resume here are not essential to the
algorithm. The thread is known to be in some idle loop, so as an
optimization it can be suspended. Until that happens, it burns cycles,
so this is clearly not perfect. The thread could use its entire
remaining timeslice until the manager is dispatched to process the
message, and perform the suspension.

Also, one problem here is that if you want to use priorities, the
waiting thread better not have a higher priority than the manager,
because it's then not possible to give up a timeslice to it. The while
loop will lock out the manager. So for priority support, the
manager must have a equal or higher priority than any other thread
which uses wait_for_event().

> Obviously, var would not actually be on the stack (since stacks are not
> shared between threads).

Stacks are shared between threads on POSIX and Win32, but I
don't know what the exact platform portabiilty requirements are for
glib.  So at least on some platforms, you can use automatic storage for
wait-related objects such as wait queue nodes, reply boxes, flags or
whatever. The Linux kernel makes good use of this idea---task wait
structs are in automatic storage. The technique is also exploited in
recent LinuxThreads to implement timed-out mutex waits.

> However, your idea sounds more promising anyway.  One concern is, how
> do you get rid of the race condition between when a thread adds itself
> to the queue and when it waits on its own event?

There is no race condition, see below.

> Unless you make the
> thread events manual-reset, you still have the potential for a lost
> event.

Events have a ``set'' state which remembers the signal. So if a thread
is removed from the queue and its event is fired before it has reached
the wait operation, the event stays set.  Then when the thread finally
executes the wait, it will fall through, thereby resetting the event.
So the atomicity of giving up the queue lock and suspending is glued
together by the stateful nature of the event.

Where things get a little tricky is in handling wakeups due to timeout.
This case can must be detected and then the queue must be dealt with.
The woken thread looks for itself in the queue. If it is no longer on
the queue, then some other thread must have succeeded in dequeueing it,
and hence the auto-reset event is going to be signaled soon, if indeed
it has not already.  If the thread doesn't consume that signal right
away with an extra wait operation, it will get a spurious wakeup later.
If you allow for such spurious wakeups, then you have to check the
queue after each wait, timed out or not, since it can't be assumed that
the thread has been dequeued when the event is fired.

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]