diff --git a/headers/posix/semaphore.h b/headers/posix/semaphore.h index 0501830ac4..67216c7a1c 100644 --- a/headers/posix/semaphore.h +++ b/headers/posix/semaphore.h @@ -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); diff --git a/headers/private/kernel/posix/realtime_sem.h b/headers/private/kernel/posix/realtime_sem.h index 1fd8c5afd2..312b295628 100644 --- a/headers/private/kernel/posix/realtime_sem.h +++ b/headers/private/kernel/posix/realtime_sem.h @@ -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 diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index d428c163b1..94e95cbd42 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -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); diff --git a/src/system/kernel/posix/realtime_sem.cpp b/src/system/kernel/posix/realtime_sem.cpp index 4bd66525b6..d78d1b0b34 100644 --- a/src/system/kernel/posix/realtime_sem.cpp +++ b/src/system/kernel/posix/realtime_sem.cpp @@ -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)); } diff --git a/src/system/libroot/posix/semaphore.cpp b/src/system/libroot/posix/semaphore.cpp index 394e6b0898..41c72eebcc 100644 --- a/src/system/libroot/posix/semaphore.cpp +++ b/src/system/libroot/posix/semaphore.cpp @@ -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) {