Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add C11 thread, mutex and condition API #249

Merged
merged 7 commits into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ endif()
#
include(GNUInstallDirs)
include(CheckIncludeFile)
include(CheckFunctionExists)
find_package(Backtrace)
find_package(Threads)
find_package(OpenSSL)
Expand Down Expand Up @@ -86,6 +87,11 @@ else()
set(Backtrace_LIBRARIES)
endif()

check_function_exists(thrd_create HAVE_THREADS)
if(HAVE_THREADS)
add_definitions(-DHAVE_THREADS)
endif()

if(CMAKE_USE_PTHREADS_INIT)
add_definitions(-DHAVE_PTHREAD)
set(HAVE_PTHREAD ON)
Expand Down Expand Up @@ -543,6 +549,21 @@ elseif(HAVE_PTHREAD)
)
endif()

if(HAVE_THREADS)
list(APPEND SRCS
src/thread/thread.c
)
elseif(HAVE_PTHREAD)
list(APPEND SRCS
src/thread/thread.c
src/thread/posix.c
)
elseif(CMAKE_USE_WIN32_THREADS_INIT)
list(APPEND SRCS
src/thread/thread.c
src/thread/win32.c
)
endif()

if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
list(APPEND SRCS
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ MODULES += dns
MODULES += md5 crc32 sha hmac base64
MODULES += udp sa net tcp tls
MODULES += list mbuf hash
MODULES += fmt tmr trace btrace main mem dbg sys lock mqueue
MODULES += fmt tmr trace btrace main mem dbg sys thread lock mqueue
MODULES += mod conf
MODULES += bfcp
MODULES += aes srtp
Expand Down
1 change: 1 addition & 0 deletions include/re.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ extern "C" {
#include "re_sys.h"
#include "re_tcp.h"
#include "re_telev.h"
#include "re_thread.h"
#include "re_tmr.h"
#include "re_trace.h"
#include "re_tls.h"
Expand Down
236 changes: 236 additions & 0 deletions include/re_thread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
/**
* @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)
* - POSIX PTHREAD (Linux/UNIX, winpthreads)
* - Windows Thread API
*
* Copyright (C) 2022 Sebastian Reimers
*/

#if defined(HAVE_THREADS)
#include <threads.h>

#else

#if defined(HAVE_PTHREAD)

#include <pthread.h>
#include <time.h>
#define THREAD_ONCE_FLAG_INIT PTHREAD_ONCE_INIT
typedef pthread_once_t thrd_once_flag;
typedef pthread_t thrd_t;
typedef pthread_cond_t cnd_t;
typedef pthread_mutex_t mtx_t;

#elif defined(WIN32)

#include <windows.h>
#define THREAD_ONCE_FLAG_INIT INIT_ONCE_STATIC_INIT
typedef INIT_ONCE thrd_once_flag;
typedef HANDLE thrd_t;
typedef CONDITION_VARIABLE cnd_t;
typedef CRITICAL_SECTION mtx_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 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 0 if success, otherwise errorcode
*/
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);


/**
* Checks whether `lhs` and `rhs` refer to the same 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.
*/
thrd_t thrd_current(void);


/**
* Detaches the thread identified by `thr` from the current environment.
*
* @return 0 if success, otherwise errorcode
*/
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 0 if success, otherwise errorcode
*/
int thrd_join(thrd_t thr, int *res);


/**
* Calls a function exactly once
*
* @param flag Pointer to object initialized by THREAD_ONCE_FLAG_INIT
* @param func The function to execute only once
*/
void call_once(thrd_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 0 if success, otherwise errorcode
*/
int cnd_init(cnd_t *cnd);


/**
* Unblocks one thread blocked on a condition variable
*
* @param cnd Pointer to condition variable
*
* @return 0 if success, otherwise errorcode
*/
int cnd_signal(cnd_t *cnd);


/**
* Unblocks all thrds blocked on a condition variable
*
* @param cnd Pointer to condition variable
*
* @return 0 if success, otherwise errorcode
*/
int cnd_broadcast(cnd_t *cnd);


/**
* Blocks on a condition variable
*
* @param cnd Pointer to condition variable
* @param lock Lock mutex pointer
*
* @return 0 if success, otherwise errorcode
*/
int cnd_wait(cnd_t *cnd, mtx_t *mtx);


/**
* 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 alread 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);


#endif /* C11 threads fallback */


/******************************************************************************
* Extra
*****************************************************************************/
/* int thrd_prio(enum thrd_prio prio) */
/* void thrd_print(struct re_printf *pf, void *unused); */
int thrd_create_name(thrd_t *thr, const char *name, thrd_start_t func,
void *arg);
4 changes: 4 additions & 0 deletions mk/re.mk
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,10 @@ CFLAGS += -DUSE_ZLIB
LIBS += -lz
endif

HAVE_THREADS := $(shell $(call CC_TEST,threads.h))
ifneq ($(HAVE_THREADS),)
CFLAGS += -DHAVE_THREADS
endif

HAVE_PTHREAD := $(shell $(call CC_TEST,pthread.h))
ifneq ($(HAVE_PTHREAD),)
Expand Down
9 changes: 9 additions & 0 deletions src/thread/mod.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ifdef HAVE_THREADS
SRCS += thread/thread.c
else ifdef HAVE_PTHREAD
SRCS += thread/thread.c
SRCS += thread/posix.c
else ifeq ($(OS),win32)
SRCS += thread/thread.c
SRCS += thread/win32.c
endif
Loading