mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +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" {
|
extern "C" {
|
||||||
|
|
||||||
/* Thread */
|
/* Thread */
|
||||||
@ -879,11 +888,16 @@ extern "C" {
|
|||||||
sem_t signal_sem;
|
sem_t signal_sem;
|
||||||
sem_t handshake_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);
|
pthread_mutex_init(&counter_mutex, nullptr);
|
||||||
sem_init(&signal_sem, 0, 0);
|
sem_init(&signal_sem, 0, 0);
|
||||||
sem_init(&handshake_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()
|
~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)
|
int pthread_condattr_init(pthread_condattr_t *attr)
|
||||||
{
|
{
|
||||||
|
static Mutex condattr_init_mutex { };
|
||||||
|
|
||||||
if (!attr)
|
if (!attr)
|
||||||
return EINVAL;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -908,10 +935,13 @@ extern "C" {
|
|||||||
|
|
||||||
int pthread_condattr_destroy(pthread_condattr_t *attr)
|
int pthread_condattr_destroy(pthread_condattr_t *attr)
|
||||||
{
|
{
|
||||||
/* assert that the attr was produced by the init no-op */
|
if (!attr)
|
||||||
if (!attr || *attr != nullptr)
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
Libc::Allocator alloc { };
|
||||||
|
destroy(alloc, *attr);
|
||||||
|
*attr = nullptr;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -919,11 +949,10 @@ extern "C" {
|
|||||||
int pthread_condattr_setclock(pthread_condattr_t *attr,
|
int pthread_condattr_setclock(pthread_condattr_t *attr,
|
||||||
clockid_t clock_id)
|
clockid_t clock_id)
|
||||||
{
|
{
|
||||||
/* assert that the attr was produced by the init no-op */
|
if (!attr)
|
||||||
if (!attr || *attr != nullptr)
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
warning(__func__, " not implemented yet");
|
(*attr)->clock_id = clock_id;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -940,7 +969,8 @@ extern "C" {
|
|||||||
try {
|
try {
|
||||||
Mutex::Guard guard(cond_init_mutex);
|
Mutex::Guard guard(cond_init_mutex);
|
||||||
Libc::Allocator alloc { };
|
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;
|
return 0;
|
||||||
} catch (...) { return ENOMEM; }
|
} catch (...) { return ENOMEM; }
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,8 @@ struct sem : Genode::Noncopyable
|
|||||||
int _count;
|
int _count;
|
||||||
Mutex _data_mutex;
|
Mutex _data_mutex;
|
||||||
|
|
||||||
|
clockid_t _clock_id { CLOCK_REALTIME };
|
||||||
|
|
||||||
/* _data_mutex must be hold when calling the following methods */
|
/* _data_mutex must be hold when calling the following methods */
|
||||||
|
|
||||||
void _append_applicant(Applicant *applicant)
|
void _append_applicant(Applicant *applicant)
|
||||||
@ -185,7 +187,7 @@ struct sem : Genode::Noncopyable
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
timespec abs_now;
|
timespec abs_now;
|
||||||
clock_gettime(CLOCK_REALTIME, &abs_now);
|
clock_gettime(_clock_id, &abs_now);
|
||||||
|
|
||||||
Libc::uint64_t const timeout_ms =
|
Libc::uint64_t const timeout_ms =
|
||||||
calculate_relative_timeout_ms(abs_now, abs_timeout);
|
calculate_relative_timeout_ms(abs_now, abs_timeout);
|
||||||
@ -206,11 +208,31 @@ struct sem : Genode::Noncopyable
|
|||||||
|
|
||||||
return 0;
|
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" {
|
extern "C" {
|
||||||
|
|
||||||
|
int sem_set_clock(sem_t *sem, clockid_t clock_id)
|
||||||
|
{
|
||||||
|
return (*sem)->set_clock(clock_id);
|
||||||
|
}
|
||||||
|
|
||||||
int sem_close(sem_t *)
|
int sem_close(sem_t *)
|
||||||
{
|
{
|
||||||
warning(__func__, " not implemented");
|
warning(__func__, " not implemented");
|
||||||
|
Loading…
Reference in New Issue
Block a user