[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: Design hole in nptl (and more general in POSIX threads)

Dragiša Durić <dragisha ho com> writes:
>   What bothers me now is... What procedures in pthread API are async
> safe? Boehm GC uses pthread_self(), as probably you too are using. Is it
> safe to use pthread_key_getspecific()?

At the end of section 2.4 of the POSIX System Interfaces spec, it
lists all the functions that are async-safe.  Not a single pthread_*
function is async-safe.

Boehm does call pthread_self, which is thus not kosher.  (But in some
sense, the Boehm GC is all about taking advantage of non-guaranteed
behavior, as carefully as possible, and getting surprising results.)

It's my intent for my code uses only promised behavior of POSIX and
ISO C facilities.  Where I need things they don't give me, I try to
use explicitly supplied compiler- or architecture-specific things,
like mn__arch_memory_barrier and mn__arch_code_modified.

Instead of calling pthread_self, I have a struct for each thread,
declared with the __thread storage qualifier (which I'm calling
mn__per_thread in my code).  Using __thread variables is async-safe.

I also have a pthreads thread-specific value that points to that
struct.  This sounds redundant, but here's the rationale:

    /* This is kind of dumb, but we need both 'thread_self' and

       - We need to access our 'struct thread' from gc_pause_signal's
         handler.  pthread_getspecific isn't async-safe, but
         mn__per_thread is.

       - We need to remove this thread from the global thread list when it
         dies.  You can't define destructor functions for mn__per_thread
         objects, but you can for thread-specific values.

       Boehm has a hash table mapping pthread_t values onto his thread
       structures, and he knows the hash table isn't being modified while
       he's stopping threads, so his signal handler just calls
       pthread_self (which isn't officially async-signal-safe, but geez)
       and looks itself up.  Maybe we should do that, too.  */

    /* A 'struct thread' instance for each thread.  */
    static mn__per_thread struct thread thread_self;

    /* A thread-specific value pointing to thread_self.  */
    static pthread_key_t thread_self_key;

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]