diff --git a/repos/libports/src/lib/libc/pthread.cc b/repos/libports/src/lib/libc/pthread.cc index 494cf0d439..cefa5f8e7b 100644 --- a/repos/libports/src/lib/libc/pthread.cc +++ b/repos/libports/src/lib/libc/pthread.cc @@ -505,6 +505,15 @@ struct Libc::Pthread_mutex_recursive : pthread_mutex }; +/* + * The pthread_cond implementation uses the POSIX semaphore API + * internally that does not have means to set the clock. For this + * reason the private 'sem_set_clock' function is introduced, + * see 'semaphore.cc' for the implementation. +*/ +extern "C" int sem_set_clock(sem_t *sem, clockid_t clock_id); + + extern "C" { /* Thread */ @@ -879,11 +888,16 @@ extern "C" { sem_t signal_sem; sem_t handshake_sem; - pthread_cond() : num_waiters(0), num_signallers(0) + pthread_cond(clockid_t clock_id) : num_waiters(0), num_signallers(0) { pthread_mutex_init(&counter_mutex, nullptr); sem_init(&signal_sem, 0, 0); sem_init(&handshake_sem, 0, 0); + + if (sem_set_clock(&signal_sem, clock_id)) { + struct Invalid_timedwait_clock { }; + throw Invalid_timedwait_clock(); + } } ~pthread_cond() @@ -895,12 +909,25 @@ extern "C" { }; + struct pthread_cond_attr + { + clockid_t clock_id { CLOCK_REALTIME }; + }; + + int pthread_condattr_init(pthread_condattr_t *attr) { + static Mutex condattr_init_mutex { }; + if (!attr) return EINVAL; - *attr = nullptr; + try { + Mutex::Guard guard(condattr_init_mutex); + Libc::Allocator alloc { }; + *attr = new (alloc) pthread_cond_attr; + return 0; + } catch (...) { return ENOMEM; } return 0; } @@ -908,10 +935,13 @@ extern "C" { int pthread_condattr_destroy(pthread_condattr_t *attr) { - /* assert that the attr was produced by the init no-op */ - if (!attr || *attr != nullptr) + if (!attr) return EINVAL; + Libc::Allocator alloc { }; + destroy(alloc, *attr); + *attr = nullptr; + return 0; } @@ -919,11 +949,10 @@ extern "C" { int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id) { - /* assert that the attr was produced by the init no-op */ - if (!attr || *attr != nullptr) + if (!attr) return EINVAL; - warning(__func__, " not implemented yet"); + (*attr)->clock_id = clock_id; return 0; } @@ -940,7 +969,8 @@ extern "C" { try { Mutex::Guard guard(cond_init_mutex); Libc::Allocator alloc { }; - *cond = new (alloc) pthread_cond; + *cond = attr && *attr ? new (alloc) pthread_cond((*attr)->clock_id) + : new (alloc) pthread_cond(CLOCK_REALTIME); return 0; } catch (...) { return ENOMEM; } } diff --git a/repos/libports/src/lib/libc/semaphore.cc b/repos/libports/src/lib/libc/semaphore.cc index 85f9e82233..5a55b00cba 100644 --- a/repos/libports/src/lib/libc/semaphore.cc +++ b/repos/libports/src/lib/libc/semaphore.cc @@ -64,6 +64,8 @@ struct sem : Genode::Noncopyable int _count; Mutex _data_mutex; + clockid_t _clock_id { CLOCK_REALTIME }; + /* _data_mutex must be hold when calling the following methods */ void _append_applicant(Applicant *applicant) @@ -185,7 +187,7 @@ struct sem : Genode::Noncopyable return 0; timespec abs_now; - clock_gettime(CLOCK_REALTIME, &abs_now); + clock_gettime(_clock_id, &abs_now); Libc::uint64_t const timeout_ms = calculate_relative_timeout_ms(abs_now, abs_timeout); @@ -206,11 +208,31 @@ struct sem : Genode::Noncopyable return 0; } + + int set_clock(clockid_t clock_id) + { + switch (clock_id) { + case CLOCK_REALTIME: + _clock_id = CLOCK_REALTIME; + return 0; + case CLOCK_MONOTONIC: + _clock_id = CLOCK_MONOTONIC; + return 0; + default: + break; + } + return -1; + } }; extern "C" { + int sem_set_clock(sem_t *sem, clockid_t clock_id) + { + return (*sem)->set_clock(clock_id); + } + int sem_close(sem_t *) { warning(__func__, " not implemented");