Kernel-supported threading in user programs

Randy Chapman (chapman@cs.washington.edu)
Tue, 5 Mar 1996 22:21:58 -0800 (PST)


[copied to linux-kernel and linux-gcc as well as the original
linux-smp, where it was called RFC: Resource....]

On Tue, 5 Mar 1996, Martin v. Loewis wrote:

> > Whats wrong with the existing clone() syscall. That seems to provide all
> > you need for stuff like pthreads
>
> I think there is a problem with thread identification. On one hand, you want
> to identify each individual thread, to find out what context is current. This
> is a must for thread local storage.

getpid() will return the current thread id. The thread/process distinction
in Linux kernel seems pretty much nonexistant. All threads in a
"Multithreaded" application will show up in ps as separate processes.
GDB cannot deal with this well, either. I don't know gdb innards at
all, so i don't know how easily fixable that will be.

However, I'm also not sure this is the wrong thing. This makes the
kernel side of matter very simple and elegant. From the user side,
some clever use of tables and other trickeries can be used to bind
things together. Let me throw out some ideas here. (Note most
of my threaded programming is in Win32, my lowlevel threading
from java code, so ....)

When an application starts up, it will mmap() an area of memory in some
certain location. Perhaps this could be handled the same as loading
a shared library. Perhaps it would be *in* the threads library.
This area would then contain information about all the threads in
the given process. This area would not be allocated until the
threading system starts up (perhaps at application startup for
-lthreads applications, or perhaps when the program first requests
anotehr thread).

When the threading system starts up, the first task is to create a
"main" thread for the application to continue executing in. This
would be the new process from a clone(). The "old" original process
(which still shares memory, files, etc), would then jump out to
a special service-providing function and essentially become
a helper thread. It could control all thread creation, external
signal processing and would overall be a "front" for the application
as a whole. Anyone sending a signal to the application would
be sending it to this "thread".

ps would have to (somehow) have the know-how to not show the other
threds by default.. but this isnt critical. With the definite
global per-application dataset containing information about all
the threads, gdb *should* be able to manage. It will then be able
to suspend all threads when you break, etc.

> OTOH, you want to keep the concept of process, which is a collection of threads.
> You want to be able to kill a single thread, or the whole process.
> I didn't look close enough into pthreads to know whether this is really
> required, or clone, to say that this is not possible. I do believe it is
> a problem that there is no concept of 'thread id' in Linux.

Right. With the above, there is a "process" (the original PID),
and all threads have their own TID (their system PID).

> Another thing is stack management. Using clone, can you easily have multiple
> stacks for multiple processes? I was told Linux does not support that out of
> the box. So it looks like one has to make one's own stack management for the
> individual threads, probably using mmap(). Are then all stacks the same?
> I understand the stack grows dynamically in Linux. Would that hold for the
> other threads, too?

Out of the box, Linux has no helping support for kernel threading.
I believe you still have to make your own clone syscall even. You
can deal with stacks by mmap()ing a large area (remember to mprotect
the tail end of the stack!). This will give you a non-expandable
stack in a way.. however, it doesnt really use the memory until the
stack grows that large.

> I have to say that I'm looking at the whole issue not from a pthread point
> of view. My focus is Win32 emulation, where I found those two issues to be
> the biggest problems. We didn't move far enough yet to say whether clone is
> sufficient to emulate Win32 threads.

I think it cuold be done. You mention thread local storage. You'll
notice how this is tagged as an attribute in Win32. I believe
(please correct me if I'm wrong), that there is an invisible
dereference that ocurs any time you reference one of these. IE,
depending on which thread you are in, the address of the TLS
item is at a different place.

Although TLS can be implemented moderately easily, to do it as
smoothly as Win32 does will require compiler changes. It would
be informative to talk to the GNU-Win32 folks at Cygnus to see
what they are planning to do to deal with this.

--randy