53 lines
995 B
C++
53 lines
995 B
C++
#include <BAN/Atomic.h>
|
|
|
|
#include <errno.h>
|
|
#include <semaphore.h>
|
|
#include <sys/futex.h>
|
|
|
|
int sem_destroy(sem_t* sem)
|
|
{
|
|
(void)sem;
|
|
return 0;
|
|
}
|
|
|
|
int sem_init(sem_t* sem, int pshared, unsigned value)
|
|
{
|
|
*sem = {
|
|
.shared = pshared,
|
|
.value = value,
|
|
};
|
|
return 0;
|
|
}
|
|
|
|
int sem_post(sem_t* sem)
|
|
{
|
|
const auto old = BAN::atomic_fetch_add(sem->value, 1);
|
|
if (old == 0)
|
|
futex(FUTEX_WAKE, &sem->value, 1, nullptr);
|
|
return 0;
|
|
}
|
|
|
|
int sem_trywait(sem_t* sem)
|
|
{
|
|
uint32_t expected = BAN::atomic_load(sem->value);
|
|
while (expected)
|
|
if (BAN::atomic_compare_exchange(sem->value, expected, expected - 1))
|
|
return 0;
|
|
errno = EAGAIN;
|
|
return -1;
|
|
}
|
|
|
|
int sem_wait(sem_t* sem)
|
|
{
|
|
for (;;)
|
|
{
|
|
uint32_t expected = BAN::atomic_load(sem->value);
|
|
if (expected > 0 && BAN::atomic_compare_exchange(sem->value, expected, expected - 1))
|
|
return 0;
|
|
|
|
const int op = FUTEX_WAIT | (sem->shared ? 0 : FUTEX_PRIVATE);
|
|
if (futex(op, &sem->value, expected, nullptr) == -1 && errno == EINTR)
|
|
return -1;
|
|
}
|
|
}
|