diff --git a/repos/libports/src/lib/pthread/thread.cc b/repos/libports/src/lib/pthread/thread.cc index f918894e91..c086008170 100644 --- a/repos/libports/src/lib/pthread/thread.cc +++ b/repos/libports/src/lib/pthread/thread.cc @@ -57,6 +57,53 @@ static __attribute__((constructor)) Thread * main_thread() } +void Pthread_registry::insert(pthread_t thread) +{ + /* prevent multiple insertions at the same location */ + static Genode::Lock insert_lock; + Genode::Lock::Guard insert_lock_guard(insert_lock); + + for (unsigned int i = 0; i < MAX_NUM_PTHREADS; i++) { + if (_array[i] == 0) { + _array[i] = thread; + return; + } + } + + Genode::error("pthread registry overflow, pthread_self() might fail"); +} + + +void Pthread_registry::remove(pthread_t thread) +{ + for (unsigned int i = 0; i < MAX_NUM_PTHREADS; i++) { + if (_array[i] == thread) { + _array[i] = 0; + return; + } + } + + Genode::error("could not remove unknown pthread from registry"); +} + + +bool Pthread_registry::contains(pthread_t thread) +{ + for (unsigned int i = 0; i < MAX_NUM_PTHREADS; i++) + if (_array[i] == thread) + return true; + + return false; +} + + +Pthread_registry &pthread_registry() +{ + static Pthread_registry instance; + return instance; +} + + extern "C" { /* Thread */ @@ -129,9 +176,10 @@ extern "C" { { Thread *myself = Thread::myself(); - pthread_t pthread = dynamic_cast(myself); - if (pthread) - return pthread; + pthread_t pthread_myself = static_cast(myself); + + if (pthread_registry().contains(pthread_myself)) + return pthread_myself; /* * We pass here if the main thread or an alien thread calls diff --git a/repos/libports/src/lib/pthread/thread.h b/repos/libports/src/lib/pthread/thread.h index f7a7741e74..4189197adc 100644 --- a/repos/libports/src/lib/pthread/thread.h +++ b/repos/libports/src/lib/pthread/thread.h @@ -18,6 +18,31 @@ #include +/* + * Used by 'pthread_self()' to find out if the current thread is an alien + * thread. + */ +class Pthread_registry +{ + private: + + enum { MAX_NUM_PTHREADS = 128 }; + + pthread_t _array[MAX_NUM_PTHREADS] = { 0 }; + + public: + + void insert(pthread_t thread); + + void remove(pthread_t thread); + + bool contains(pthread_t thread); +}; + + +Pthread_registry &pthread_registry(); + + extern "C" { struct pthread_attr @@ -50,6 +75,8 @@ extern "C" { { if (_attr) _attr->pthread = this; + + pthread_registry().insert(this); } /** @@ -62,6 +89,13 @@ extern "C" { { if (_attr) _attr->pthread = this; + + pthread_registry().insert(this); + } + + virtual ~pthread() + { + pthread_registry().remove(this); } void entry()