lkml.org 
[lkml]   [1999]   [Jul]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: kernel thread support - LWP's
Date
From

Khimenko Victor wrote:
> Hmm. I know it's not really related to linux-kernel but still... WHY glibc
> is getting 20 usecs or so and can it be shrinked down to 3 usecs ? Usually
> peoples (like Apache developers, for examle) do not use clone(), it uses
> pthreads: clone is nice and all but it's non-portable...

pthread_create() has to do a hell of a lot more work than just clone().
Part of this is the ugly implementation, part is (I think) intrinsic to the
attempt to stack POSIX thread semantics on top of clone().

There is an internal thread used by libpthread. It's called the "manager".
It gets created the first time you call pthread_create. It sits blocked
in select() on a pipe.

Assuming the manager is already active, pthread_create writes a message down
that pipe saying "please create another thread". The manager wakes up and
creates a new child, which involves a pile of work both before and after the
call. In the end it kicks the original thread back awake with a signal.

The minimum sequence is

<calling thread>
write
sigsuspend
<switch to manager>
select returns
getppid
read
geteuid
mmap, twice
clone
<switch to child>
getpid
<back in manager>
kill
select
<calling thread is awake again>

That's _minimum_. Add at least two calls to sched_setscheduler (one parent,
one child) if you run RT threads. There might be N calls to waitpid in
between getppid and read. Plus there's a bunch of copying data around in
user space. There are some mutexes that have to be acquired and dropped.
Etc.

Why is it doing all this crap? Because of another requirement of the POSIX
thread spec, which hasn't got any air in the conversation yet: Any thread in
the process can do the equivalent of waitpid for any other thread in the
process. Linux doesn't allow that; you can only wait for a task that you
yourself spawned (unless you are init). The workaround is to make all the
threads children of the "manager". It waits for them and passes back exit
statuses to the threads calling pthread_join.

There's another lovely detail: The "initial thread" (the one that was
executing before the first call to pthread_create) isn't a child of the
manager; it's the parent of. Per POSIX, the manager has to notice when the
initial thread goes away and kill all the others. That's why there is a
getppid in the above. The select times out every two seconds just so it can
check.

---

If there were a way to specify - ideally at clone time - that any task in
some group (process group would be fine with me) can wait for this child,
then the above gunk could be reduced to clone() plus the work of setting up
the child's stack (the mmaps) and user-level context (data for
pthread_setspecific, per-thread errno, etc.) And that would get you a hell
of a lot closer to 3usec thread create times. If you had a
CLONE_VM_WITH_NEW_STACK that created a new stack for the child (still visible
to both) then more overhead would go away, plus clone() wouldn't need a
special assembly stub that only works if you use CLONE_VM.

It would also be handy to have a "disown" call which had the effect of
immediately reparenting the target process to init. Currently "detached
threads" have to be waited for too.

zw

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:53    [W:0.083 / U:0.272 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site