diff options
author | David Robillard <d@drobilla.net> | 2022-10-23 12:55:40 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2022-10-23 13:26:00 -0400 |
commit | e883ea50dd1154294e21e946e391dd38e04d6527 (patch) | |
tree | 2019aecf50e1eb2f73a2aaf567d0f4573d9efc31 /src/posix/sem_posix.c | |
parent | 07b1289cd4907aa3defe3fc600f3db1dcefcb719 (diff) | |
download | zix-e883ea50dd1154294e21e946e391dd38e04d6527.tar.gz zix-e883ea50dd1154294e21e946e391dd38e04d6527.tar.bz2 zix-e883ea50dd1154294e21e946e391dd38e04d6527.zip |
Split up platform sources
This puts more onus on the build system to do things properly, but it's still
easy enough to build, even manually: all the files in the appropriate system
subdirectory just need to be included in the build.
Otherwise, the several nested levels of preprocessor conditionals get
confusing, and clang-format doesn't format code properly.
Diffstat (limited to 'src/posix/sem_posix.c')
-rw-r--r-- | src/posix/sem_posix.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/posix/sem_posix.c b/src/posix/sem_posix.c new file mode 100644 index 0000000..452830d --- /dev/null +++ b/src/posix/sem_posix.c @@ -0,0 +1,89 @@ +// Copyright 2012-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +#include "zix/sem.h" + +#include "../errno_status.h" +#include "../zix_config.h" + +#include "zix/status.h" + +#include <semaphore.h> + +#include <errno.h> +#include <stdint.h> +#include <time.h> + +ZixStatus +zix_sem_init(ZixSem* sem, unsigned initial) +{ + return zix_errno_status_if(sem_init(&sem->sem, 0, initial)); +} + +ZixStatus +zix_sem_destroy(ZixSem* sem) +{ + return zix_errno_status_if(sem_destroy(&sem->sem)); +} + +ZixStatus +zix_sem_post(ZixSem* sem) +{ + return zix_errno_status_if(sem_post(&sem->sem)); +} + +ZixStatus +zix_sem_wait(ZixSem* sem) +{ + int r = 0; + while ((r = sem_wait(&sem->sem)) && errno == EINTR) { + // Interrupted, try again + } + + return zix_errno_status_if(r); +} + +ZixStatus +zix_sem_try_wait(ZixSem* sem) +{ + int r = 0; + while ((r = sem_trywait(&sem->sem)) && errno == EINTR) { + // Interrupted, try again + } + + return zix_errno_status_if(r); +} + +ZixStatus +zix_sem_timed_wait(ZixSem* sem, + const uint32_t seconds, + const uint32_t nanoseconds) +{ +#if !USE_CLOCK_GETTIME || !USE_SEM_TIMEDWAIT + + return ZIX_STATUS_NOT_SUPPORTED; + +#else +# define NS_PER_SECOND 1000000000L + + struct timespec ts = {0, 0}; + + int r = 0; + if (!(r = clock_gettime(CLOCK_REALTIME, &ts))) { + ts.tv_sec += (time_t)seconds; + ts.tv_nsec += (long)nanoseconds; + if (ts.tv_nsec >= NS_PER_SECOND) { + ts.tv_nsec -= NS_PER_SECOND; + ts.tv_sec++; + } + + while ((r = sem_timedwait(&sem->sem, &ts)) && errno == EINTR) { + // Interrupted, try again + } + } + + return zix_errno_status_if(r); + +# undef NS_PER_SECOND +#endif +} |