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 <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
Jérôme Duval
2022-02-18 21:27:06 +00:00
committed by waddlesplash
parent a21676b669
commit a866e2d902
5 changed files with 62 additions and 34 deletions
+3 -1
View File
@@ -33,7 +33,9 @@ int sem_init(sem_t* semaphore, int shared, unsigned value);
int sem_destroy(sem_t* semaphore); int sem_destroy(sem_t* semaphore);
int sem_post(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_trywait(sem_t* semaphore);
int sem_wait(sem_t* semaphore); int sem_wait(sem_t* semaphore);
int sem_getvalue(sem_t* semaphore, int* value); int sem_getvalue(sem_t* semaphore, int* value);
+2 -1
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_get_value(sem_id semID, int* value);
status_t _user_realtime_sem_post(sem_id semID); 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 __END_DECLS
+2 -1
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_get_value(sem_id semID, int* value);
extern status_t _kern_realtime_sem_post(sem_id semID); 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 */ /* POSIX XSI semaphore syscalls */
extern int _kern_xsi_semget(key_t key, int numSems, int flags); extern int _kern_xsi_semget(key_t key, int numSems, int flags);
+4 -14
View File
@@ -506,7 +506,7 @@ struct realtime_sem_context {
return B_OK; 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); MutexLocker locker(fLock);
@@ -518,17 +518,7 @@ struct realtime_sem_context {
locker.Unlock(); locker.Unlock();
status_t error; status_t error = acquire_sem_etc(id, 1, flags | B_CAN_INTERRUPT, timeout);
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);
}
return error == B_BAD_SEM_ID ? B_BAD_VALUE : error; return error == B_BAD_SEM_ID ? B_BAD_VALUE : error;
} }
@@ -813,11 +803,11 @@ _user_realtime_sem_post(sem_id semID)
status_t 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(); realtime_sem_context* context = get_current_team_context();
if (context == NULL) if (context == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
return syscall_restart_handle_post(context->AcquireSem(semID, timeout)); return syscall_restart_handle_post(context->AcquireSem(semID, flags, timeout));
} }
+51 -17
View File
@@ -131,7 +131,8 @@ sem_destroy(sem_t* semaphore)
static int static int
unnamed_sem_post(sem_t* semaphore) { unnamed_sem_post(sem_t* semaphore)
{
int32* sem = (int32*)&semaphore->u.unnamed_sem; int32* sem = (int32*)&semaphore->u.unnamed_sem;
int32 oldValue = atomic_add_if_greater(sem, 1, -1); int32 oldValue = atomic_add_if_greater(sem, 1, -1);
if (oldValue > -1) if (oldValue > -1)
@@ -142,7 +143,8 @@ unnamed_sem_post(sem_t* semaphore) {
static int static int
unnamed_sem_trywait(sem_t* semaphore) { unnamed_sem_trywait(sem_t* semaphore)
{
int32* sem = (int32*)&semaphore->u.unnamed_sem; int32* sem = (int32*)&semaphore->u.unnamed_sem;
int32 oldValue = atomic_add_if_greater(sem, -1, 0); int32 oldValue = atomic_add_if_greater(sem, -1, 0);
if (oldValue > 0) if (oldValue > 0)
@@ -153,22 +155,33 @@ unnamed_sem_trywait(sem_t* semaphore) {
static int 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; int32* sem = (int32*)&semaphore->u.unnamed_sem;
bigtime_t timeoutMicros = B_INFINITE_TIMEOUT; bigtime_t timeoutMicros = B_INFINITE_TIMEOUT;
uint32 flags = 0;
if (timeout != NULL) { if (timeout != NULL) {
timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000 timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000
+ timeout->tv_nsec / 1000; + 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); int result = unnamed_sem_trywait(semaphore);
if (result == 0) if (result == 0)
return 0; return 0;
return _kern_mutex_sem_acquire(sem, NULL, return _kern_mutex_sem_acquire(sem, NULL, flags, timeoutMicros);
timeoutMicros == B_INFINITE_TIMEOUT ? 0 : B_ABSOLUTE_REAL_TIME_TIMEOUT,
timeoutMicros);
} }
@@ -186,11 +199,13 @@ sem_post(sem_t* semaphore)
static int 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 if (timeout != NULL
&& (timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000)) { && (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) if (err == B_WOULD_BLOCK)
err = EINVAL; err = EINVAL;
// do nothing, return err as it is. // 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; bigtime_t timeoutMicros = B_INFINITE_TIMEOUT;
uint32 flags = 0;
if (timeout != NULL) { if (timeout != NULL) {
timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000 timeoutMicros = ((bigtime_t)timeout->tv_sec) * 1000000
+ timeout->tv_nsec / 1000; + 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); timeoutMicros);
if (err == B_WOULD_BLOCK) if (err == B_WOULD_BLOCK)
err = ETIMEDOUT; err = ETIMEDOUT;
@@ -215,9 +241,10 @@ int
sem_trywait(sem_t* semaphore) sem_trywait(sem_t* semaphore)
{ {
status_t error; status_t error;
if (semaphore->type == SEM_TYPE_NAMED) if (semaphore->type == SEM_TYPE_NAMED) {
error = _kern_realtime_sem_wait(semaphore->u.named_sem_id, 0); error = _kern_realtime_sem_wait(semaphore->u.named_sem_id,
else B_RELATIVE_TIMEOUT, 0);
} else
error = unnamed_sem_trywait(semaphore); error = unnamed_sem_trywait(semaphore);
RETURN_AND_SET_ERRNO(error); RETURN_AND_SET_ERRNO(error);
@@ -229,27 +256,34 @@ sem_wait(sem_t* semaphore)
{ {
status_t error; status_t error;
if (semaphore->type == SEM_TYPE_NAMED) if (semaphore->type == SEM_TYPE_NAMED)
error = named_sem_timedwait(semaphore, NULL); error = named_sem_timedwait(semaphore, CLOCK_REALTIME, NULL);
else else
error = unnamed_sem_timedwait(semaphore, NULL); error = unnamed_sem_timedwait(semaphore, CLOCK_REALTIME, NULL);
RETURN_AND_SET_ERRNO_TEST_CANCEL(error); RETURN_AND_SET_ERRNO_TEST_CANCEL(error);
} }
int 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; status_t error;
if (semaphore->type == SEM_TYPE_NAMED) if (semaphore->type == SEM_TYPE_NAMED)
error = named_sem_timedwait(semaphore, timeout); error = named_sem_timedwait(semaphore, clock_id, abstime);
else else
error = unnamed_sem_timedwait(semaphore, timeout); error = unnamed_sem_timedwait(semaphore, clock_id, abstime);
RETURN_AND_SET_ERRNO_TEST_CANCEL(error); 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 int
sem_getvalue(sem_t* semaphore, int* value) sem_getvalue(sem_t* semaphore, int* value)
{ {