This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: New pthreads library


   From: Ulrich Drepper <drepper@cygnus.com>
   Date: 27 Aug 1999 23:49:08 -0700

   Hi,

   I've taken a brief look at the code.  The model would currently not be
   usable for Linux due to missing functionality in the kernel.  We need
   this strange manager thread.  But this hopefully will change.

Thanks, for looking at the code.  When you say that `The model would
currently not be usable for Linux', do you mean that it would involve
a lot of work to merge the manager thread into my current approach,
which would be a lot of wasted effort since the missing functionality
is going to be added to the Linux kernel anyway?  Or do you mean that
there really is a fundamental reason why it would impossible to
implement the system dependent bits of code necessary in my
implementation for the current Linux kernels?

   The code itself looks quite reasonable though some things are really
   problematic: too many locks.  E.g., you use a lock to increment global
   variables.  This should not be necessary.  Most processors define such
   an instruction or a number of instructions.  I have added some time
   back the header atomicity.h in glibc and the functions contained
   should be used.  There are certainly some missing (e.g.,
   atomic_increment and atomic_decrement, which are less generic than
   atomic_add).

I agree that such optimizations should be made when they're possible.
However, I'm a little puzzled over the current implementation.  If
we're compiling the library for a processor that does not support all
atomic operations (e.g. the i386) the file
`sysdeps/generic/atomicity.h' is used.  The operations in this file
aren't really atomic.  Right now this is not a very big problem since
the only use of <atomicity.h> is in the profiling code
(elf/dl-profile.c and gmon/mcount.c), but in the threads library this
is unacceptable.  So in certain cases I'll have to fall back on using
locks.  Implementing atomic_increment on the i386 is not difficult at
all, so that'll defenitely do that.

   In this context I should complain a bit about the lack of comments.
   For code as complicated as the thread library I would like to see lots
   of comments.  I know that it seems early to do this but because you
   are not going to develop this code alone by yourself it is necessary
   to communicate the decisions.  E.g., from the brief look I was not
   able to see why you need the PTHREAD_COUNTED flag.

OK.  Adding comments is now top priority.  By the way, PTHREAD_COUNTED
is no longer there since it would prevent using atomic_increment as
you suggested.  There is also a comment now explaining the possible
race condition between pthread_create() and pthread_exit() that it was
supposed to solve.

   The next problem is the handling of thread descriptor.  We used to use
   the pointer to the data structures as the pthread_t element but
   stopped this.  I think the main reason was that it caused problems
   recognizing when a thread desriptor was illegal.  I personally don't
   think this is much of a problem.

Yes, pthread_join, pthread_detach and pthread_kill are supposed to
fail and return ESRCH if no thread with the specified thread ID could
be found.  For some other functions (for example pthread_getpriority)
this is a ``may fail'' condition, and the behaviour of pthread_equal
is undefined if the thread ID is invalid.  Back when I started I
discussed this with Roland McGrath and Thomas Bushnell.  They said
that making the pointer to the thread data structure the thread ID was
defenitely the right thing (and I agree), and said that this might
very well be that the intention of the standard was to make ESRCH a
``may fail'' condition in all cases.  I decided to keep things as they
are now until someone complains about it.

   What is a problem is that you dereference the pointer directly.  Maybe
   you should have taken a look at the LinuxThreads code.  Here I've
   added some time last year some changes which move the access in a
   macro.  E.g., instead of

	   thread->exited

   I would write

	   THREAD_GETMEM (thread, exited)

   The benefit of this is that on modern architectures with dedicated
   thread pointer registers (see SPARC) one could define THREAD_GETMEM as
   this:

	   register pthread_t *__thread_self __asm__ ("%g6");

	   #define THREAD_GETMEM(descr, member) __thread_self->member

   It should be obvious that this is much better.  Even for x86 it is
   possible to user this trick and the only reason I have not activated
   this so far in LinuxThreads is that there iss a kernel problem.  But
   for the Hurd you should be able to make it work.

Thanks for explaining what THREAD_GETMEM is for.  I didn't quite get
why this `ugflication' of the code was necessary.  Of course I never
looked at the SPARC code.  I will certainly convert my code to do
this, but I may postpone this until the code has stabilized a bit.

By `using this trick for the x86' you probably mean the approach laid
out in `linuxthreads/sysdeps/i386/useldt.h'.  Implementing this
approach for the Hurd should indeed be possible since Mach has the
necessary support for manipulating the LDT.  If you want to support
arbitrary stacks (_PTHREAD_STACKADDR and _PTHREAD_STACKSIZE support)
in an efficient way, such a mechanism is almost essential.

   A last point is no really criticism on your code.  I planned to revamp
   the entire thread library anyway.  One of the things I want to
   implement is the separation of kernel and user threads.  User level
   thread implementations have big advantages in some situations and I
   would like to have a combination.  I have not yet any concrete
   planning but I would have waited making with coming up with a new
   design until I have an indea how to tackle this problem.  At least the
   implementation should be general enough to allow this modified behaviour.

A while back, when you were hinting at a rewrite of the threads
library, you talked about a paper describing the new Mach 3.0 cthreads
library.  I belive the paper you were talking about is `Randall
W. Dean, Using Continuations to Build a User-Level Threads Library'.
I've read the paper and it seems like a good approach to me.  Anyway,
I'll design the public interfaces in such a way that moving
`one-on-one' model to the `many-on-many' model is possible.  I believe
that this only means that I must avoid exposing details about the
underlying kernel threads, which is a good goal anyway, and is not
hard to achieve.  Making sure that we can implement the the
`many-to-many' model later on without changing too much of the
internals is a bit more difficult, but I'll do my best.  I'll avoid
assuming that every thread is always tied to a kernel thread.  If you
have any other suggestions for things that I have to keep in mind,
please don't hesitate to mention them to me.

Mark

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]