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:
committed by
waddlesplash
parent
a21676b669
commit
a866e2d902
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user