Add thread wait functions with clock support.
- pthread_cond_clockwait(2) - pthread_mutex_clocklock(2) - pthread_mutex_timedlock(2) - pthread_rwlock_clockrdlock(2) - pthread_rwlock_clockwrlock(2) - pthread_rwlock_timedrdlock(2) - pthread_rwlock_timedwrlock(2) - sem_clockwait(2)
This commit is contained in:
parent
f460bb78aa
commit
64fc6b5f6d
16 changed files with 378 additions and 132 deletions
|
@ -438,6 +438,7 @@ pthread/pthread_condattr_getclock.o \
|
||||||
pthread/pthread_condattr_init.o \
|
pthread/pthread_condattr_init.o \
|
||||||
pthread/pthread_condattr_setclock.o \
|
pthread/pthread_condattr_setclock.o \
|
||||||
pthread/pthread_cond_broadcast.o \
|
pthread/pthread_cond_broadcast.o \
|
||||||
|
pthread/pthread_cond_clockwait.o \
|
||||||
pthread/pthread_cond_destroy.o \
|
pthread/pthread_cond_destroy.o \
|
||||||
pthread/pthread_cond_init.o \
|
pthread/pthread_cond_init.o \
|
||||||
pthread/pthread_cond_signal.o \
|
pthread/pthread_cond_signal.o \
|
||||||
|
@ -456,15 +457,21 @@ pthread/pthread_mutexattr_destroy.o \
|
||||||
pthread/pthread_mutexattr_gettype.o \
|
pthread/pthread_mutexattr_gettype.o \
|
||||||
pthread/pthread_mutexattr_init.o \
|
pthread/pthread_mutexattr_init.o \
|
||||||
pthread/pthread_mutexattr_settype.o \
|
pthread/pthread_mutexattr_settype.o \
|
||||||
|
pthread/pthread_mutex_clocklock.o \
|
||||||
pthread/pthread_mutex_destroy.o \
|
pthread/pthread_mutex_destroy.o \
|
||||||
pthread/pthread_mutex_init.o \
|
pthread/pthread_mutex_init.o \
|
||||||
pthread/pthread_mutex_lock.o \
|
pthread/pthread_mutex_lock.o \
|
||||||
|
pthread/pthread_mutex_timedlock.o \
|
||||||
pthread/pthread_mutex_trylock.o \
|
pthread/pthread_mutex_trylock.o \
|
||||||
pthread/pthread_mutex_unlock.o \
|
pthread/pthread_mutex_unlock.o \
|
||||||
pthread/pthread_once.o \
|
pthread/pthread_once.o \
|
||||||
|
pthread/pthread_rwlock_clockrdlock.o \
|
||||||
|
pthread/pthread_rwlock_clockwrlock.o \
|
||||||
pthread/pthread_rwlock_destroy.o \
|
pthread/pthread_rwlock_destroy.o \
|
||||||
pthread/pthread_rwlock_init.o \
|
pthread/pthread_rwlock_init.o \
|
||||||
pthread/pthread_rwlock_rdlock.o \
|
pthread/pthread_rwlock_rdlock.o \
|
||||||
|
pthread/pthread_rwlock_timedrdlock.o \
|
||||||
|
pthread/pthread_rwlock_timedwrlock.o \
|
||||||
pthread/pthread_rwlock_tryrdlock.o \
|
pthread/pthread_rwlock_tryrdlock.o \
|
||||||
pthread/pthread_rwlock_trywrlock.o \
|
pthread/pthread_rwlock_trywrlock.o \
|
||||||
pthread/pthread_rwlock_unlock.o \
|
pthread/pthread_rwlock_unlock.o \
|
||||||
|
@ -488,6 +495,7 @@ pwd/setpwent.o \
|
||||||
sched/sched_yield.o \
|
sched/sched_yield.o \
|
||||||
pty/openpty.o \
|
pty/openpty.o \
|
||||||
scram/scram.o \
|
scram/scram.o \
|
||||||
|
semaphore/sem_clockwait.o \
|
||||||
semaphore/sem_destroy.o \
|
semaphore/sem_destroy.o \
|
||||||
semaphore/sem_getvalue.o \
|
semaphore/sem_getvalue.o \
|
||||||
semaphore/sem_init.o \
|
semaphore/sem_init.o \
|
||||||
|
|
|
@ -252,7 +252,8 @@ int pthread_mutex_init(pthread_mutex_t* __restrict,
|
||||||
const pthread_mutexattr_t* __restrict);
|
const pthread_mutexattr_t* __restrict);
|
||||||
int pthread_mutex_lock(pthread_mutex_t*);
|
int pthread_mutex_lock(pthread_mutex_t*);
|
||||||
/* TODO: pthread_mutex_setprioceiling */
|
/* TODO: pthread_mutex_setprioceiling */
|
||||||
/* TODO: pthread_mutex_timedlock */
|
int pthread_mutex_timedlock(pthread_mutex_t* __restrict,
|
||||||
|
const struct timespec* __restrict);
|
||||||
int pthread_mutex_trylock(pthread_mutex_t*);
|
int pthread_mutex_trylock(pthread_mutex_t*);
|
||||||
int pthread_mutex_unlock(pthread_mutex_t*);
|
int pthread_mutex_unlock(pthread_mutex_t*);
|
||||||
int pthread_mutexattr_destroy(pthread_mutexattr_t*);
|
int pthread_mutexattr_destroy(pthread_mutexattr_t*);
|
||||||
|
@ -272,8 +273,10 @@ int pthread_rwlock_destroy(pthread_rwlock_t*);
|
||||||
int pthread_rwlock_init(pthread_rwlock_t* __restrict,
|
int pthread_rwlock_init(pthread_rwlock_t* __restrict,
|
||||||
const pthread_rwlockattr_t* __restrict);
|
const pthread_rwlockattr_t* __restrict);
|
||||||
int pthread_rwlock_rdlock(pthread_rwlock_t*);
|
int pthread_rwlock_rdlock(pthread_rwlock_t*);
|
||||||
/* TODO: pthread_rwlock_timedrdlock */
|
int pthread_rwlock_timedrdlock(pthread_rwlock_t* __restrict,
|
||||||
/* TODO: pthread_rwlock_timedwrlock */
|
const struct timespec* __restrict);
|
||||||
|
int pthread_rwlock_timedwrlock(pthread_rwlock_t* __restrict,
|
||||||
|
const struct timespec* __restrict);
|
||||||
int pthread_rwlock_tryrdlock(pthread_rwlock_t*);
|
int pthread_rwlock_tryrdlock(pthread_rwlock_t*);
|
||||||
int pthread_rwlock_trywrlock(pthread_rwlock_t*);
|
int pthread_rwlock_trywrlock(pthread_rwlock_t*);
|
||||||
int pthread_rwlock_unlock(pthread_rwlock_t*);
|
int pthread_rwlock_unlock(pthread_rwlock_t*);
|
||||||
|
@ -296,6 +299,18 @@ int pthread_setspecific(pthread_key_t, const void*);
|
||||||
/* TODO: pthread_spin_unlock */
|
/* TODO: pthread_spin_unlock */
|
||||||
/* TODO: pthread_testcancel */
|
/* TODO: pthread_testcancel */
|
||||||
|
|
||||||
|
#if __USE_SORTIX || 202405L <= __USE_POSIX
|
||||||
|
int pthread_cond_clockwait(pthread_cond_t* __restrict,
|
||||||
|
pthread_mutex_t* __restrict, clockid_t,
|
||||||
|
const struct timespec* __restrict);
|
||||||
|
int pthread_mutex_clocklock(pthread_mutex_t* __restrict, clockid_t,
|
||||||
|
const struct timespec* __restrict);
|
||||||
|
int pthread_rwlock_clockrdlock(pthread_rwlock_t* __restrict, clockid_t,
|
||||||
|
const struct timespec* __restrict);
|
||||||
|
int pthread_rwlock_clockwrlock(pthread_rwlock_t* __restrict, clockid_t,
|
||||||
|
const struct timespec* __restrict);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
#include <sortix/timespec.h>
|
#include <time.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -52,6 +52,11 @@ int sem_trywait(sem_t*);
|
||||||
/*int sem_unlink(const char*);*/
|
/*int sem_unlink(const char*);*/
|
||||||
int sem_wait(sem_t*);
|
int sem_wait(sem_t*);
|
||||||
|
|
||||||
|
#if __USE_SORTIX || 202405L <= __USE_POSIX
|
||||||
|
int sem_clockwait(sem_t* __restrict, clockid_t clock,
|
||||||
|
const struct timespec* __restrict);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
68
libc/pthread/pthread_cond_clockwait.c
Normal file
68
libc/pthread/pthread_cond_clockwait.c
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 2021, 2024 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pthread/pthread_cond_clockwait.c
|
||||||
|
* Waits on a condition or until a timeout happens.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/futex.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
int pthread_cond_clockwait(pthread_cond_t* restrict cond,
|
||||||
|
pthread_mutex_t* restrict mutex,
|
||||||
|
clockid_t clock,
|
||||||
|
const struct timespec* restrict abstime)
|
||||||
|
{
|
||||||
|
struct pthread_cond_elem elem;
|
||||||
|
pthread_mutex_lock(&cond->lock);
|
||||||
|
elem.next = NULL;
|
||||||
|
elem.prev = cond->last;
|
||||||
|
elem.woken = 0;
|
||||||
|
if ( cond->last )
|
||||||
|
cond->last->next = &elem;
|
||||||
|
if ( !cond->first )
|
||||||
|
cond->first = &elem;
|
||||||
|
cond->last = &elem;
|
||||||
|
pthread_mutex_unlock(&cond->lock);
|
||||||
|
pthread_mutex_unlock(mutex);
|
||||||
|
int op = FUTEX_WAIT | FUTEX_ABSOLUTE | FUTEX_CLOCK(clock);
|
||||||
|
int result = 0;
|
||||||
|
while ( !__atomic_load_n(&elem.woken, __ATOMIC_SEQ_CST) &&
|
||||||
|
futex(&elem.woken, op, 0, abstime) < 0 )
|
||||||
|
{
|
||||||
|
if ( errno == EINTR )
|
||||||
|
continue;
|
||||||
|
if ( errno != EAGAIN )
|
||||||
|
result = errno;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(mutex);
|
||||||
|
pthread_mutex_lock(&cond->lock);
|
||||||
|
if ( !__atomic_load_n(&elem.woken, __ATOMIC_SEQ_CST) )
|
||||||
|
{
|
||||||
|
if ( elem.next )
|
||||||
|
elem.next->prev = elem.prev;
|
||||||
|
else
|
||||||
|
cond->last = elem.prev;
|
||||||
|
if ( elem.prev )
|
||||||
|
elem.prev->next = elem.next;
|
||||||
|
else
|
||||||
|
cond->first = elem.next;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&cond->lock);
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2021 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2014, 2021, 2024 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -17,51 +17,11 @@
|
||||||
* Waits on a condition or until a timeout happens.
|
* Waits on a condition or until a timeout happens.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/futex.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
int pthread_cond_timedwait(pthread_cond_t* restrict cond,
|
int pthread_cond_timedwait(pthread_cond_t* restrict cond,
|
||||||
pthread_mutex_t* restrict mutex,
|
pthread_mutex_t* restrict mutex,
|
||||||
const struct timespec* restrict abstime)
|
const struct timespec* restrict abstime)
|
||||||
{
|
{
|
||||||
struct pthread_cond_elem elem;
|
return pthread_cond_clockwait(cond, mutex, cond->clock, abstime);
|
||||||
pthread_mutex_lock(&cond->lock);
|
|
||||||
elem.next = NULL;
|
|
||||||
elem.prev = cond->last;
|
|
||||||
elem.woken = 0;
|
|
||||||
if ( cond->last )
|
|
||||||
cond->last->next = &elem;
|
|
||||||
if ( !cond->first )
|
|
||||||
cond->first = &elem;
|
|
||||||
cond->last = &elem;
|
|
||||||
pthread_mutex_unlock(&cond->lock);
|
|
||||||
pthread_mutex_unlock(mutex);
|
|
||||||
int op = FUTEX_WAIT | FUTEX_ABSOLUTE | FUTEX_CLOCK(cond->clock);
|
|
||||||
int result = 0;
|
|
||||||
while ( !__atomic_load_n(&elem.woken, __ATOMIC_SEQ_CST) &&
|
|
||||||
futex(&elem.woken, op, 0, abstime) < 0 )
|
|
||||||
{
|
|
||||||
if ( errno == EINTR )
|
|
||||||
continue;
|
|
||||||
if ( errno != EAGAIN )
|
|
||||||
result = errno;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pthread_mutex_lock(mutex);
|
|
||||||
pthread_mutex_lock(&cond->lock);
|
|
||||||
if ( !__atomic_load_n(&elem.woken, __ATOMIC_SEQ_CST) )
|
|
||||||
{
|
|
||||||
if ( elem.next )
|
|
||||||
elem.next->prev = elem.prev;
|
|
||||||
else
|
|
||||||
cond->last = elem.prev;
|
|
||||||
if ( elem.prev )
|
|
||||||
elem.prev->next = elem.next;
|
|
||||||
else
|
|
||||||
cond->first = elem.next;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&cond->lock);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
66
libc/pthread/pthread_mutex_clocklock.c
Normal file
66
libc/pthread/pthread_mutex_clocklock.c
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 2014, 2021, 2024 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pthread/pthread_mutex_clocklock.c
|
||||||
|
* Locks a mutex or waits for a timeout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/futex.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
static const int UNLOCKED = 0;
|
||||||
|
static const int LOCKED = 1;
|
||||||
|
static const int CONTENDED = 2;
|
||||||
|
|
||||||
|
int pthread_mutex_clocklock(pthread_mutex_t* mutex,
|
||||||
|
clockid_t clock,
|
||||||
|
const struct timespec* abstime)
|
||||||
|
{
|
||||||
|
int state = UNLOCKED;
|
||||||
|
int desired = LOCKED;
|
||||||
|
while ( !__atomic_compare_exchange_n(&mutex->lock, &state, desired, false,
|
||||||
|
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) )
|
||||||
|
{
|
||||||
|
if ( mutex->type == PTHREAD_MUTEX_RECURSIVE &&
|
||||||
|
(pthread_t) mutex->owner == pthread_self() )
|
||||||
|
{
|
||||||
|
if ( mutex->recursion == ULONG_MAX )
|
||||||
|
return errno = EAGAIN;
|
||||||
|
mutex->recursion++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ( state == LOCKED &&
|
||||||
|
!__atomic_compare_exchange_n(&mutex->lock, &state, CONTENDED,
|
||||||
|
false, __ATOMIC_SEQ_CST,
|
||||||
|
__ATOMIC_SEQ_CST) )
|
||||||
|
{
|
||||||
|
state = UNLOCKED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
desired = CONTENDED;
|
||||||
|
int op = FUTEX_WAIT | FUTEX_ABSOLUTE | FUTEX_CLOCK(clock);
|
||||||
|
if ( futex(&mutex->lock, op, CONTENDED, abstime) < 0 &&
|
||||||
|
errno != EAGAIN && errno != EINTR )
|
||||||
|
return errno;
|
||||||
|
state = UNLOCKED;
|
||||||
|
}
|
||||||
|
mutex->owner = (unsigned long) pthread_self();
|
||||||
|
mutex->recursion = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2014, 2021 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2014, 2021, 2024 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -17,47 +17,9 @@
|
||||||
* Locks a mutex.
|
* Locks a mutex.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/futex.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
static const int UNLOCKED = 0;
|
|
||||||
static const int LOCKED = 1;
|
|
||||||
static const int CONTENDED = 2;
|
|
||||||
|
|
||||||
int pthread_mutex_lock(pthread_mutex_t* mutex)
|
int pthread_mutex_lock(pthread_mutex_t* mutex)
|
||||||
{
|
{
|
||||||
int state = UNLOCKED;
|
return pthread_mutex_timedlock(mutex, NULL);
|
||||||
int desired = LOCKED;
|
|
||||||
while ( !__atomic_compare_exchange_n(&mutex->lock, &state, desired, false,
|
|
||||||
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) )
|
|
||||||
{
|
|
||||||
if ( mutex->type == PTHREAD_MUTEX_RECURSIVE &&
|
|
||||||
(pthread_t) mutex->owner == pthread_self() )
|
|
||||||
{
|
|
||||||
if ( mutex->recursion == ULONG_MAX )
|
|
||||||
return errno = EAGAIN;
|
|
||||||
mutex->recursion++;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ( state == LOCKED &&
|
|
||||||
!__atomic_compare_exchange_n(&mutex->lock, &state, CONTENDED,
|
|
||||||
false, __ATOMIC_SEQ_CST,
|
|
||||||
__ATOMIC_SEQ_CST) )
|
|
||||||
{
|
|
||||||
state = UNLOCKED;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
desired = CONTENDED;
|
|
||||||
if ( futex(&mutex->lock, FUTEX_WAIT, CONTENDED, NULL) < 0 &&
|
|
||||||
errno != EAGAIN && errno != EINTR )
|
|
||||||
return errno;
|
|
||||||
state = UNLOCKED;
|
|
||||||
}
|
|
||||||
mutex->owner = (unsigned long) pthread_self();
|
|
||||||
mutex->recursion = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
26
libc/pthread/pthread_mutex_timedlock.c
Normal file
26
libc/pthread/pthread_mutex_timedlock.c
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 2014, 2021, 2024 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pthread/pthread_mutex_timedlock.c
|
||||||
|
* Locks a mutex or waits for a timeout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
int pthread_mutex_timedlock(pthread_mutex_t* mutex,
|
||||||
|
const struct timespec* abstime)
|
||||||
|
{
|
||||||
|
return pthread_mutex_clocklock(mutex, CLOCK_REALTIME, abstime);
|
||||||
|
}
|
36
libc/pthread/pthread_rwlock_clockrdlock.c
Normal file
36
libc/pthread/pthread_rwlock_clockrdlock.c
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 2024 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pthread/pthread_rwlock_clockrdlock.c
|
||||||
|
* Acquires read access to a read-write lock or waits for a timeout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
int pthread_rwlock_clockrdlock(pthread_rwlock_t* rwlock, clockid_t clock,
|
||||||
|
const struct timespec* abstime)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&rwlock->request_mutex);
|
||||||
|
rwlock->pending_readers++;
|
||||||
|
int ret = 0;
|
||||||
|
while ( !ret && (!rwlock->num_writers || rwlock->pending_writers) )
|
||||||
|
ret = pthread_cond_clockwait(&rwlock->reader_condition,
|
||||||
|
&rwlock->request_mutex, clock, abstime);
|
||||||
|
rwlock->pending_readers--;
|
||||||
|
if ( !ret )
|
||||||
|
rwlock->num_readers++;
|
||||||
|
pthread_mutex_unlock(&rwlock->request_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
36
libc/pthread/pthread_rwlock_clockwrlock.c
Normal file
36
libc/pthread/pthread_rwlock_clockwrlock.c
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 2024 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pthread/pthread_rwlock_clockwrlock.c
|
||||||
|
* Acquires write access to a read-write lock or waits for a timeout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
int pthread_rwlock_clocklock(pthread_rwlock_t* rwlock, clockid_t clock,
|
||||||
|
const struct timespec* abstime)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&rwlock->request_mutex);
|
||||||
|
rwlock->pending_writers++;
|
||||||
|
int ret = 0;
|
||||||
|
while ( !ret && (rwlock->num_readers || rwlock->num_writers) )
|
||||||
|
ret = pthread_cond_clockwait(&rwlock->writer_condition,
|
||||||
|
&rwlock->request_mutex, clock, abstime);
|
||||||
|
rwlock->pending_writers--;
|
||||||
|
if ( !ret )
|
||||||
|
rwlock->num_writers = 1;
|
||||||
|
pthread_mutex_unlock(&rwlock->request_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -21,12 +21,5 @@
|
||||||
|
|
||||||
int pthread_rwlock_rdlock(pthread_rwlock_t* rwlock)
|
int pthread_rwlock_rdlock(pthread_rwlock_t* rwlock)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rwlock->request_mutex);
|
return pthread_rwlock_timedrdlock(rwlock, NULL);
|
||||||
rwlock->pending_readers++;
|
|
||||||
while ( rwlock->num_writers || rwlock->pending_writers )
|
|
||||||
pthread_cond_wait(&rwlock->reader_condition, &rwlock->request_mutex);
|
|
||||||
rwlock->pending_readers--;
|
|
||||||
rwlock->num_readers++;
|
|
||||||
pthread_mutex_unlock(&rwlock->request_mutex);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
26
libc/pthread/pthread_rwlock_timedrdlock.c
Normal file
26
libc/pthread/pthread_rwlock_timedrdlock.c
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 2024 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pthread/pthread_rwlock_timedrdlock.c
|
||||||
|
* Acquires read access to a read-write lock or waits for a timeout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
int pthread_rwlock_timedrdlock(pthread_rwlock_t* rwlock,
|
||||||
|
const struct timespec* abstime)
|
||||||
|
{
|
||||||
|
return pthread_rwlock_clockrdlock(rwlock, CLOCK_REALTIME, abstime);
|
||||||
|
}
|
26
libc/pthread/pthread_rwlock_timedwrlock.c
Normal file
26
libc/pthread/pthread_rwlock_timedwrlock.c
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 2024 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pthread/pthread_rwlock_timedwrlock.c
|
||||||
|
* Acquires write access to a read-write lock or waits for a timeout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
int pthread_rwlock_timedrwlock(pthread_rwlock_t* rwlock,
|
||||||
|
const struct timespec* abstime)
|
||||||
|
{
|
||||||
|
return pthread_rwlock_clockwrlock(rwlock, CLOCK_REALTIME, abstime);
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2024 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -21,12 +21,5 @@
|
||||||
|
|
||||||
int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock)
|
int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rwlock->request_mutex);
|
return pthread_rwlock_timedwrlock(rwlock, NULL);
|
||||||
rwlock->pending_writers++;
|
|
||||||
while ( rwlock->num_readers || rwlock->num_writers )
|
|
||||||
pthread_cond_wait(&rwlock->writer_condition, &rwlock->request_mutex);
|
|
||||||
rwlock->pending_writers--;
|
|
||||||
rwlock->num_writers = 1;
|
|
||||||
pthread_mutex_unlock(&rwlock->request_mutex);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
53
libc/semaphore/sem_clockwait.c
Normal file
53
libc/semaphore/sem_clockwait.c
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 2021, 2024 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* semaphore/sem_clockwait.c
|
||||||
|
* Lock a semaphore with a timeout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/futex.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int sem_clockwait(sem_t* restrict sem, clockid_t clock,
|
||||||
|
const struct timespec* restrict abstime)
|
||||||
|
{
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
int old = __atomic_load_n(&sem->value, __ATOMIC_SEQ_CST);
|
||||||
|
int new = old != -1 ? old - 1 : -1;
|
||||||
|
bool waiting = new == -1;
|
||||||
|
if ( waiting )
|
||||||
|
__atomic_add_fetch(&sem->waiters, 1, __ATOMIC_SEQ_CST);
|
||||||
|
if ( old != new &&
|
||||||
|
!__atomic_compare_exchange_n(&sem->value, &old, new, false,
|
||||||
|
__ATOMIC_SEQ_CST, __ATOMIC_RELAXED) )
|
||||||
|
{
|
||||||
|
if ( waiting )
|
||||||
|
__atomic_sub_fetch(&sem->waiters, 1, __ATOMIC_SEQ_CST);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( !waiting )
|
||||||
|
return 0;
|
||||||
|
int op = FUTEX_WAIT | FUTEX_ABSOLUTE | FUTEX_CLOCK(clock);
|
||||||
|
int ret = futex(&sem->value, op, -1, abstime);
|
||||||
|
__atomic_sub_fetch(&sem->waiters, 1, __ATOMIC_SEQ_CST);
|
||||||
|
if ( ret < 0 && errno != EAGAIN )
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2021 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2014, 2021, 2024 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -17,36 +17,9 @@
|
||||||
* Lock a semaphore with a timeout.
|
* Lock a semaphore with a timeout.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/futex.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
int sem_timedwait(sem_t* restrict sem, const struct timespec* restrict abstime)
|
int sem_timedwait(sem_t* restrict sem, const struct timespec* restrict abstime)
|
||||||
{
|
{
|
||||||
while ( true )
|
return sem_clockwait(sem, CLOCK_REALTIME, abstime);
|
||||||
{
|
|
||||||
int old = __atomic_load_n(&sem->value, __ATOMIC_SEQ_CST);
|
|
||||||
int new = old != -1 ? old - 1 : -1;
|
|
||||||
bool waiting = new == -1;
|
|
||||||
if ( waiting )
|
|
||||||
__atomic_add_fetch(&sem->waiters, 1, __ATOMIC_SEQ_CST);
|
|
||||||
if ( old != new &&
|
|
||||||
!__atomic_compare_exchange_n(&sem->value, &old, new, false,
|
|
||||||
__ATOMIC_SEQ_CST, __ATOMIC_RELAXED) )
|
|
||||||
{
|
|
||||||
if ( waiting )
|
|
||||||
__atomic_sub_fetch(&sem->waiters, 1, __ATOMIC_SEQ_CST);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( !waiting )
|
|
||||||
return 0;
|
|
||||||
int op = FUTEX_WAIT | FUTEX_ABSOLUTE | FUTEX_CLOCK(CLOCK_REALTIME);
|
|
||||||
int ret = futex(&sem->value, op, -1, abstime);
|
|
||||||
__atomic_sub_fetch(&sem->waiters, 1, __ATOMIC_SEQ_CST);
|
|
||||||
if ( ret < 0 && errno != EAGAIN )
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue