From e883ea50dd1154294e21e946e391dd38e04d6527 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 23 Oct 2022 12:55:40 -0400 Subject: 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. --- meson.build | 21 +++- meson/suppressions/meson.build | 1 + src/darwin/sem_darwin.c | 68 +++++++++++++ src/posix/sem_posix.c | 89 +++++++++++++++++ src/posix/thread_posix.c | 34 +++++++ src/sem.c | 212 ----------------------------------------- src/thread.c | 62 ------------ src/win32/sem_win32.c | 63 ++++++++++++ src/win32/thread_win32.c | 28 ++++++ 9 files changed, 300 insertions(+), 278 deletions(-) create mode 100644 src/darwin/sem_darwin.c create mode 100644 src/posix/sem_posix.c create mode 100644 src/posix/thread_posix.c delete mode 100644 src/sem.c delete mode 100644 src/thread.c create mode 100644 src/win32/sem_win32.c create mode 100644 src/win32/thread_win32.c diff --git a/meson.build b/meson.build index 58669cf..c56a10e 100644 --- a/meson.build +++ b/meson.build @@ -118,14 +118,27 @@ sources = files( 'src/hash.c', 'src/ring.c', 'src/status.c', - 'src/thread.c', 'src/tree.c', ) if thread_dep.found() - sources += files( - 'src/sem.c', - ) + if host_machine.system() == 'darwin' + sources += files( + 'src/darwin/sem_darwin.c', + 'src/posix/thread_posix.c', + ) + + elif host_machine.system() == 'windows' + sources += files( + 'src/win32/sem_win32.c', + 'src/win32/thread_win32.c', + ) + else + sources += files( + 'src/posix/sem_posix.c', + 'src/posix/thread_posix.c', + ) + endif endif # Set appropriate arguments for building against the library type diff --git a/meson/suppressions/meson.build b/meson/suppressions/meson.build index 5b2d0d0..06a0821 100644 --- a/meson/suppressions/meson.build +++ b/meson/suppressions/meson.build @@ -49,6 +49,7 @@ if is_variable('cc') '/wd4191', # unsafe function conversion '/wd4200', # zero-sized array in struct/union '/wd4365', # signed/unsigned mismatch + '/wd4464', # relative include path contains ".." '/wd4514', # unreferenced inline function has been removed '/wd4710', # function not inlined '/wd4711', # function selected for automatic inline expansion diff --git a/src/darwin/sem_darwin.c b/src/darwin/sem_darwin.c new file mode 100644 index 0000000..0ace564 --- /dev/null +++ b/src/darwin/sem_darwin.c @@ -0,0 +1,68 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "zix/sem.h" + +#include "zix/status.h" + +#include + +#include +#include + +ZixStatus +zix_sem_init(ZixSem* sem, unsigned val) +{ + return semaphore_create( + mach_task_self(), &sem->sem, SYNC_POLICY_FIFO, (int)val) + ? ZIX_STATUS_ERROR + : ZIX_STATUS_SUCCESS; +} + +ZixStatus +zix_sem_destroy(ZixSem* sem) +{ + return semaphore_destroy(mach_task_self(), sem->sem) ? ZIX_STATUS_ERROR + : ZIX_STATUS_SUCCESS; +} + +ZixStatus +zix_sem_post(ZixSem* sem) +{ + return semaphore_signal(sem->sem) ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS; +} + +ZixStatus +zix_sem_wait(ZixSem* sem) +{ + kern_return_t r = 0; + while ((r = semaphore_wait(sem->sem)) && r == KERN_ABORTED) { + // Interrupted, try again + } + + return r ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS; +} + +ZixStatus +zix_sem_try_wait(ZixSem* sem) +{ + const mach_timespec_t zero = {0, 0}; + const kern_return_t r = semaphore_timedwait(sem->sem, zero); + + return (r == KERN_SUCCESS) ? ZIX_STATUS_SUCCESS + : (r == KERN_OPERATION_TIMED_OUT) ? ZIX_STATUS_UNAVAILABLE + : ZIX_STATUS_ERROR; +} + +ZixStatus +zix_sem_timed_wait(ZixSem* sem, + const uint32_t seconds, + const uint32_t nanoseconds) +{ + const mach_timespec_t interval = {seconds, (clock_res_t)nanoseconds}; + const kern_return_t r = semaphore_timedwait(sem->sem, interval); + + return (r == KERN_SUCCESS) ? ZIX_STATUS_SUCCESS + : (r == KERN_OPERATION_TIMED_OUT) ? ZIX_STATUS_TIMEOUT + : ZIX_STATUS_ERROR; +} 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 +// SPDX-License-Identifier: ISC + +#include "zix/sem.h" + +#include "../errno_status.h" +#include "../zix_config.h" + +#include "zix/status.h" + +#include + +#include +#include +#include + +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 +} diff --git a/src/posix/thread_posix.c b/src/posix/thread_posix.c new file mode 100644 index 0000000..2073448 --- /dev/null +++ b/src/posix/thread_posix.c @@ -0,0 +1,34 @@ +// Copyright 2012-2020 David Robillard +// SPDX-License-Identifier: ISC + +#include "zix/thread.h" + +#include "../errno_status.h" + +#include "zix/status.h" + +#include + +#include + +ZixStatus +zix_thread_create(ZixThread* thread, + size_t stack_size, + ZixThreadFunc function, + void* arg) +{ + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, stack_size); + + const int ret = pthread_create(thread, NULL, function, arg); + + pthread_attr_destroy(&attr); + return zix_errno_status(ret); +} + +ZixStatus +zix_thread_join(ZixThread thread) +{ + return pthread_join(thread, NULL) ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS; +} diff --git a/src/sem.c b/src/sem.c deleted file mode 100644 index 4b87297..0000000 --- a/src/sem.c +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2012-2022 David Robillard -// SPDX-License-Identifier: ISC - -#include "zix/sem.h" - -#include "errno_status.h" -#include "zix_config.h" - -#include "zix/status.h" - -#ifdef __APPLE__ -# include -#elif defined(_WIN32) -# include -# include -#else -# include -# include -#endif - -#include -#include - -#ifdef __APPLE__ - -ZixStatus -zix_sem_init(ZixSem* sem, unsigned val) -{ - return semaphore_create( - mach_task_self(), &sem->sem, SYNC_POLICY_FIFO, (int)val) - ? ZIX_STATUS_ERROR - : ZIX_STATUS_SUCCESS; -} - -ZixStatus -zix_sem_destroy(ZixSem* sem) -{ - return semaphore_destroy(mach_task_self(), sem->sem) ? ZIX_STATUS_ERROR - : ZIX_STATUS_SUCCESS; -} - -ZixStatus -zix_sem_post(ZixSem* sem) -{ - return semaphore_signal(sem->sem) ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS; -} - -ZixStatus -zix_sem_wait(ZixSem* sem) -{ - kern_return_t r = 0; - while ((r = semaphore_wait(sem->sem)) && r == KERN_ABORTED) { - // Interrupted, try again - } - - return r ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS; -} - -ZixStatus -zix_sem_try_wait(ZixSem* sem) -{ - const mach_timespec_t zero = {0, 0}; - const kern_return_t r = semaphore_timedwait(sem->sem, zero); - - return (r == KERN_SUCCESS) ? ZIX_STATUS_SUCCESS - : (r == KERN_OPERATION_TIMED_OUT) ? ZIX_STATUS_UNAVAILABLE - : ZIX_STATUS_ERROR; -} - -ZixStatus -zix_sem_timed_wait(ZixSem* sem, - const uint32_t seconds, - const uint32_t nanoseconds) -{ - const mach_timespec_t interval = {seconds, (clock_res_t)nanoseconds}; - const kern_return_t r = semaphore_timedwait(sem->sem, interval); - - return (r == KERN_SUCCESS) ? ZIX_STATUS_SUCCESS - : (r == KERN_OPERATION_TIMED_OUT) ? ZIX_STATUS_TIMEOUT - : ZIX_STATUS_ERROR; -} - -#elif defined(_WIN32) - -ZixStatus -zix_sem_init(ZixSem* sem, unsigned initial) -{ - sem->sem = CreateSemaphore(NULL, (LONG)initial, LONG_MAX, NULL); - return sem->sem ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR; -} - -ZixStatus -zix_sem_destroy(ZixSem* sem) -{ - return CloseHandle(sem->sem) ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR; -} - -ZixStatus -zix_sem_post(ZixSem* sem) -{ - return ReleaseSemaphore(sem->sem, 1, NULL) ? ZIX_STATUS_SUCCESS - : ZIX_STATUS_ERROR; -} - -ZixStatus -zix_sem_wait(ZixSem* sem) -{ - return WaitForSingleObject(sem->sem, INFINITE) == WAIT_OBJECT_0 - ? ZIX_STATUS_SUCCESS - : ZIX_STATUS_ERROR; -} - -ZixStatus -zix_sem_try_wait(ZixSem* sem) -{ - const DWORD r = WaitForSingleObject(sem->sem, 0); - - return (r == WAIT_OBJECT_0) ? ZIX_STATUS_SUCCESS - : (r == WAIT_TIMEOUT) ? ZIX_STATUS_UNAVAILABLE - : ZIX_STATUS_ERROR; -} - -ZixStatus -zix_sem_timed_wait(ZixSem* sem, - const uint32_t seconds, - const uint32_t nanoseconds) -{ - const uint32_t milliseconds = seconds * 1000U + nanoseconds / 1000000U; - const DWORD r = WaitForSingleObject(sem->sem, milliseconds); - - return (r == WAIT_OBJECT_0) ? ZIX_STATUS_SUCCESS - : (r == WAIT_TIMEOUT) ? ZIX_STATUS_TIMEOUT - : ZIX_STATUS_ERROR; -} - -#else /* !defined(__APPLE__) && !defined(_WIN32) */ - -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) -{ -# define NS_PER_SECOND 1000000000L - -# if !USE_CLOCK_GETTIME || !USE_SEM_TIMEDWAIT - return ZIX_STATUS_NOT_SUPPORTED; - -# else - - 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); -# endif - -# undef NS_PER_SECOND -} - -#endif diff --git a/src/thread.c b/src/thread.c deleted file mode 100644 index 9b8af20..0000000 --- a/src/thread.c +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2012-2020 David Robillard -// SPDX-License-Identifier: ISC - -#include "zix/thread.h" - -#include "errno_status.h" - -#include "zix/status.h" - -#ifdef _WIN32 -# include -#else -# include -#endif - -#include - -#ifdef _WIN32 - -ZixStatus -zix_thread_create(ZixThread* thread, - size_t stack_size, - ZixThreadFunc function, - void* arg) -{ - *thread = CreateThread(NULL, stack_size, function, arg, 0, NULL); - return *thread ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR; -} - -ZixStatus -zix_thread_join(ZixThread thread) -{ - return (WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0) - ? ZIX_STATUS_SUCCESS - : ZIX_STATUS_ERROR; -} - -#else // !defined(_WIN32) - -ZixStatus -zix_thread_create(ZixThread* thread, - size_t stack_size, - ZixThreadFunc function, - void* arg) -{ - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, stack_size); - - const int ret = pthread_create(thread, NULL, function, arg); - - pthread_attr_destroy(&attr); - return zix_errno_status(ret); -} - -ZixStatus -zix_thread_join(ZixThread thread) -{ - return pthread_join(thread, NULL) ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS; -} - -#endif diff --git a/src/win32/sem_win32.c b/src/win32/sem_win32.c new file mode 100644 index 0000000..979390e --- /dev/null +++ b/src/win32/sem_win32.c @@ -0,0 +1,63 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "zix/sem.h" + +#include "zix/status.h" + +#include + +#include +#include +#include + +ZixStatus +zix_sem_init(ZixSem* sem, unsigned initial) +{ + sem->sem = CreateSemaphore(NULL, (LONG)initial, LONG_MAX, NULL); + return sem->sem ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR; +} + +ZixStatus +zix_sem_destroy(ZixSem* sem) +{ + return CloseHandle(sem->sem) ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR; +} + +ZixStatus +zix_sem_post(ZixSem* sem) +{ + return ReleaseSemaphore(sem->sem, 1, NULL) ? ZIX_STATUS_SUCCESS + : ZIX_STATUS_ERROR; +} + +ZixStatus +zix_sem_wait(ZixSem* sem) +{ + return WaitForSingleObject(sem->sem, INFINITE) == WAIT_OBJECT_0 + ? ZIX_STATUS_SUCCESS + : ZIX_STATUS_ERROR; +} + +ZixStatus +zix_sem_try_wait(ZixSem* sem) +{ + const DWORD r = WaitForSingleObject(sem->sem, 0); + + return (r == WAIT_OBJECT_0) ? ZIX_STATUS_SUCCESS + : (r == WAIT_TIMEOUT) ? ZIX_STATUS_UNAVAILABLE + : ZIX_STATUS_ERROR; +} + +ZixStatus +zix_sem_timed_wait(ZixSem* sem, + const uint32_t seconds, + const uint32_t nanoseconds) +{ + const uint32_t milliseconds = seconds * 1000U + nanoseconds / 1000000U; + const DWORD r = WaitForSingleObject(sem->sem, milliseconds); + + return (r == WAIT_OBJECT_0) ? ZIX_STATUS_SUCCESS + : (r == WAIT_TIMEOUT) ? ZIX_STATUS_TIMEOUT + : ZIX_STATUS_ERROR; +} diff --git a/src/win32/thread_win32.c b/src/win32/thread_win32.c new file mode 100644 index 0000000..e4411b1 --- /dev/null +++ b/src/win32/thread_win32.c @@ -0,0 +1,28 @@ +// Copyright 2012-2022 David Robillard +// SPDX-License-Identifier: ISC + +#include "zix/thread.h" + +#include "zix/status.h" + +#include + +#include + +ZixStatus +zix_thread_create(ZixThread* thread, + size_t stack_size, + ZixThreadFunc function, + void* arg) +{ + *thread = CreateThread(NULL, stack_size, function, arg, 0, NULL); + return *thread ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR; +} + +ZixStatus +zix_thread_join(ZixThread thread) +{ + return (WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0) + ? ZIX_STATUS_SUCCESS + : ZIX_STATUS_ERROR; +} -- cgit v1.2.1