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.
This commit is contained in:
Josef Söntgen
2018-11-13 13:33:45 +01:00
committed by Christian Helmuth
parent 3c8714ed5a
commit 38a10c92d3
2 changed files with 48 additions and 7 deletions

View File

@ -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) int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
{ {
*rwlock = new struct pthread_rwlock(); return rwlock_init(rwlock, attr);
return 0;
} }
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
@ -105,12 +118,26 @@ extern "C" {
int pthread_rwlock_rdlock(pthread_rwlock_t * rwlock) 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(); (*rwlock)->rdlock();
return 0; return 0;
} }
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) 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(); (*rwlock)->wrlock();
return 0; return 0;
} }

View File

@ -639,15 +639,26 @@ extern "C" {
} }
int pthread_cond_init(pthread_cond_t *__restrict cond, static int cond_init(pthread_cond_t *__restrict cond,
const pthread_condattr_t *__restrict attr) const pthread_condattr_t *__restrict attr)
{ {
static Genode::Lock cond_init_lock { };
if (!cond) if (!cond)
return EINVAL; 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; int result = 0;
if (!cond || !*cond) if (!cond)
return EINVAL; return EINVAL;
if (*cond == PTHREAD_COND_INITIALIZER)
cond_init(cond, NULL);
pthread_cond *c = *cond; pthread_cond *c = *cond;
c->counter_lock.lock(); c->counter_lock.lock();