|
Home > Archive > Unix Programming > October 2006 > how the thread.Sleep(Ta) is implemented with no kernel support
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
how the thread.Sleep(Ta) is implemented with no kernel support
|
|
| xu_feng_xu@yahoo.com 2006-10-19, 7:32 am |
| Hi,
I am just wondering how the sleep(Ta) function is implemented when
using user level thread with NO kernel support. i.e. the kernel is not
multithreaded?
The thread which calls the sleep(Ta) method will be switched to a
waiting state and it has to wait for "Ta" before being eligible for
execution again. however, if this period Ta is checked using the clock
timer, via a BLOCKING system call (e.g. nanosleep), the
(single-threaded) kernel will block the entire process. An undesired
situation since all the process threads get blocked despite that some
of them might be runnable.
so how the sleep function is implemented at the user level library,
without the kernel support, to avoid blocking all the process threads?
thanks
| |
| Nils O. Selåsdal 2006-10-19, 7:32 am |
| xu_feng_xu@yahoo.com wrote:
> Hi,
>
> I am just wondering how the sleep(Ta) function is implemented when
> using user level thread with NO kernel support. i.e. the kernel is not
> multithreaded?
>
> The thread which calls the sleep(Ta) method will be switched to a
> waiting state and it has to wait for "Ta" before being eligible for
> execution again. however, if this period Ta is checked using the clock
> timer, via a BLOCKING system call (e.g. nanosleep), the
> (single-threaded) kernel will block the entire process. An undesired
> situation since all the process threads get blocked despite that some
> of them might be runnable.
>
> so how the sleep function is implemented at the user level library,
> without the kernel support, to avoid blocking all the process threads?
In such a case, the scheduling is done by the user application that
places that thread outside a run queue for the period it wishes to
sleep. One way or another you fetch the current time, start a timer,etc.
so you can know how much time has elapsed in order to wake up threads.
If no thread is eligible to run it calls on a kernel service to halt the
entire process..
If you're asking about a specific userspace only threading package,
state which you're asking about. Commonly native threading on unixes
rely heavily on kernel specific features to implement threads.
| |
| Kaz Kylheku 2006-10-19, 1:21 pm |
|
xu_feng_xu@yahoo.com wrote:
> Hi,
>
> I am just wondering how the sleep(Ta) function is implemented when
> using user level thread with NO kernel support.
sleep() is a very old function, which dates back to Unix with no
threads.
It has always been implemented with kernel support.
No idea what this "thread.Sleep" thing is that you are talking about in
the subject line.
You seem to think that everyone can just look into a magic crystal ball
and know what programming language and library you are talking about.
> i.e. the kernel is not multithreaded?
Which kernel?
> The thread which calls the sleep(Ta) method will be switched to a
> waiting state and it has to wait for "Ta" before being eligible for
> execution again. however, if this period Ta is checked using the clock
> timer, via a BLOCKING system call (e.g. nanosleep), the
> (single-threaded) kernel will block the entire process.
The POSIX nanosleep function does not block the entire process. That
would be broken behavior. Neither Solaris nor Linux have that broken
behavior, so why are you crossposting this to Solaris and Linux
newsgroups?
Why don't you find a newsgroup that discusses the programming toolkit
which you are using, and the limitations of its threading library?
> so how the sleep function is implemented at the user level library,
> without the kernel support, to avoid blocking all the process threads?
It is possible to have a sleep function in a user-space threading
library, which does not block all the threads. Only, you don't want to
call it sleep(), since that symbol is already taken. What that function
does is simply deschedule the thread, and mark it for wakeup at some
later time. The scheduler will make that thread runnable when the time
comes and dispatch it when (for instance) it gets to the head of the
run queue.
The user-space thread scheduler has some low-priority idle task which
calls a blocking function in the kernel when no other threads are
runnable. That blocking function might be poll() or select() so that
when I/O arrives, the process will be able to wake up and dispatch a
thread to it.
Take a look at GNU Pth and others.
| |
| David Schwartz 2006-10-19, 7:23 pm |
|
xu_feng_xu@yahoo.com wrote:
> I am just wondering how the sleep(Ta) function is implemented when
> using user level thread with NO kernel support. i.e. the kernel is not
> multithreaded?
The threading library marks the thread as 'not ready to run' and sets a
timer to mark the thread 'ready to run' after the appropriate amount of
time. Then it calls the scheduler. If another thread is 'ready to run',
the scheduler (part of the user-space threading library) will run that
thread. If not, the scheduler will wait for a timer or event to occur.
> The thread which calls the sleep(Ta) method will be switched to a
> waiting state and it has to wait for "Ta" before being eligible for
> execution again. however, if this period Ta is checked using the clock
> timer, via a BLOCKING system call (e.g. nanosleep), the
> (single-threaded) kernel will block the entire process. An undesired
> situation since all the process threads get blocked despite that some
> of them might be runnable.
Right, so the threading library definitely won't do that. If no threads
are ready to run, it will compute when the earliest timer will fire and
'nanosleep' for that amount of time. If any threads are blocked on
socket I/O, it may block in 'poll' or 'select' for up to that amount of
time. It's up to the scheduler to find the right way to do it.
> so how the sleep function is implemented at the user level library,
> without the kernel support, to avoid blocking all the process threads?
The library marks the calling thread as not ready to run, sets a timer
to mark it ready to run in the right amount of time, then calls its
scheduler.
DS
| |
| xu_feng_xu@yahoo.com 2006-10-20, 7:23 pm |
|
David Schwartz wrote:
> xu_feng_xu@yahoo.com wrote:
>
>
> The threading library marks the thread as 'not ready to run' and sets a
> timer to mark the thread 'ready to run' after the appropriate amount of
> time. Then it calls the scheduler. If another thread is 'ready to run',
> the scheduler (part of the user-space threading library) will run that
> thread. If not, the scheduler will wait for a timer or event to occur.
but this where my confusion lies, how can the thread library set a
(software) timer that run concurrently with another thread in a single
processor? if it has to program the (hardware) timer, this has to be
done through a (blocking?) system call
| |
| Kaz Kylheku 2006-10-20, 7:23 pm |
| xu_feng_xu@yahoo.com wrote:
> but this where my confusion lies, how can the thread library set a
> (software) timer that run concurrently with another thread in a single
> processor?
A software timer is just a name for a higher level utility that is
built on the hardware timer. It means that you aren't taking the event
as an interrupt service routine call directly. The hardware event is
hidden under a higher level abstraction.
That abstraction can let you do things, for instance, like creating
hundreds of timers which you can start and stop individually. It makes
sense to call these "software" timers because your system does not have
hundreds of hardware timers. There may be only one underlying hardware
timer driving everything.
> if it has to program the (hardware) timer, this has to be
> done through a (blocking?) system call
A blocking system call means that the caller is put to sleep until some
(interrupt-driven) event happens.
Reprogramming the interrupt timer would be done synchronously using
programmed I/O: simply storing values in some hardware registers. No
sleep required to wait for any event, and so that is not a blocking
system call.
Software timers usually don't reprogram the hardware. That would be a
special technique in real-time embedded systems that need an accurately
timed event.
Typically, the timer is programmed to deliver an interrupt periodically
at fixed intervals. A software timer is simply an event generated in
response to the interrupts generated by the hardware timer.
There could be a second timer dedicated for these events. E.g. the
regular clock tick might go off 100 times per second (10 ms periods),
but through some special functions, a task could arrange for a one
millisecond period, using an auxiliary timer.
| |
| David Schwartz 2006-10-21, 1:27 am |
|
xu_feng_xu@yahoo.com wrote:
> but this where my confusion lies, how can the thread library set a
> (software) timer that run concurrently with another thread in a single
> processor? if it has to program the (hardware) timer, this has to be
> done through a (blocking?) system call
It simply makes a note that it has set a timer. There's nothing special
that it needs to do.
If it has some other thread that's ready-to-run, it simply runs that
thread. If it there's no other thread that's ready-to-run, it
calculates how long until the first timer and blocks for that long.
All the library has to do is make a note that the thread needs to be
rewoken at a particular time. When it later enters the scheduler, it
checks the time, and if it's after the time any timers should have
fired, it calls them.
In pseudo-code:
For the sleep function:
1) Set a timer to mark the thread ready-to-run at the correct time.
(Which usually just means allocating some memory for a timer object,
filling in the values, and adding it to a list.)
2) Mark this thread not ready to run.
3) Call the scheduler.
For the scheduler:
1) Check the current time.
2) See if any timers need to fire, if so call them now.
3) If any threads are ready-to-run, run them and go back to step 1
4) Block the process for up to the time until the first timer needs to
fire. (This mean blocking in 'nanosleep' if no threads are waiting for
I/O. If any threads are waiting for I/O, this may mean blocking in
'select' or 'poll'.)
DS
|
|
|
|
|