From b18f56eaf260761d8b9154e3004587c90f8c67b8 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 27 Oct 2023 12:45:10 -0400 Subject: thread: Move thread wrapper functions out of line --- GNUmakefile | 1 + src/thread.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/thread.h | 50 ++++++++++++++----------------------- 3 files changed, 100 insertions(+), 32 deletions(-) create mode 100644 src/thread.c diff --git a/GNUmakefile b/GNUmakefile index 62f24fb..2494b16 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -250,6 +250,7 @@ LIBBFS := \ $(OBJ)/src/printf.o \ $(OBJ)/src/pwcache.o \ $(OBJ)/src/stat.o \ + $(OBJ)/src/thread.o \ $(OBJ)/src/trie.o \ $(OBJ)/src/typo.o \ $(OBJ)/src/xregex.o \ diff --git a/src/thread.c b/src/thread.c new file mode 100644 index 0000000..200d8c3 --- /dev/null +++ b/src/thread.c @@ -0,0 +1,81 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include "thread.h" +#include "bfstd.h" +#include "config.h" +#include "diag.h" +#include +#include + +#define THREAD_FALLIBLE(expr) \ + do { \ + int err = expr; \ + if (err == 0) { \ + return 0; \ + } else { \ + errno = err; \ + return -1; \ + } \ + } while (0) + +#define THREAD_INFALLIBLE(...) \ + THREAD_INFALLIBLE_(__VA_ARGS__, 0, ) + +#define THREAD_INFALLIBLE_(expr, allowed, ...) \ + int err = expr; \ + bfs_verify(err == 0 || err == allowed, "%s: %s", #expr, xstrerror(err)); \ + (void)0 + +int thread_create(pthread_t *thread, const pthread_attr_t *attr, thread_fn *fn, void *arg) { + THREAD_FALLIBLE(pthread_create(thread, attr, fn, arg)); +} + +void thread_join(pthread_t thread, void **ret) { + THREAD_INFALLIBLE(pthread_join(thread, ret)); +} + +int mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr) { + THREAD_FALLIBLE(pthread_mutex_init(mutex, attr)); +} + +void mutex_lock(pthread_mutex_t *mutex) { + THREAD_INFALLIBLE(pthread_mutex_lock(mutex)); +} + +bool mutex_trylock(pthread_mutex_t *mutex) { + THREAD_INFALLIBLE(pthread_mutex_trylock(mutex), EBUSY); + return err == 0; +} + +void mutex_unlock(pthread_mutex_t *mutex) { + THREAD_INFALLIBLE(pthread_mutex_unlock(mutex)); +} + +void mutex_destroy(pthread_mutex_t *mutex) { + THREAD_INFALLIBLE(pthread_mutex_destroy(mutex)); +} + +int cond_init(pthread_cond_t *cond, pthread_condattr_t *attr) { + THREAD_FALLIBLE(pthread_cond_init(cond, attr)); +} + +void cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { + THREAD_INFALLIBLE(pthread_cond_wait(cond, mutex)); +} + +void cond_signal(pthread_cond_t *cond) { + THREAD_INFALLIBLE(pthread_cond_signal(cond)); +} + +void cond_broadcast(pthread_cond_t *cond) { + THREAD_INFALLIBLE(pthread_cond_broadcast(cond)); +} + +void cond_destroy(pthread_cond_t *cond) { + THREAD_INFALLIBLE(pthread_cond_destroy(cond)); +} + +void invoke_once(pthread_once_t *once, once_fn *fn) { + THREAD_INFALLIBLE(pthread_once(once, fn)); +} diff --git a/src/thread.h b/src/thread.h index a59033c..b37d45f 100644 --- a/src/thread.h +++ b/src/thread.h @@ -8,12 +8,8 @@ #ifndef BFS_THREAD_H #define BFS_THREAD_H -#include "bfstd.h" #include "config.h" -#include "diag.h" -#include #include -#include #if __STDC_VERSION__ < 202311L && !defined(thread_local) # if BFS_USE_THREADS_H @@ -23,8 +19,8 @@ # endif #endif -#define thread_verify(expr, cond) \ - bfs_verify((errno = (expr), (cond)), "%s: %s", #expr, xstrerror(errno)) +/** Thread entry point type. */ +typedef void *thread_fn(void *arg); /** * Wrapper for pthread_create(). @@ -32,26 +28,22 @@ * @return * 0 on success, -1 on error. */ -#define thread_create(thread, attr, fn, arg) \ - ((errno = pthread_create(thread, attr, fn, arg)) ? -1 : 0) +int thread_create(pthread_t *thread, const pthread_attr_t *attr, thread_fn *fn, void *arg); /** * Wrapper for pthread_join(). */ -#define thread_join(thread, ret) \ - thread_verify(pthread_join(thread, ret), errno == 0) +void thread_join(pthread_t thread, void **ret); /** * Wrapper for pthread_mutex_init(). */ -#define mutex_init(mutex, attr) \ - ((errno = pthread_mutex_init(mutex, attr)) ? -1 : 0) +int mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr); /** * Wrapper for pthread_mutex_lock(). */ -#define mutex_lock(mutex) \ - thread_verify(pthread_mutex_lock(mutex), errno == 0) +void mutex_lock(pthread_mutex_t *mutex); /** * Wrapper for pthread_mutex_trylock(). @@ -59,55 +51,49 @@ * @return * Whether the mutex was locked. */ -#define mutex_trylock(mutex) \ - (thread_verify(pthread_mutex_trylock(mutex), errno == 0 || errno == EBUSY), errno == 0) +bool mutex_trylock(pthread_mutex_t *mutex); /** * Wrapper for pthread_mutex_unlock(). */ -#define mutex_unlock(mutex) \ - thread_verify(pthread_mutex_unlock(mutex), errno == 0) +void mutex_unlock(pthread_mutex_t *mutex); /** * Wrapper for pthread_mutex_destroy(). */ -#define mutex_destroy(mutex) \ - thread_verify(pthread_mutex_destroy(mutex), errno == 0) +void mutex_destroy(pthread_mutex_t *mutex); /** * Wrapper for pthread_cond_init(). */ -#define cond_init(cond, attr) \ - ((errno = pthread_cond_init(cond, attr)) ? -1 : 0) +int cond_init(pthread_cond_t *cond, pthread_condattr_t *attr); /** * Wrapper for pthread_cond_wait(). */ -#define cond_wait(cond, mutex) \ - thread_verify(pthread_cond_wait(cond, mutex), errno == 0) +void cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); /** * Wrapper for pthread_cond_signal(). */ -#define cond_signal(cond) \ - thread_verify(pthread_cond_signal(cond), errno == 0) +void cond_signal(pthread_cond_t *cond); /** * Wrapper for pthread_cond_broadcast(). */ -#define cond_broadcast(cond) \ - thread_verify(pthread_cond_broadcast(cond), errno == 0) +void cond_broadcast(pthread_cond_t *cond); /** * Wrapper for pthread_cond_destroy(). */ -#define cond_destroy(cond) \ - thread_verify(pthread_cond_destroy(cond), errno == 0) +void cond_destroy(pthread_cond_t *cond); + +/** pthread_once() callback type. */ +typedef void once_fn(void); /** * Wrapper for pthread_once(). */ -#define invoke_once(once, fn) \ - thread_verify(pthread_once(once, fn), errno == 0) +void invoke_once(pthread_once_t *once, once_fn *fn); #endif // BFS_THREAD_H -- cgit v1.2.3