diff --git a/repos/libports/src/lib/libc/rwlock.cc b/repos/libports/src/lib/libc/rwlock.cc index 102939337..f96238e98 100644 --- a/repos/libports/src/lib/libc/rwlock.cc +++ b/repos/libports/src/lib/libc/rwlock.cc @@ -91,10 +91,23 @@ extern "C" { { }; + static int rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) + { + static Genode::Lock rwlock_init_lock { }; + + if (!rwlock) + return EINVAL; + + try { + Genode::Lock::Guard g(rwlock_init_lock); + *rwlock = new struct pthread_rwlock(); + return 0; + } catch (...) { return ENOMEM; } + } + int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { - *rwlock = new struct pthread_rwlock(); - return 0; + return rwlock_init(rwlock, attr); } int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) @@ -105,12 +118,26 @@ extern "C" { int pthread_rwlock_rdlock(pthread_rwlock_t * rwlock) { + if (!rwlock) + return EINVAL; + + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + if (rwlock_init(rwlock, NULL)) + return ENOMEM; + (*rwlock)->rdlock(); return 0; } int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) { + if (!rwlock) + return EINVAL; + + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + if (rwlock_init(rwlock, NULL)) + return ENOMEM; + (*rwlock)->wrlock(); return 0; } diff --git a/repos/libports/src/lib/libc/thread.cc b/repos/libports/src/lib/libc/thread.cc index 0c7b74222..935963eba 100644 --- a/repos/libports/src/lib/libc/thread.cc +++ b/repos/libports/src/lib/libc/thread.cc @@ -639,15 +639,26 @@ extern "C" { } - int pthread_cond_init(pthread_cond_t *__restrict cond, - const pthread_condattr_t *__restrict attr) + static int cond_init(pthread_cond_t *__restrict cond, + const pthread_condattr_t *__restrict attr) { + static Genode::Lock cond_init_lock { }; + if (!cond) return EINVAL; - *cond = new pthread_cond; + try { + Genode::Lock::Guard g(cond_init_lock); + *cond = new pthread_cond; + return 0; + } catch (...) { return ENOMEM; } + } - return 0; + + int pthread_cond_init(pthread_cond_t *__restrict cond, + const pthread_condattr_t *__restrict attr) + { + return cond_init(cond, attr); } @@ -710,9 +721,12 @@ extern "C" { { int result = 0; - if (!cond || !*cond) + if (!cond) return EINVAL; + if (*cond == PTHREAD_COND_INITIALIZER) + cond_init(cond, NULL); + pthread_cond *c = *cond; c->counter_lock.lock();