Re: how do threads work?
From: Enrique Perez-Terron (enrio_at_online.no)
Date: 11/20/05
- Previous message: Andersen: "Re: how do threads work?"
- In reply to: Andersen: "Re: how do threads work?"
- Next in thread: Enrique Perez-Terron: "Re: how do threads work?"
- Reply: Enrique Perez-Terron: "Re: how do threads work?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Sun, 20 Nov 2005 01:15:36 +0100
On Sat, 19 Nov 2005 23:03:31 +0100, Andersen <andersen_800@hotmail.com> wrote:
>
> Enrique Perez-Terron wrote:
[...]
>> A process cannot consider to switch task unless the flow of instructions
>> brings it to a function that does such deliberations. While in the middle
>> of computing pi to one million decimals, the flow of instructions does
>> not get near any such function. To solve this, the process can ask the
>> kernel for a little help, in the form of regular timer signals.
>
> Right. Though I am curious how that would be implemented on a IA32 arch
> (Interrupts?).
In what way is this different for a IA32 arch processor? What other kind
of processors would you compare with?
At the level where the processor per se is visible, you have external chips
deliver interrupts to the processor, and all such interrupts invoke interrupt
handlers that run in kernel mode. All processors I know about invoke
interrupt handlers in whatever protection mode or ring level, or whatever
it's called, that is used by the kernel, and implies hardware access etc.
Remember, on a uniprocessor, when the kernel starts a process, the processor
starts executing instructions from that process' code, and the processor
by itself has no other means of being intelligent about what it is doing
than by executing instructions that are intelligently composed.
So, while the processor is executing the process' code, it has no other
intelligence than that which is implicit in that process. The kernel, at
that point in time is not a live being that can decide and act, it is just
a bunch of instructions lying idle in the memory, about like the letters in
a book in a shelf. Those instructions are powerless to look at the watch
every thousandth of a second, as long as those instructions are not
executed.
This is where the interrupt comes in. The processor is built that way, it
will not fetch and run the next instruction of the running program, it
will instead fetch and run instructions from an interrupt handler whose
address is found through a hardwired procedure. In this way, the kernel
regains control over the computer every while, thanks to the regular
interrupts from a timer circuit.
In order for a user-level library like a user-level threads library to
get notification at times when the thread (and therefore, the process) is
doing the proverbial computation of pi decimals, i.e., when the flow of
instructions does not naturally lead to functions in the thread library
(which could poll the os to learn how long the pi decimals have been
computing) -- you need something coming in from outside the process itself,
and that is the signal, which the kernel can deliver, prompted by a
hardware interrupt from an external (or internal, for that matter) circuit.
If you now ask, how does the kernel deliver signals, then we are no longer
talking about threads, but about the kernel and its processes (or tasks,
or kernel-level threads) in general. Whenever the kernel is running some
of its code, and is about to resume the active process, it checks the state
of the signal bits in the process (er, task) structure, and if one is set,
it invokes the process signal handler instead of the normal resumption
point - after arranging whatever messy details are required so the normal
resumption point can be resumed later, after the signal handler returns.
>> Signals do force an interruption of the flow of instructions. Once in
>> the signal handler, the threading library takes the steps needed to
>> "preempt" the computation of pi in favor of something else.
>>
>> One of the technical hurdles that such a threading library must overcome,
>> is to arrange for each "thread" to have a separate stack. It must be
>> posible
>> for one thread to unwind its stack even after another thread has spun
>> deeply into some recursion of its own.
>
> Would it not be quite simple to have multiple stacks, save their stack
> pointers on the heap of the thrd lib, and when context switching make
> sure that the right stack pointer is used poiting to the right place?
That is approximately what thread libraries do, as far as I know. There
is a list of tread structures, each containing the data needed to resume
that thread, just like the kernel maintains similar data for the proceses.
Each thread has a private stack region, and a resuption address on the stack.
The value of the stack pointer register for the thread is in one of three
places: in the library's tread structure, in the kernel's process structure,
or in the stack pointer register, when the thread is actually executing.
>> A problem with user-space threads is if one thread does a blocking read,
>> there is no way the thread library can switch to another thread without
>> aborting or completing that read. The threading library needs to replace
>> all blocking system calls with its own wrappers, which call non-blocking
>> equivalents, and take suitable control when that equivalent fails to
>> deliver immediately.
>
> Why is this a problem if your a using signals to preempt? I mean why
> replace blocking calls. Why not just use the signal, interrupt the
> blocking operation and context switch? Is it problematic to signal in
> the middle of a blocking call?
Because the blocking is at kernel level, and the kernel does "know" or care
that the process is multiple threads. The kernel simply blocks the process,
including the threading library.
When a signal arrives, the kernel must decide to deliver the signal, or not.
If it does, it must decide to abort the system call (returning with a status
of EINTR) or restart the system call. The latter means the control will go
back to the kernel after the signal handler finishes, and then back to the
program when the system call finishes.
In any case this is not dependent on the process being multithreaded.
Perhaps the signal handling routine can switch context and run another
thread while the kernel thinks you are still running a signal handler.
Now consider the following: a thread issues a system call of the restartable
variety, and a signal is delivered while this system call is incomplete.
The threading library receives the signal in its signal handler. The treading
library does not even know that the currently active thread is a blocked
in a system call. It has no way to know that it should switch context, and
not switch back, until that system call has returned.
Further, assume that the thread library switches context, and the new context
issues a second restartable system call. Just assume that both calls are
read calls that will transfer data from some external network connection
to a disk buffer. (I don't know what calls are actually restartable,
anybody can correct me here.) Now the kernel must handle two return
addresses for the process, one for each system call. It must ensure that
each return is associated with the correct number of bytes tranferred or
any other status information. Now you want the two threads to be resumed
with the correct status, no matter what system call finishes first.
I guess you see there is a can of worms here.
>> However, if a program uses a new kind of device, executes some ioctl's that
>> the threading lib authors were not aware of, or that did not even exist at
>> the time, then the threading lib will not have a wrapper for that.
>
> Again, why would it not work as the signal would interrupt this
> unexpected blocking operation?
I guess this is really the same question as above.
> Thanks a lot for your answers. This is exactly what I was looking for!
Just a final word: I'm not God. I'm not even a kernel programmer. I could
be mistaken. It's just my two cents.
-Enrique
- Previous message: Andersen: "Re: how do threads work?"
- In reply to: Andersen: "Re: how do threads work?"
- Next in thread: Enrique Perez-Terron: "Re: how do threads work?"
- Reply: Enrique Perez-Terron: "Re: how do threads work?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|