mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
pthread: implement condattr setclock
Normally CLOCK_REALTIME is used. However libraries, like glib, want to use CLOCK_MONOTONIC. To make those users happy add setting the clock. Note, 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. Fixes #3846.
This commit is contained in:
parent
66ff18a53e
commit
157f4b1270
@ -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; }
|
||||
}
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user