From 04a676f3c8d2443499f27612f69ee88e12089e61 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Sun, 22 Apr 2018 18:59:13 +0100 Subject: linuxthreads: implement pthread_condattr_{s,g}etclock() More applications are using pthread_condattr_setclock()/ pthread_condattr_getclock() in their code. Port these two functions from NPTL over to be more compatible. --- libpthread/linuxthreads/condvar.c | 48 ++++++++++++++++++++++ libpthread/linuxthreads/internals.h | 19 +++++++++ .../sysdeps/pthread/bits/pthreadtypes.h | 9 ++-- libpthread/linuxthreads/sysdeps/pthread/pthread.h | 12 ++++++ 4 files changed, 85 insertions(+), 3 deletions(-) (limited to 'libpthread') diff --git a/libpthread/linuxthreads/condvar.c b/libpthread/linuxthreads/condvar.c index 35daacf15..6ac1622da 100644 --- a/libpthread/linuxthreads/condvar.c +++ b/libpthread/linuxthreads/condvar.c @@ -275,6 +275,7 @@ libpthread_hidden_def(pthread_cond_broadcast) int pthread_condattr_init(pthread_condattr_t *attr attribute_unused) { + memset (attr, '\0', sizeof (*attr)); return 0; } libpthread_hidden_def(pthread_condattr_init) @@ -302,3 +303,50 @@ int pthread_condattr_setpshared (pthread_condattr_t *attr attribute_unused, int return 0; } + +int pthread_condattr_getclock (const pthread_condattr_t *attr, clockid_t *clock_id) +{ + *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1) + & ((1 << COND_NWAITERS_SHIFT) - 1)); + return 0; +} + +int pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock_id) +{ + /* Only a few clocks are allowed. CLOCK_REALTIME is always allowed. + CLOCK_MONOTONIC only if the kernel has the necessary support. */ + if (clock_id == CLOCK_MONOTONIC) + { +#ifndef __ASSUME_POSIX_TIMERS +# ifdef __NR_clock_getres + /* Check whether the clock is available. */ + static int avail; + + if (avail == 0) + { + struct timespec ts; + + INTERNAL_SYSCALL_DECL (err); + int val; + val = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts); + avail = INTERNAL_SYSCALL_ERROR_P (val, err) ? -1 : 1; + } + + if (avail < 0) +# endif + /* Not available. */ + return EINVAL; +#endif + } + else if (clock_id != CLOCK_REALTIME) + /* If more clocks are allowed some day the storing of the clock ID + in the pthread_cond_t structure needs to be adjusted. */ + return EINVAL; + + int *valuep = &((struct pthread_condattr *) attr)->value; + + *valuep = ((*valuep & ~(((1 << COND_NWAITERS_SHIFT) - 1) << 1)) + | (clock_id << 1)); + + return 0; +} diff --git a/libpthread/linuxthreads/internals.h b/libpthread/linuxthreads/internals.h index ab6b01528..720be8ec0 100644 --- a/libpthread/linuxthreads/internals.h +++ b/libpthread/linuxthreads/internals.h @@ -51,6 +51,25 @@ # define THREAD_SETMEM_NC(descr, member, value) descr->member = (value) #endif +/* Conditional variable attribute data structure. */ +struct pthread_condattr +{ + /* Combination of values: + + Bit 0 : flag whether coditional variable will be shareable between + processes. + + Bit 1-7: clock ID. */ + int value; +}; + +/* The __NWAITERS field is used as a counter and to house the number + of bits for other purposes. COND_CLOCK_BITS is the number + of bits needed to represent the ID of the clock. COND_NWAITERS_SHIFT + is the number of bits reserved for other purposes like the clock. */ +#define COND_CLOCK_BITS 1 +#define COND_NWAITERS_SHIFT 1 + /* Arguments passed to thread creation routine */ struct pthread_start_args { diff --git a/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h b/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h index 3eb592919..638dc75c9 100644 --- a/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h +++ b/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h @@ -25,6 +25,8 @@ #define __need_schedparam #include +#define __SIZEOF_PTHREAD_CONDATTR_T 4 + /* Fast locks (not abstract because mutexes and conditions aren't abstract). */ struct _pthread_fastlock { @@ -63,12 +65,13 @@ typedef struct } pthread_cond_t; -/* Attribute for conditionally variables. */ -typedef struct +typedef union { - int __dummy; + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; } pthread_condattr_t; + /* Keys for thread-specific data */ typedef unsigned int pthread_key_t; diff --git a/libpthread/linuxthreads/sysdeps/pthread/pthread.h b/libpthread/linuxthreads/sysdeps/pthread/pthread.h index 0d175025b..9bcd887ed 100644 --- a/libpthread/linuxthreads/sysdeps/pthread/pthread.h +++ b/libpthread/linuxthreads/sysdeps/pthread/pthread.h @@ -455,6 +455,18 @@ extern int pthread_condattr_getpshared (const pthread_condattr_t * extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, int __pshared) __THROW; +#ifdef __USE_XOPEN2K +/* Get the clock selected for the condition variable attribute ATTR. */ +extern int pthread_condattr_getclock (const pthread_condattr_t * + __restrict __attr, + __clockid_t *__restrict __clock_id) + __THROW __nonnull ((1, 2)); + +/* Set the clock selected for the condition variable attribute ATTR. */ +extern int pthread_condattr_setclock (pthread_condattr_t *__attr, + __clockid_t __clock_id) + __THROW __nonnull ((1)); +#endif #if defined __USE_UNIX98 || defined __USE_XOPEN2K /* Functions for handling read-write locks. */ -- cgit v1.2.3