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
7c76ebdc4d
commit
5cc0027cf7
16 changed files with 378 additions and 132 deletions
libc
Makefile
include
pthread
pthread_cond_clockwait.cpthread_cond_timedwait.cpthread_mutex_clocklock.cpthread_mutex_lock.cpthread_mutex_timedlock.cpthread_rwlock_clockrdlock.cpthread_rwlock_clockwrlock.cpthread_rwlock_rdlock.cpthread_rwlock_timedrdlock.cpthread_rwlock_timedwrlock.cpthread_rwlock_wrlock.c
semaphore
|
@ -436,6 +436,7 @@ pthread/pthread_condattr_getclock.o \
|
|||
pthread/pthread_condattr_init.o \
|
||||
pthread/pthread_condattr_setclock.o \
|
||||
pthread/pthread_cond_broadcast.o \
|
||||
pthread/pthread_cond_clockwait.o \
|
||||
pthread/pthread_cond_destroy.o \
|
||||
pthread/pthread_cond_init.o \
|
||||
pthread/pthread_cond_signal.o \
|
||||
|
@ -454,15 +455,21 @@ pthread/pthread_mutexattr_destroy.o \
|
|||
pthread/pthread_mutexattr_gettype.o \
|
||||
pthread/pthread_mutexattr_init.o \
|
||||
pthread/pthread_mutexattr_settype.o \
|
||||
pthread/pthread_mutex_clocklock.o \
|
||||
pthread/pthread_mutex_destroy.o \
|
||||
pthread/pthread_mutex_init.o \
|
||||
pthread/pthread_mutex_lock.o \
|
||||
pthread/pthread_mutex_timedlock.o \
|
||||
pthread/pthread_mutex_trylock.o \
|
||||
pthread/pthread_mutex_unlock.o \
|
||||
pthread/pthread_once.o \
|
||||
pthread/pthread_rwlock_clockrdlock.o \
|
||||
pthread/pthread_rwlock_clockwrlock.o \
|
||||
pthread/pthread_rwlock_destroy.o \
|
||||
pthread/pthread_rwlock_init.o \
|
||||
pthread/pthread_rwlock_rdlock.o \
|
||||
pthread/pthread_rwlock_timedrdlock.o \
|
||||
pthread/pthread_rwlock_timedwrlock.o \
|
||||
pthread/pthread_rwlock_tryrdlock.o \
|
||||
pthread/pthread_rwlock_trywrlock.o \
|
||||
pthread/pthread_rwlock_unlock.o \
|
||||
|
@ -486,6 +493,7 @@ pwd/setpwent.o \
|
|||
sched/sched_yield.o \
|
||||
pty/openpty.o \
|
||||
scram/scram.o \
|
||||
semaphore/sem_clockwait.o \
|
||||
semaphore/sem_destroy.o \
|
||||
semaphore/sem_getvalue.o \
|
||||
semaphore/sem_init.o \
|
||||
|
|
|
@ -252,7 +252,8 @@ int pthread_mutex_init(pthread_mutex_t* __restrict,
|
|||
const pthread_mutexattr_t* __restrict);
|
||||
int pthread_mutex_lock(pthread_mutex_t*);
|
||||
/* 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_unlock(pthread_mutex_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,
|
||||
const pthread_rwlockattr_t* __restrict);
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t*);
|
||||
/* TODO: pthread_rwlock_timedrdlock */
|
||||
/* TODO: pthread_rwlock_timedwrlock */
|
||||
int pthread_rwlock_timedrdlock(pthread_rwlock_t* __restrict,
|
||||
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_trywrlock(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_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
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <sortix/timespec.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -52,6 +52,11 @@ int sem_trywait(sem_t*);
|
|||
/*int sem_unlink(const char*);*/
|
||||
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
|
||||
} /* extern "C" */
|
||||
#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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/futex.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
int pthread_cond_timedwait(pthread_cond_t* restrict cond,
|
||||
pthread_mutex_t* restrict mutex,
|
||||
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(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;
|
||||
return pthread_cond_clockwait(cond, mutex, cond->clock, abstime);
|
||||
}
|
||||
|
|
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
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -17,47 +17,9 @@
|
|||
* Locks a mutex.
|
||||
*/
|
||||
|
||||
#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_lock(pthread_mutex_t* mutex)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
return pthread_mutex_timedlock(mutex, NULL);
|
||||
}
|
||||
|
|
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_clockwrlock(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)
|
||||
{
|
||||
pthread_mutex_lock(&rwlock->request_mutex);
|
||||
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;
|
||||
return pthread_rwlock_timedrdlock(rwlock, NULL);
|
||||
}
|
||||
|
|
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_timedwrlock(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
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -21,12 +21,5 @@
|
|||
|
||||
int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock)
|
||||
{
|
||||
pthread_mutex_lock(&rwlock->request_mutex);
|
||||
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;
|
||||
return pthread_rwlock_timedwrlock(rwlock, NULL);
|
||||
}
|
||||
|
|
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
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -17,36 +17,9 @@
|
|||
* Lock a semaphore with a timeout.
|
||||
*/
|
||||
|
||||
#include <sys/futex.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
int sem_timedwait(sem_t* restrict sem, 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_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;
|
||||
}
|
||||
return sem_clockwait(sem, CLOCK_REALTIME, abstime);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue