POSIX: introduce sem_clockwait

will appear in the next version: https://www.opengroup.org/austin/docs/austin_1110.pdf

Change-Id: Iee3faf23647aa5244ad316fe1c3d825592483935
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4966
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
Jérôme Duval 2022-02-16 20:29:11 +01:00 committed by waddlesplash
parent a21676b669
commit a866e2d902
5 changed files with 62 additions and 34 deletions

View File

@ -33,7 +33,9 @@ int sem_init(sem_t* semaphore, int shared, unsigned value);
int sem_destroy(sem_t* semaphore);
int sem_post(sem_t* semaphore);
int sem_timedwait(sem_t* semaphore, const struct timespec* timeout);
int sem_clockwait(sem_t* semaphore, clockid_t clock_id,
const struct timespec* abstime);
int sem_timedwait(sem_t* semaphore, const struct timespec* abstime);
int sem_trywait(sem_t* semaphore);
int sem_wait(sem_t* semaphore);
int sem_getvalue(sem_t* semaphore, int* value);

View File

@ -32,7 +32,8 @@ status_t _user_realtime_sem_unlink(const char* name);
status_t _user_realtime_sem_get_value(sem_id semID, int* value);
status_t _user_realtime_sem_post(sem_id semID);
status_t _user_realtime_sem_wait(sem_id semID, bigtime_t timeout);
status_t _user_realtime_sem_wait(sem_id semID, uint32 flags,
bigtime_t timeout);
__END_DECLS

View File

@ -112,7 +112,8 @@ extern status_t _kern_realtime_sem_unlink(const char* name);
extern status_t _kern_realtime_sem_get_value(sem_id semID, int* value);
extern status_t _kern_realtime_sem_post(sem_id semID);
extern status_t _kern_realtime_sem_wait(sem_id semID, bigtime_t timeout);
extern status_t _kern_realtime_sem_wait(sem_id semID, uint32 flags,
bigtime_t timeout);
/* POSIX XSI semaphore syscalls */
extern int _kern_xsi_semget(key_t key, int numSems, int flags);

View File

@ -506,7 +506,7 @@ struct realtime_sem_context {
return B_OK;
}
status_t AcquireSem(sem_id id, bigtime_t timeout)
status_t AcquireSem(sem_id id, uint32 flags, bigtime_t timeout)
{
MutexLocker locker(fLock);
@ -518,17 +518,7 @@ struct realtime_sem_context {
locker.Unlock();
status_t error;
if (timeout == 0) {
error = acquire_sem_etc(id, 1, B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT,
0);
} else if (timeout == B_INFINITE_TIMEOUT) {
error = acquire_sem_etc(id, 1, B_CAN_INTERRUPT, 0);
} else {
error = acquire_sem_etc(id, 1,
B_CAN_INTERRUPT | B_ABSOLUTE_REAL_TIME_TIMEOUT, timeout);
}
status_t error = acquire_sem_etc(id, 1, flags | B_CAN_INTERRUPT, timeout);
return error == B_BAD_SEM_ID ? B_BAD_VALUE : error;
}
@ -813,11 +803,11 @@ _user_realtime_sem_post(sem_id semID)
status_t
_user_realtime_sem_wait(sem_id semID, bigtime_t timeout)
_user_realtime_sem_wait(sem_id semID, uint32 flags, bigtime_t timeout)
{
realtime_sem_context* context = get_current_team_context();
if (context == NULL)
return B_BAD_VALUE;
return syscall_restart_handle_post(context->AcquireSem(semID, timeout));
return syscall_restart_handle_post(context->AcquireSem(semID, flags, timeout));
}

View File

@ -131,7 +131,8 @@ sem_destroy(sem_t* semaphore)
static int
unnamed_sem_post(sem_t* semaphore) {
unnamed_sem_post(sem_t* semaphore)
{
int32* sem = (int32*)&semaphore->u.unnamed_sem;
int32 oldValue = atomic_add_if_greater(sem, 1, -1);
if (oldValue > -1)
@ -142,7 +143,8 @@ unnamed_sem_post(sem_t* semaphore) {
static int
unnamed_sem_trywait(sem_t* semaphore) {
unnamed_sem_trywait(sem_t* semaphore)
{
int32* sem = (int32*)&semaphore->u.unnamed_sem;
int32 oldValue = atomic_add_if_greater(sem, -1, 0);
if (oldValue > 0)
@ -153,22 +155,33 @@ unnamed_sem_trywait(sem_t* semaphore) {
static int
unnamed_sem_timedwait(sem_t* semaphore, const struct timespec* timeout) {
unnamed_sem_timedwait(sem_t* semaphore, clockid_t clock_id,
const struct timespec* timeout)
{
int32* sem = (int32*)&semaphore->u.unnamed_sem;
bigtime_t timeoutMicros = B_INFINITE_TIMEOUT;
uint32 flags = 0;
if (timeout != NULL) {
timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000
+ timeout->tv_nsec / 1000;
switch (clock_id) {
case CLOCK_REALTIME:
flags = B_ABSOLUTE_REAL_TIME_TIMEOUT;
break;
case CLOCK_MONOTONIC:
flags = B_ABSOLUTE_TIMEOUT;
break;
default:
return EINVAL;
}
}
int result = unnamed_sem_trywait(semaphore);
if (result == 0)
return 0;
return _kern_mutex_sem_acquire(sem, NULL,
timeoutMicros == B_INFINITE_TIMEOUT ? 0 : B_ABSOLUTE_REAL_TIME_TIMEOUT,
timeoutMicros);
return _kern_mutex_sem_acquire(sem, NULL, flags, timeoutMicros);
}
@ -186,11 +199,13 @@ sem_post(sem_t* semaphore)
static int
named_sem_timedwait(sem_t* semaphore, const struct timespec* timeout)
named_sem_timedwait(sem_t* semaphore, clockid_t clock_id,
const struct timespec* timeout)
{
if (timeout != NULL
&& (timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000)) {
status_t err = _kern_realtime_sem_wait(semaphore->u.named_sem_id, 0);
status_t err = _kern_realtime_sem_wait(semaphore->u.named_sem_id,
B_RELATIVE_TIMEOUT, 0);
if (err == B_WOULD_BLOCK)
err = EINVAL;
// do nothing, return err as it is.
@ -198,11 +213,22 @@ named_sem_timedwait(sem_t* semaphore, const struct timespec* timeout)
}
bigtime_t timeoutMicros = B_INFINITE_TIMEOUT;
uint32 flags = 0;
if (timeout != NULL) {
timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000
+ timeout->tv_nsec / 1000;
switch (clock_id) {
case CLOCK_REALTIME:
flags = B_ABSOLUTE_REAL_TIME_TIMEOUT;
break;
case CLOCK_MONOTONIC:
flags = B_ABSOLUTE_TIMEOUT;
break;
default:
return EINVAL;
}
}
status_t err = _kern_realtime_sem_wait(semaphore->u.named_sem_id,
status_t err = _kern_realtime_sem_wait(semaphore->u.named_sem_id, flags,
timeoutMicros);
if (err == B_WOULD_BLOCK)
err = ETIMEDOUT;
@ -215,9 +241,10 @@ int
sem_trywait(sem_t* semaphore)
{
status_t error;
if (semaphore->type == SEM_TYPE_NAMED)
error = _kern_realtime_sem_wait(semaphore->u.named_sem_id, 0);
else
if (semaphore->type == SEM_TYPE_NAMED) {
error = _kern_realtime_sem_wait(semaphore->u.named_sem_id,
B_RELATIVE_TIMEOUT, 0);
} else
error = unnamed_sem_trywait(semaphore);
RETURN_AND_SET_ERRNO(error);
@ -229,27 +256,34 @@ sem_wait(sem_t* semaphore)
{
status_t error;
if (semaphore->type == SEM_TYPE_NAMED)
error = named_sem_timedwait(semaphore, NULL);
error = named_sem_timedwait(semaphore, CLOCK_REALTIME, NULL);
else
error = unnamed_sem_timedwait(semaphore, NULL);
error = unnamed_sem_timedwait(semaphore, CLOCK_REALTIME, NULL);
RETURN_AND_SET_ERRNO_TEST_CANCEL(error);
}
int
sem_timedwait(sem_t* semaphore, const struct timespec* timeout)
sem_clockwait(sem_t* semaphore, clockid_t clock_id, const struct timespec* abstime)
{
status_t error;
if (semaphore->type == SEM_TYPE_NAMED)
error = named_sem_timedwait(semaphore, timeout);
error = named_sem_timedwait(semaphore, clock_id, abstime);
else
error = unnamed_sem_timedwait(semaphore, timeout);
error = unnamed_sem_timedwait(semaphore, clock_id, abstime);
RETURN_AND_SET_ERRNO_TEST_CANCEL(error);
}
int
sem_timedwait(sem_t* semaphore, const struct timespec* abstime)
{
return sem_clockwait(semaphore, CLOCK_REALTIME, abstime);
}
int
sem_getvalue(sem_t* semaphore, int* value)
{