From 38a10c92d36bac43ae583f200a9e5f6702712677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Tue, 13 Nov 2018 13:33:45 +0100 Subject: [PATCH] pthread: initialize static rwlocks/conds Make sure that the rwlock is allocated before a lock operation is performed. This case occurs if a static rwlock was create by using PTHREAD_RWLOCK_INITIALIZER. Same goes for PTHREAD_CONDS_INITIALIZER. Fixes #3262. --- repos/libports/src/lib/libc/rwlock.cc | 31 +++++++++++++++++++++++++-- repos/libports/src/lib/libc/thread.cc | 24 ++++++++++++++++----- 2 files changed, 48 insertions(+), 7 deletions(-) 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();