315 lines
7.3 KiB
C
315 lines
7.3 KiB
C
/**
|
|
* @file re_thread.h Thread support
|
|
*
|
|
* Inspired by C11 thread support this provides a cross platform interfaces to
|
|
* thread, mutex and condition handling (C11, POSIX and Windows Threads).
|
|
*
|
|
* Preferred order:
|
|
*
|
|
* - C11 threads (glibc>=2.28, musl, FreeBSD>=10)
|
|
* - Windows Thread API
|
|
* - POSIX PTHREAD (Linux/UNIX)
|
|
*
|
|
* Copyright (C) 2022 Sebastian Reimers
|
|
*/
|
|
|
|
#ifndef RE_H_THREAD__
|
|
#define RE_H_THREAD__
|
|
|
|
#if defined(HAVE_THREADS)
|
|
#include <threads.h>
|
|
|
|
#else
|
|
|
|
#if defined(WIN32)
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
|
|
struct thrd_win32 {
|
|
HANDLE hdl;
|
|
DWORD id;
|
|
};
|
|
#define ONCE_FLAG_INIT INIT_ONCE_STATIC_INIT
|
|
typedef INIT_ONCE once_flag;
|
|
typedef struct thrd_win32 thrd_t;
|
|
typedef CONDITION_VARIABLE cnd_t;
|
|
typedef CRITICAL_SECTION mtx_t;
|
|
typedef DWORD tss_t;
|
|
|
|
#else
|
|
|
|
#include <pthread.h>
|
|
#include <time.h>
|
|
#define ONCE_FLAG_INIT PTHREAD_ONCE_INIT
|
|
typedef pthread_once_t once_flag;
|
|
typedef pthread_t thrd_t;
|
|
typedef pthread_cond_t cnd_t;
|
|
typedef pthread_mutex_t mtx_t;
|
|
typedef pthread_key_t tss_t;
|
|
|
|
#endif
|
|
|
|
enum { mtx_plain = 0, mtx_try = 1, mtx_timed = 2, mtx_recursive = 4 };
|
|
|
|
/* Exit and error codes. */
|
|
enum {
|
|
thrd_success = 0,
|
|
thrd_busy = 1,
|
|
thrd_error = 2,
|
|
thrd_nomem = 3,
|
|
thrd_timedout = 4
|
|
};
|
|
|
|
typedef void (*tss_dtor_t)(void *);
|
|
typedef int (*thrd_start_t)(void *);
|
|
|
|
|
|
/******************************************************************************
|
|
* Thread functions
|
|
*****************************************************************************/
|
|
|
|
/**
|
|
* Creates a new thread
|
|
*
|
|
* @param thr Pointer to new thread
|
|
* @param func Function to execute
|
|
* @param arg Argument to pass to the function
|
|
*
|
|
* @return thrd_success on success, otherwise thrd_error
|
|
*/
|
|
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
|
|
|
|
|
|
/**
|
|
* Checks whether `lhs` and `rhs` refer to the same thread.
|
|
*
|
|
* @param lhs Left hand side thread
|
|
* @param rhs Right hand side thread
|
|
*
|
|
* @return Non-zero value if lhs and rhs refer to the same value, 0 otherwise.
|
|
*/
|
|
int thrd_equal(thrd_t lhs, thrd_t rhs);
|
|
|
|
|
|
/**
|
|
* Return the identifier of the calling thread.
|
|
*
|
|
* @return Current thread
|
|
*/
|
|
thrd_t thrd_current(void);
|
|
|
|
|
|
/**
|
|
* Detaches the thread identified by `thr` from the current environment.
|
|
*
|
|
* @param thr Thread
|
|
*
|
|
* @return thrd_success on success, otherwise thrd_error
|
|
*/
|
|
int thrd_detach(thrd_t thr);
|
|
|
|
|
|
/**
|
|
* Blocks the current thread until the thread identified by `thr` finishes
|
|
* execution
|
|
*
|
|
* @param thr Thread
|
|
* @param res Result code location
|
|
*
|
|
* @return thrd_success on success, otherwise thrd_error
|
|
*/
|
|
int thrd_join(thrd_t thr, int *res);
|
|
|
|
|
|
/**
|
|
* Calls a function exactly once
|
|
*
|
|
* @param flag Pointer to object initialized by ONCE_FLAG_INIT
|
|
* @param func The function to execute only once
|
|
*/
|
|
void call_once(once_flag *flag, void (*func)(void));
|
|
|
|
|
|
/**
|
|
* Terminates the calling thread
|
|
*
|
|
* @param res The result value to return
|
|
*/
|
|
void thrd_exit(int res);
|
|
|
|
|
|
/******************************************************************************
|
|
* Condition functions
|
|
*****************************************************************************/
|
|
|
|
/**
|
|
* Initializes new condition variable
|
|
*
|
|
* @param cnd Pointer to a variable to store condition variable
|
|
*
|
|
* @return thrd_success on success, otherwise thrd_error
|
|
*/
|
|
int cnd_init(cnd_t *cnd);
|
|
|
|
|
|
/**
|
|
* Unblocks one thread blocked on a condition variable
|
|
*
|
|
* @param cnd Pointer to condition variable
|
|
*
|
|
* @return thrd_success on success, otherwise thrd_error
|
|
*/
|
|
int cnd_signal(cnd_t *cnd);
|
|
|
|
|
|
/**
|
|
* Unblocks all thrds blocked on a condition variable
|
|
*
|
|
* @param cnd Pointer to condition variable
|
|
*
|
|
* @return thrd_success on success, otherwise thrd_error
|
|
*/
|
|
int cnd_broadcast(cnd_t *cnd);
|
|
|
|
|
|
/**
|
|
* Blocks on a condition variable
|
|
*
|
|
* @param cnd Pointer to condition variable
|
|
* @param mtx Lock mutex pointer
|
|
*
|
|
* @return thrd_success on success, otherwise thrd_error
|
|
*/
|
|
int cnd_wait(cnd_t *cnd, mtx_t *mtx);
|
|
|
|
|
|
/**
|
|
* Blocks on a condition variable with timeout (TIME_UTC based)
|
|
*
|
|
* @param cnd Pointer to condition variable
|
|
* @param mtx Lock mutex pointer
|
|
* @param abstime Pointer to timeout time
|
|
*
|
|
* @return thrd_success on success, thrd_timedout if the timeout time
|
|
* has been reached before the mutex is locked, otherwise thrd_error
|
|
*/
|
|
int cnd_timedwait(cnd_t *cnd, mtx_t *mtx, const struct timespec *abstime);
|
|
|
|
|
|
/**
|
|
* Destroys the condition variable pointed to by cnd.
|
|
* If there are thrds waiting on cnd, the behavior is undefined.
|
|
*
|
|
* @param cnd pointer to the condition variable to destroy
|
|
*/
|
|
void cnd_destroy(cnd_t *cnd);
|
|
|
|
|
|
/******************************************************************************
|
|
* Mutex functions
|
|
*****************************************************************************/
|
|
|
|
/**
|
|
* Creates a new mutex object with type. The object pointed to by mutex is set
|
|
* to an identifier of the newly created mutex.
|
|
*
|
|
* @param mtx Pointer to the mutex to initialize
|
|
* @param type The type of the mutex
|
|
*
|
|
* @return thrd_success on success, otherwise thrd_error
|
|
*/
|
|
int mtx_init(mtx_t *mtx, int type);
|
|
|
|
|
|
/**
|
|
* Blocks the current thread until the mutex pointed to by mutex is locked.
|
|
* The behavior is undefined if the current thread has already locked the
|
|
* mutex and the mutex is not recursive.
|
|
*
|
|
* @param mtx Pointer to the mutex
|
|
*
|
|
* @return thrd_success on success, otherwise thrd_error
|
|
*/
|
|
int mtx_lock(mtx_t *mtx);
|
|
|
|
|
|
/**
|
|
* Tries to lock the mutex pointed to by mutex without blocking.
|
|
* Returns immediately if the mutex is already locked.
|
|
*
|
|
* @param mtx Pointer to the mutex
|
|
*
|
|
* @return thrd_success on success, thrd_busy if already locked,
|
|
* otherwise thrd_error
|
|
*/
|
|
int mtx_trylock(mtx_t *mtx);
|
|
|
|
|
|
/**
|
|
* Unlocks the mutex pointed to by mutex.
|
|
*
|
|
* @param mtx Pointer to the mutex
|
|
*
|
|
* @return thrd_success on success, otherwise thrd_error
|
|
*/
|
|
int mtx_unlock(mtx_t *mtx);
|
|
|
|
|
|
/**
|
|
* Destroys the mutex pointed to by mutex.
|
|
* If there are threads waiting on mutex, the behavior is undefined.
|
|
*
|
|
* @param mtx Pointer to the mutex
|
|
*/
|
|
void mtx_destroy(mtx_t *mtx);
|
|
|
|
|
|
/******************************************************************************
|
|
* Thread-local storage functions
|
|
*****************************************************************************/
|
|
int tss_create(tss_t *key, tss_dtor_t destructor);
|
|
void *tss_get(tss_t key);
|
|
int tss_set(tss_t key, void *val);
|
|
void tss_delete(tss_t key);
|
|
|
|
#endif /* C11 threads fallback */
|
|
|
|
|
|
/******************************************************************************
|
|
* Extra - non C11 helpers
|
|
* (We avoid tss_ mtx_ cnd_ prefixes since these reserved for functions with
|
|
* different return values)
|
|
*****************************************************************************/
|
|
|
|
/* Ideas: */
|
|
/* int thread_prio(enum thrd_prio prio) */
|
|
/* void thread_print(struct re_printf *pf, void *unused); */
|
|
|
|
/**
|
|
* Allocates and initializes a new mutex
|
|
*
|
|
* @param mtx Pointer to new mutex
|
|
*
|
|
* @return 0 if success, otherwise errorcode
|
|
*/
|
|
int mutex_alloc(mtx_t **mtx);
|
|
int mutex_alloc_tp(mtx_t **mtx, int type);
|
|
|
|
|
|
/**
|
|
* Creates a new thread with name
|
|
*
|
|
* @param thr Pointer to new thread
|
|
* @param name Unique name for a thread
|
|
* @param func Function to execute
|
|
* @param arg Argument to pass to the function
|
|
*
|
|
* @return 0 if success, otherwise errorcode
|
|
*/
|
|
int thread_create_name(thrd_t *thr, const char *name, thrd_start_t func,
|
|
void *arg);
|
|
|
|
#endif /* RE_H_THREAD__ */
|