summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2022-12-18 00:12:32 +0100
committerMitya Selivanov <automainint@guattari.tech>2022-12-18 00:12:32 +0100
commit251f92ede2255d7f52667a0d5794136f5da2b8c6 (patch)
treea5000513469d128aa56aa287fe6e7db653c41de1 /source
parent901478a2d04fcae70cf1f99f19b7508256633fa0 (diff)
downloadkit-251f92ede2255d7f52667a0d5794136f5da2b8c6.zip
Threads cleanup
Diffstat (limited to 'source')
-rw-r--r--source/kit/CMakeLists.txt6
-rw-r--r--source/kit/condition_variable.h35
-rw-r--r--source/kit/mersenne_twister_64.c8
-rw-r--r--source/kit/mersenne_twister_64.h2
-rw-r--r--source/kit/mutex.h44
-rw-r--r--source/kit/secure_random.c23
-rw-r--r--source/kit/secure_random.h5
-rw-r--r--source/kit/thread.h92
-rw-r--r--source/kit/thread.posix.c (renamed from source/kit/threads.posix.c)66
-rw-r--r--source/kit/thread.win32.c (renamed from source/kit/threads.win32.c)81
-rw-r--r--source/kit/threads.h197
-rw-r--r--source/kit/time.c43
-rw-r--r--source/kit/time.h43
-rw-r--r--source/test/unittests/atomic.test.c2
-rw-r--r--source/test/unittests/condition_variable.test.c1
-rw-r--r--source/test/unittests/mersenne_twister_64.test.c4
-rw-r--r--source/test/unittests/mutex.test.c1
-rw-r--r--source/test/unittests/secure_random.test.c4
-rw-r--r--source/test/unittests/thread.test.c2
19 files changed, 218 insertions, 441 deletions
diff --git a/source/kit/CMakeLists.txt b/source/kit/CMakeLists.txt
index f9a30d2..e12077a 100644
--- a/source/kit/CMakeLists.txt
+++ b/source/kit/CMakeLists.txt
@@ -1,8 +1,8 @@
target_sources(
${KIT_LIBRARY}
PRIVATE
- input_buffer.c bigint.c status.c threads.win32.c time.c
- secure_random.c atomic.win32.c threads.posix.c condition_variable.c
+ input_buffer.c bigint.c status.c time.c secure_random.c
+ thread.posix.c atomic.win32.c condition_variable.c thread.win32.c
move_back.c input_stream.c lower_bound.c file.c string_ref.c
async_function.c allocator.c array_ref.c dynamic_array.c mutex.c
mersenne_twister_64.c
@@ -13,7 +13,7 @@ target_sources(
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/atomic.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/allocator.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/string_ref.h>
- $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/threads.h>
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/thread.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/bigint.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/dynamic_array.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/condition_variable.h>
diff --git a/source/kit/condition_variable.h b/source/kit/condition_variable.h
index dd3b891..0e4630d 100644
--- a/source/kit/condition_variable.h
+++ b/source/kit/condition_variable.h
@@ -1,6 +1,39 @@
#ifndef KIT_CONDITION_VARIABLE_H
#define KIT_CONDITION_VARIABLE_H
-#include "threads.h"
+#ifndef KIT_DISABLE_SYSTEM_THREADS
+# include "mutex.h"
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if defined(_WIN32) && !defined(__CYGWIN__)
+typedef struct {
+ void *Ptr;
+} cnd_t;
+
+typedef struct {
+ volatile uintptr_t status;
+} once_flag;
+# else
+typedef pthread_cond_t cnd_t;
+typedef pthread_once_t once_flag;
+# endif
+
+void call_once(once_flag *, void (*)(void));
+int cnd_broadcast(cnd_t *);
+void cnd_destroy(cnd_t *);
+int cnd_init(cnd_t *);
+int cnd_signal(cnd_t *);
+int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict mtx_,
+ const struct timespec *__restrict);
+int cnd_wait(cnd_t *, mtx_t *mtx_);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
#endif
diff --git a/source/kit/mersenne_twister_64.c b/source/kit/mersenne_twister_64.c
index 28f8b3b..0570a1f 100644
--- a/source/kit/mersenne_twister_64.c
+++ b/source/kit/mersenne_twister_64.c
@@ -1,7 +1,5 @@
#include "mersenne_twister_64.h"
-#include "secure_random.h"
-
#define MM 156
#define MATRIX_A 0xb5026f5aa96619e9ull
#define UM 0xffffffff80000000ull
@@ -60,9 +58,3 @@ uint64_t kit_mt64_generate(kit_mt64_state_t *const state) {
return x;
}
-
-uint64_t kit_mt64_seed() {
- uint64_t seed;
- kit_secure_random(sizeof seed, &seed);
- return seed;
-}
diff --git a/source/kit/mersenne_twister_64.h b/source/kit/mersenne_twister_64.h
index fb509c2..67a4d22 100644
--- a/source/kit/mersenne_twister_64.h
+++ b/source/kit/mersenne_twister_64.h
@@ -24,8 +24,6 @@ void kit_mt64_init(kit_mt64_state_t *state, uint64_t seed);
uint64_t kit_mt64_generate(kit_mt64_state_t *state);
-uint64_t kit_mt64_seed();
-
#ifndef KIT_DISABLE_SHORT_NAMES
# define mt64_state_t kit_mt64_state_t
# define mt64_init_array kit_mt64_init_array
diff --git a/source/kit/mutex.h b/source/kit/mutex.h
index 0b7c548..e5d2e40 100644
--- a/source/kit/mutex.h
+++ b/source/kit/mutex.h
@@ -1,6 +1,48 @@
#ifndef KIT_MUTEX_H
#define KIT_MUTEX_H
-#include "threads.h"
+#ifndef KIT_DISABLE_SYSTEM_THREADS
+# include "time.h"
+
+# if !defined(_WIN32) || defined(__CYGWIN__)
+# include <pthread.h>
+# endif
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if defined(_WIN32) && !defined(__CYGWIN__)
+typedef struct {
+ void *DebugInfo;
+ long LockCount;
+ long RecursionCount;
+ void *OwningThread;
+ void *LockSemaphore;
+ uintptr_t SpinCount;
+} mtx_t;
+# else
+typedef pthread_mutex_t mtx_t;
+# endif
+
+enum {
+ mtx_plain = 0,
+ mtx_recursive = 1,
+ mtx_timed = 2,
+};
+
+void mtx_destroy(mtx_t *mtx_);
+int mtx_init(mtx_t *mtx_, int);
+int mtx_lock(mtx_t *mtx_);
+int mtx_timedlock(mtx_t *__restrict mtx_,
+ const struct timespec *__restrict);
+int mtx_trylock(mtx_t *mtx_);
+int mtx_unlock(mtx_t *mtx_);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
#endif
diff --git a/source/kit/secure_random.c b/source/kit/secure_random.c
index 8f48c9d..013fd52 100644
--- a/source/kit/secure_random.c
+++ b/source/kit/secure_random.c
@@ -1,8 +1,10 @@
#include "secure_random.h"
+#include "condition_variable.h"
#include "mersenne_twister_64.h"
#include "mutex.h"
#include "time.h"
+#include <assert.h>
#include <stdio.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -28,12 +30,19 @@ static uint64_t get_available_memory() {
}
#ifndef KIT_DISABLE_SYSTEM_THREADS
-static mtx_t kit_secure_random_fallback_mutex;
+static once_flag kit_secure_random_fallback_flag;
+static mtx_t kit_secure_random_fallback_mutex;
+
+static void secure_random_fallback_init() {
+ mtx_init(&kit_secure_random_fallback_mutex, mtx_plain);
+}
#endif
static void secure_random_fallback(ptrdiff_t const size,
void *const data) {
#ifndef KIT_DISABLE_SYSTEM_THREADS
+ call_once(&kit_secure_random_fallback_flag,
+ secure_random_fallback_init);
mtx_lock(&kit_secure_random_fallback_mutex);
#endif
@@ -82,18 +91,6 @@ static void secure_random_fallback(ptrdiff_t const size,
#endif
}
-void kit_secure_random_init() {
-#ifndef KIT_DISABLE_SYSTEM_THREADS
- mtx_init(&kit_secure_random_fallback_mutex, mtx_plain);
-#endif
-}
-
-void kit_secure_random_cleanup() {
-#ifndef KIT_DISABLE_SYSTEM_THREADS
- mtx_destroy(&kit_secure_random_fallback_mutex);
-#endif
-}
-
void kit_secure_random(ptrdiff_t const size, void *const data) {
if (size <= 0)
return;
diff --git a/source/kit/secure_random.h b/source/kit/secure_random.h
index 5b461f9..758478d 100644
--- a/source/kit/secure_random.h
+++ b/source/kit/secure_random.h
@@ -9,14 +9,9 @@
extern "C" {
#endif
-void kit_secure_random_init();
-void kit_secure_random_cleanup();
-
void kit_secure_random(ptrdiff_t size, void *data);
#ifndef KIT_DISABLE_SHORT_NAMES
-# define secure_random_init kit_secure_random_init
-# define secure_random_cleanup kit_secure_random_cleanup
# define secure_random kit_secure_random
#endif
diff --git a/source/kit/thread.h b/source/kit/thread.h
new file mode 100644
index 0000000..f64264e
--- /dev/null
+++ b/source/kit/thread.h
@@ -0,0 +1,92 @@
+#ifndef KIT_THREAD_H
+#define KIT_THREAD_H
+
+#ifndef KIT_DISABLE_SYSTEM_THREADS
+# include "time.h"
+# include <stddef.h>
+
+# if defined(__cplusplus)
+# define _Noreturn [[noreturn]]
+# elif defined(_MSC_VER)
+# define _Noreturn __declspec(noreturn)
+# endif
+
+# if !defined(_WIN32) || defined(__CYGWIN__)
+# include <pthread.h>
+# endif
+
+# ifndef _Thread_local
+# if defined(__cplusplus)
+/* C++11 doesn't need `_Thread_local` keyword or macro */
+# elif !defined(__STDC_NO_THREADS__)
+/* threads are optional in C11, _Thread_local present in this
+ * condition */
+# elif defined(_MSC_VER)
+# define _Thread_local __declspec(thread)
+# elif defined(__GNUC__)
+# define _Thread_local __thread
+# else
+/* Leave _Thread_local undefined so that use of _Thread_local would
+ * not promote to a non-thread-local global variable
+ */
+# endif
+# endif
+
+# if !defined(__cplusplus)
+/*
+ * C11 thread_local() macro
+ * C++11 and above already have thread_local keyword
+ */
+# ifndef thread_local
+# if _MSC_VER
+# define thread_local __declspec(thread)
+# else
+# define thread_local _Thread_local
+# endif
+# endif
+# endif
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+typedef void (*tss_dtor_t)(void *);
+typedef int (*thrd_start_t)(void *);
+
+# if defined(_WIN32) && !defined(__CYGWIN__)
+typedef struct {
+ void *handle;
+} thrd_t;
+typedef unsigned long tss_t;
+# else
+typedef pthread_t thrd_t;
+typedef pthread_key_t tss_t;
+# endif
+
+enum {
+ thrd_success = 0,
+ thrd_timedout,
+ thrd_error,
+ thrd_busy,
+ thrd_nomem,
+ thrd_wrong_stack_size
+};
+
+int thrd_create(thrd_t *, thrd_start_t, void *);
+int thrd_create_with_stack(thrd_t *, thrd_start_t, void *,
+ ptrdiff_t stack_size);
+thrd_t thrd_current(void);
+int thrd_detach(thrd_t);
+int thrd_equal(thrd_t, thrd_t);
+_Noreturn void thrd_exit(int);
+int thrd_join(thrd_t, int *);
+int thrd_sleep(const struct timespec *, struct timespec *);
+void thrd_yield(void);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+#endif
diff --git a/source/kit/threads.posix.c b/source/kit/thread.posix.c
index efedbaa..442d7f8 100644
--- a/source/kit/threads.posix.c
+++ b/source/kit/thread.posix.c
@@ -1,34 +1,3 @@
-/*
- * C11 <threads.h> emulation library
- *
- * (C) Copyright yohhoy 2012.
- * Distributed under the Boost Software License, Version 1.0.
- *
- * Permission is hereby granted, free of charge, to any person or
- * organization obtaining a copy of the software and accompanying
- * documentation covered by this license (the "Software") to use,
- * reproduce, display, distribute, execute, and transmit the Software,
- * and to prepare [[derivative work]]s of the Software, and to permit
- * third-parties to whom the Software is furnished to do so, all
- * subject to the following:
- *
- * The copyright notices in the Software and this entire statement,
- * including the above license grant, this restriction and the
- * following disclaimer, must be included in all copies of the
- * Software, in whole or in part, and all derivative works of the
- * Software, unless such copies or derivative works are solely in the
- * form of machine-executable object code generated by a source
- * language processor.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE
- * DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER
- * LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
#ifndef KIT_DISABLE_SYSTEM_THREADS
# if !defined(_WIN32) || defined(__CYGWIN__)
@@ -36,12 +5,14 @@
# include <errno.h>
# include <limits.h>
# include <sched.h>
-# include <stdint.h> /* for intptr_t */
+# include <stdint.h> /* intptr_t */
# include <stdlib.h>
# include <unistd.h>
# include "allocator.h"
-# include "threads.h"
+# include "condition_variable.h"
+# include "mutex.h"
+# include "thread.h"
/*
Configuration macro:
@@ -55,8 +26,6 @@ Configuration macro:
# define EMULATED_THREADS_USE_NATIVE_TIMEDLOCK
# endif
-/*---------------------------- types ----------------------------*/
-
/*
Implementation limits:
- Conditionally emulation for "mutex with timeout"
@@ -74,40 +43,32 @@ static void *impl_thrd_routine(void *p) {
return (void *) (intptr_t) pack.func(pack.arg);
}
-/*--------------- 7.25.2 Initialization functions ---------------*/
-// 7.25.2.1
void call_once(once_flag *flag, void (*func)(void)) {
pthread_once(flag, func);
}
-/*------------- 7.25.3 Condition variable functions -------------*/
-// 7.25.3.1
int cnd_broadcast(cnd_t *cond) {
assert(cond != NULL);
return (pthread_cond_broadcast(cond) == 0) ? thrd_success
: thrd_error;
}
-// 7.25.3.2
void cnd_destroy(cnd_t *cond) {
assert(cond);
pthread_cond_destroy(cond);
}
-// 7.25.3.3
int cnd_init(cnd_t *cond) {
assert(cond != NULL);
return (pthread_cond_init(cond, NULL) == 0) ? thrd_success
: thrd_error;
}
-// 7.25.3.4
int cnd_signal(cnd_t *cond) {
assert(cond != NULL);
return (pthread_cond_signal(cond) == 0) ? thrd_success : thrd_error;
}
-// 7.25.3.5
int cnd_timedwait(cnd_t *cond, mtx_t *mtx,
const struct timespec *abs_time) {
int rt;
@@ -122,7 +83,6 @@ int cnd_timedwait(cnd_t *cond, mtx_t *mtx,
return (rt == 0) ? thrd_success : thrd_error;
}
-// 7.25.3.6
int cnd_wait(cnd_t *cond, mtx_t *mtx) {
assert(mtx != NULL);
assert(cond != NULL);
@@ -130,8 +90,6 @@ int cnd_wait(cnd_t *cond, mtx_t *mtx) {
: thrd_error;
}
-/*-------------------- 7.25.4 Mutex functions --------------------*/
-// 7.25.4.1
void mtx_destroy(mtx_t *mtx) {
assert(mtx != NULL);
pthread_mutex_destroy(mtx);
@@ -163,7 +121,6 @@ __attribute__((weak)) int pthread_mutexattr_destroy(
pthread_mutexattr_t *attr);
# endif
-// 7.25.4.2
int mtx_init(mtx_t *mtx, int type) {
pthread_mutexattr_t attr;
assert(mtx != NULL);
@@ -184,13 +141,11 @@ int mtx_init(mtx_t *mtx, int type) {
return thrd_success;
}
-// 7.25.4.3
int mtx_lock(mtx_t *mtx) {
assert(mtx != NULL);
return (pthread_mutex_lock(mtx) == 0) ? thrd_success : thrd_error;
}
-// 7.25.4.4
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) {
assert(mtx != NULL);
assert(ts != NULL);
@@ -217,20 +172,16 @@ int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) {
}
}
-// 7.25.4.5
int mtx_trylock(mtx_t *mtx) {
assert(mtx != NULL);
return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy;
}
-// 7.25.4.6
int mtx_unlock(mtx_t *mtx) {
assert(mtx != NULL);
return (pthread_mutex_unlock(mtx) == 0) ? thrd_success : thrd_error;
}
-/*------------------- 7.25.5 Thread functions -------------------*/
-// 7.25.5.1
int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg,
ptrdiff_t const require_stack_size) {
impl_thrd_param_t *pack;
@@ -253,7 +204,7 @@ int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg,
}
kit_allocator_t alloc = kit_alloc_default();
pack = (impl_thrd_param_t *) alloc.allocate(
- alloc.state, sizeof(impl_thrd_param_t));
+ alloc.state, sizeof(impl_thrd_param_t));
if (!pack) {
if (attr_p)
pthread_attr_destroy(attr_p);
@@ -276,27 +227,22 @@ int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg,
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) {
return thrd_create_with_stack(thr, func, arg, 0);
}
-// 7.25.5.2
thrd_t thrd_current(void) {
return pthread_self();
}
-// 7.25.5.3
int thrd_detach(thrd_t thr) {
return (pthread_detach(thr) == 0) ? thrd_success : thrd_error;
}
-// 7.25.5.4
int thrd_equal(thrd_t thr0, thrd_t thr1) {
return pthread_equal(thr0, thr1);
}
-// 7.25.5.5
_Noreturn void thrd_exit(int res) {
pthread_exit((void *) (intptr_t) res);
}
-// 7.25.5.6
int thrd_join(thrd_t thr, int *res) {
void *code;
if (pthread_join(thr, &code) != 0)
@@ -306,14 +252,12 @@ int thrd_join(thrd_t thr, int *res) {
return thrd_success;
}
-// 7.25.5.7
int thrd_sleep(const struct timespec *time_point,
struct timespec *remaining) {
assert(time_point != NULL);
return nanosleep(time_point, remaining);
}
-// 7.25.5.8
void thrd_yield(void) {
sched_yield();
}
diff --git a/source/kit/threads.win32.c b/source/kit/thread.win32.c
index 534b01c..7e1dda8 100644
--- a/source/kit/threads.win32.c
+++ b/source/kit/thread.win32.c
@@ -1,45 +1,16 @@
-/*
- * C11 <threads.h> emulation library
- *
- * (C) Copyright yohhoy 2012.
- * Distributed under the Boost Software License, Version 1.0.
- *
- * Permission is hereby granted, free of charge, to any person or
- * organization obtaining a copy of the software and accompanying
- * documentation covered by this license (the "Software") to use,
- * reproduce, display, distribute, execute, and transmit the Software,
- * and to prepare [[derivative work]]s of the Software, and to permit
- * third-parties to whom the Software is furnished to do so, all
- * subject to the following:
- *
- * The copyright notices in the Software and this entire statement,
- * including the above license grant, this restriction and the
- * following disclaimer, must be included in all copies of the
- * Software, in whole or in part, and all derivative works of the
- * Software, unless such copies or derivative works are solely in the
- * form of machine-executable object code generated by a source
- * language processor.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE
- * DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER
- * LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
#ifndef KIT_DISABLE_SYSTEM_THREADS
# if defined(_WIN32) && !defined(__CYGWIN__)
# include <assert.h>
# include <errno.h>
# include <limits.h>
-# include <process.h> // MSVCRT
+# include <process.h>
# include <stdbool.h>
# include <stdlib.h>
# include "allocator.h"
+# include "condition_variable.h"
+# include "mutex.h"
# include "threads.h"
# ifndef WIN32_LEAN_AND_MEAN
@@ -60,15 +31,15 @@ Configuration macro:
*/
# if _WIN32_WINNT >= 0x0600
-// Prefer native WindowsAPI on newer environment.
+/* Prefer native WindowsAPI on newer environment. */
# if !defined(__MINGW32__)
# define EMULATED_THREADS_USE_NATIVE_CALL_ONCE
# endif
# endif
# define EMULATED_THREADS_TSS_DTOR_SLOTNUM \
- 64 // see TLS_MINIMUM_AVAILABLE
+ 64 /* see TLS_MINIMUM_AVAILABLE */
-// check configuration
+/* check configuration */
# if defined(EMULATED_THREADS_USE_NATIVE_CALL_ONCE) && \
(_WIN32_WINNT < 0x0600)
# error EMULATED_THREADS_USE_NATIVE_CALL_ONCE requires _WIN32_WINNT>=0x0600
@@ -136,6 +107,7 @@ static DWORD impl_abs2relmsec(const struct timespec *abs_time) {
struct impl_call_once_param {
void (*func)(void);
};
+
static BOOL CALLBACK impl_call_once_callback(PINIT_ONCE InitOnce,
PVOID Parameter,
PVOID *Context) {
@@ -143,10 +115,10 @@ static BOOL CALLBACK impl_call_once_callback(PINIT_ONCE InitOnce,
Parameter;
(param->func)();
((void) InitOnce);
- ((void) Context); // suppress warning
+ ((void) Context); /* suppress warning */
return TRUE;
}
-# endif // ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE
+# endif /* ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE */
static struct impl_tss_dtor_entry {
tss_t key;
@@ -177,8 +149,6 @@ static void impl_tss_dtor_invoke(void) {
}
}
-/*--------------- 7.25.2 Initialization functions ---------------*/
-// 7.25.2.1
void call_once(once_flag *flag, void (*func)(void)) {
assert(flag && func);
# ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE
@@ -204,36 +174,30 @@ void call_once(once_flag *flag, void (*func)(void)) {
# endif
}
-/*------------- 7.25.3 Condition variable functions -------------*/
-// 7.25.3.1
int cnd_broadcast(cnd_t *cond) {
assert(cond != NULL);
WakeAllConditionVariable((PCONDITION_VARIABLE) cond);
return thrd_success;
}
-// 7.25.3.2
void cnd_destroy(cnd_t *cond) {
- (void) cond;
assert(cond != NULL);
- // do nothing
+ /* do nothing */
+ (void) cond;
}
-// 7.25.3.3
int cnd_init(cnd_t *cond) {
assert(cond != NULL);
InitializeConditionVariable((PCONDITION_VARIABLE) cond);
return thrd_success;
}
-// 7.25.3.4
int cnd_signal(cnd_t *cond) {
assert(cond != NULL);
WakeConditionVariable((PCONDITION_VARIABLE) cond);
return thrd_success;
}
-// 7.25.3.5
int cnd_timedwait(cnd_t *cond, mtx_t *mtx,
const struct timespec *abs_time) {
assert(cond != NULL);
@@ -247,7 +211,6 @@ int cnd_timedwait(cnd_t *cond, mtx_t *mtx,
: thrd_error;
}
-// 7.25.3.6
int cnd_wait(cnd_t *cond, mtx_t *mtx) {
assert(cond != NULL);
assert(mtx != NULL);
@@ -256,14 +219,11 @@ int cnd_wait(cnd_t *cond, mtx_t *mtx) {
return thrd_success;
}
-/*-------------------- 7.25.4 Mutex functions --------------------*/
-// 7.25.4.1
void mtx_destroy(mtx_t *mtx) {
assert(mtx);
DeleteCriticalSection((PCRITICAL_SECTION) mtx);
}
-// 7.25.4.2
int mtx_init(mtx_t *mtx, int type) {
assert(mtx != NULL);
if (type != mtx_plain && type != mtx_timed &&
@@ -274,27 +234,24 @@ int mtx_init(mtx_t *mtx, int type) {
return thrd_success;
}
-// 7.25.4.3
int mtx_lock(mtx_t *mtx) {
assert(mtx != NULL);
EnterCriticalSection((PCRITICAL_SECTION) mtx);
return thrd_success;
}
-// 7.25.4.4
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) {
assert(mtx != NULL);
assert(ts != NULL);
while (mtx_trylock(mtx) != thrd_success) {
if (impl_abs2relmsec(ts) == 0)
return thrd_timedout;
- // busy loop!
+ /* busy loop! */
thrd_yield();
}
return thrd_success;
}
-// 7.25.4.5
int mtx_trylock(mtx_t *mtx) {
assert(mtx != NULL);
return TryEnterCriticalSection((PCRITICAL_SECTION) mtx)
@@ -302,15 +259,12 @@ int mtx_trylock(mtx_t *mtx) {
: thrd_busy;
}
-// 7.25.4.6
int mtx_unlock(mtx_t *mtx) {
assert(mtx != NULL);
LeaveCriticalSection((PCRITICAL_SECTION) mtx);
return thrd_success;
}
-/*------------------- 7.25.5 Thread functions -------------------*/
-// 7.25.5.1
int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg,
ptrdiff_t const stack_size) {
impl_thrd_param_t *pack;
@@ -319,7 +273,7 @@ int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg,
assert(stack_size >= 0 && stack_size < 0x100000000);
kit_allocator_t alloc = kit_alloc_default();
pack = (impl_thrd_param_t *) alloc.allocate(
- alloc.state, (sizeof(impl_thrd_param_t)));
+ alloc.state, (sizeof(impl_thrd_param_t)));
if (!pack)
return thrd_nomem;
pack->func = func;
@@ -344,7 +298,6 @@ int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) {
return thrd_create_with_stack(thr, func, arg, 0);
}
-// 7.25.5.2
thrd_t thrd_current(void) {
/* GetCurrentThread() returns a pseudo-handle, which we need
* to pass to DuplicateHandle(). Only the resulting handle can be
@@ -378,23 +331,19 @@ thrd_t thrd_current(void) {
return state->thrd;
}
-// 7.25.5.3
int thrd_detach(thrd_t thr) {
CloseHandle(thr.handle);
return thrd_success;
}
-// 7.25.5.4
int thrd_equal(thrd_t thr0, thrd_t thr1) {
return GetThreadId(thr0.handle) == GetThreadId(thr1.handle);
}
-// 7.25.5.5
_Noreturn void thrd_exit(int res) {
_endthreadex((unsigned) res);
}
-// 7.25.5.6
int thrd_join(thrd_t thr, int *res) {
DWORD w, code;
if (thr.handle == NULL) {
@@ -414,7 +363,6 @@ int thrd_join(thrd_t thr, int *res) {
return thrd_success;
}
-// 7.25.5.7
int thrd_sleep(const struct timespec *time_point,
struct timespec *remaining) {
(void) remaining;
@@ -424,10 +372,9 @@ int thrd_sleep(const struct timespec *time_point,
return 0;
}
-// 7.25.5.8
void thrd_yield(void) {
SwitchToThread();
}
# endif
-#endif /* KIT_DISABLE_SYSTEM_THREADS */
+#endif
diff --git a/source/kit/threads.h b/source/kit/threads.h
deleted file mode 100644
index 5cfb5d3..0000000
--- a/source/kit/threads.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * C11 <threads.h> emulation library
- *
- * (C) Copyright yohhoy 2012.
- * Copyright 2022 Yonggang Luo
- * Distributed under the Boost Software License, Version 1.0.
- *
- * Permission is hereby granted, free of charge, to any person or
- * organization obtaining a copy of the software and accompanying
- * documentation covered by this license (the "Software") to use,
- * reproduce, display, distribute, execute, and transmit the Software,
- * and to prepare [[derivative work]]s of the Software, and to permit
- * third-parties to whom the Software is furnished to do so, all
- * subject to the following:
- *
- * The copyright notices in the Software and this entire statement,
- * including the above license grant, this restriction and the
- * following disclaimer, must be included in all copies of the
- * Software, in whole or in part, and all derivative works of the
- * Software, unless such copies or derivative works are solely in the
- * form of machine-executable object code generated by a source
- * language processor.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE
- * DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER
- * LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef KIT_THREADS_H
-#define KIT_THREADS_H
-
-#ifndef KIT_DISABLE_SYSTEM_THREADS
-# include "time.h"
-
-# include <errno.h>
-# include <limits.h>
-# include <stddef.h>
-# include <stdlib.h>
-
-# ifdef _MSC_VER
-# define _Noreturn __declspec(noreturn)
-# endif
-
-# if defined(_WIN32) && !defined(__CYGWIN__)
-# include <io.h> /* close */
-# include <process.h> /* _exit */
-# else
-# include <pthread.h>
-# include <unistd.h> /* close, _exit */
-# endif
-
-/*---------------------------- macros ---------------------------*/
-
-# ifndef _Thread_local
-# if defined(__cplusplus)
-/* C++11 doesn't need `_Thread_local` keyword or macro */
-# elif !defined(__STDC_NO_THREADS__)
-/* threads are optional in C11, _Thread_local present in this
- * condition */
-# elif defined(_MSC_VER)
-# define _Thread_local __declspec(thread)
-# elif defined(__GNUC__)
-# define _Thread_local __thread
-# else
-/* Leave _Thread_local undefined so that use of _Thread_local would
- * not promote to a non-thread-local global variable
- */
-# endif
-# endif
-
-# if !defined(__cplusplus)
-/*
- * C11 thread_local() macro
- * C++11 and above already have thread_local keyword
- */
-# ifndef thread_local
-# if _MSC_VER
-# define thread_local __declspec(thread)
-# else
-# define thread_local _Thread_local
-# endif
-# endif
-# endif
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-/*---------------------------- types ----------------------------*/
-typedef void (*tss_dtor_t)(void *);
-typedef int (*thrd_start_t)(void *);
-
-# if defined(_WIN32) && !defined(__CYGWIN__)
-typedef struct {
- void *Ptr;
-} cnd_t;
-/* Define thrd_t as struct type intentionally for avoid use of thrd_t
- * as pointer type */
-typedef struct {
- void *handle;
-} thrd_t;
-typedef unsigned long tss_t;
-typedef struct {
- void *DebugInfo;
- long LockCount;
- long RecursionCount;
- void *OwningThread;
- void *LockSemaphore;
- uintptr_t SpinCount;
-} mtx_t; /* Mock of CRITICAL_SECTION */
-typedef struct {
- volatile uintptr_t status;
-} once_flag;
-// FIXME: temporary non-standard hack to ease transition
-# define KIT_MTX_INITIALIZER_NP_ \
- { (void *) -1, -1, 0, 0, 0, 0 }
-# define ONCE_FLAG_INIT \
- { 0 }
-# define TSS_DTOR_ITERATIONS 1
-# else
-typedef pthread_cond_t cnd_t;
-typedef pthread_t thrd_t;
-typedef pthread_key_t tss_t;
-typedef pthread_mutex_t mtx_t;
-typedef pthread_once_t once_flag;
-// FIXME: temporary non-standard hack to ease transition
-# define KIT_MTX_INITIALIZER_NP_ PTHREAD_MUTEX_INITIALIZER
-# define ONCE_FLAG_INIT PTHREAD_ONCE_INIT
-# ifdef PTHREAD_DESTRUCTOR_ITERATIONS
-# define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS
-# else
-# define TSS_DTOR_ITERATIONS \
- 1 // assume TSS dtor MAY be called at least once.
-# endif
-# endif
-
-/*-------------------- enumeration constants --------------------*/
-enum {
- mtx_plain = 0,
- mtx_recursive = 1,
- mtx_timed = 2,
-};
-
-enum {
- thrd_success = 0, // succeeded
- thrd_timedout, // timed out
- thrd_error, // failed
- thrd_busy, // resource busy
- thrd_nomem, // out of memory,
- thrd_wrong_stack_size
-};
-
-/*-------------------------- functions --------------------------*/
-
-void call_once(once_flag *, void (*)(void));
-int cnd_broadcast(cnd_t *);
-void cnd_destroy(cnd_t *);
-int cnd_init(cnd_t *);
-int cnd_signal(cnd_t *);
-int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict mtx_,
- const struct timespec *__restrict);
-int cnd_wait(cnd_t *, mtx_t *mtx_);
-void mtx_destroy(mtx_t *mtx_);
-int mtx_init(mtx_t *mtx_, int);
-int mtx_lock(mtx_t *mtx_);
-int mtx_timedlock(mtx_t *__restrict mtx_,
- const struct timespec *__restrict);
-int mtx_trylock(mtx_t *mtx_);
-int mtx_unlock(mtx_t *mtx_);
-int thrd_create(thrd_t *, thrd_start_t, void *);
-int thrd_create_with_stack(thrd_t *, thrd_start_t, void *,
- ptrdiff_t stack_size);
-thrd_t thrd_current(void);
-int thrd_detach(thrd_t);
-int thrd_equal(thrd_t, thrd_t);
-# if defined(__cplusplus)
-[[ noreturn ]]
-# else
-_Noreturn
-# endif
-void thrd_exit(int);
-int thrd_join(thrd_t, int *);
-int thrd_sleep(const struct timespec *, struct timespec *);
-void thrd_yield(void);
-
-# ifdef __cplusplus
-}
-# endif
-
-#endif /* KIT_DISABLE_SYSTEM_THREADS */
-
-#endif /* KIT_THREADS_H */
diff --git a/source/kit/time.c b/source/kit/time.c
index bcb3819..108434f 100644
--- a/source/kit/time.c
+++ b/source/kit/time.c
@@ -1,39 +1,6 @@
-/*
- * C11 <time.h> implementation
- *
- * (C) Copyright yohhoy 2012.
- * Copyright 2022 Yonggang Luo
- * Distributed under the Boost Software License, Version 1.0.
- *
- * Permission is hereby granted, free of charge, to any person or
- * organization obtaining a copy of the software and accompanying
- * documentation covered by this license (the "Software") to use,
- * reproduce, display, distribute, execute, and transmit the Software,
- * and to prepare [[derivative work]]s of the Software, and to permit
- * third-parties to whom the Software is furnished to do so, all
- * subject to the following:
- *
- * The copyright notices in the Software and this entire statement,
- * including the above license grant, this restriction and the
- * following disclaimer, must be included in all copies of the
- * Software, in whole or in part, and all derivative works of the
- * Software, unless such copies or derivative works are solely in the
- * form of machine-executable object code generated by a source
- * language processor.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE
- * DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER
- * LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
#include "time.h"
-#ifndef KIT_HAVE_TIMESPEC_GET
+#ifdef KIT_NEED_TIMESPEC_GET
# if defined(_WIN32) && !defined(__CYGWIN__)
@@ -43,11 +10,11 @@
# include <windows.h>
int timespec_get(struct timespec *ts, int base) {
-/* difference between 1970 and 1601 */
+/* difference between 1970 and 1601 */
# define _TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS 116444736000000000ull
-/* 1 tick is 100 nanoseconds */
+/* 1 tick is 100 nanoseconds */
# define _TIMESPEC_IMPL_TICKS_PER_SECONDS 10000000ull
- if (!ts)
+ if (ts == NULL)
return 0;
if (base == TIME_UTC) {
FILETIME ft;
@@ -71,7 +38,7 @@ int timespec_get(struct timespec *ts, int base) {
# else
int timespec_get(struct timespec *ts, int base) {
- if (!ts)
+ if (ts == NULL)
return 0;
if (base == TIME_UTC) {
clock_gettime(CLOCK_REALTIME, ts);
diff --git a/source/kit/time.h b/source/kit/time.h
index 0d995f4..9445912 100644
--- a/source/kit/time.h
+++ b/source/kit/time.h
@@ -1,17 +1,8 @@
-/*
- * Copyright 2022 Yonggang Luo
- * SPDX-License-Identifier: MIT
- *
- * C11 <time.h> emulation library
- */
-
#ifndef KIT_TIME_H
#define KIT_TIME_H
#include <time.h>
-/*---------------------------- macros ---------------------------*/
-
#ifndef TIME_UTC
# define TIME_UTC 1
#endif
@@ -20,43 +11,19 @@
extern "C" {
#endif
-/*---------------------------- types ----------------------------*/
-
-/*
- * On MINGW `struct timespec` present but `timespec_get` may not
- * present; On MSVC `struct timespec` and `timespec_get` present at
- * the same time; So detecting `HAVE_STRUCT_TIMESPEC` in meson script
- * dynamically.
- */
-#ifndef KIT_HAVE_STRUCT_TIMESPEC
+#ifdef KIT_NEED_STRUCT_TIMESPEC
struct timespec {
- time_t tv_sec; // Seconds - >= 0
- long tv_nsec; // Nanoseconds - [0, 999999999]
+ time_t tv_sec; /* Seconds - >= 0 */
+ long tv_nsec; /* Nanoseconds - [0, 999999999] */
};
#endif
-/*-------------------------- functions --------------------------*/
-
-#if !defined(KIT_HAVE_TIMESPEC_GET)
-# define KIT_TIMESPEC_GET_NEED_DECL_
-#elif defined(__APPLE__) && defined(__cplusplus) && \
- (__cplusplus < 201703L)
-/* On macOS, the guard for declaration of timespec_get is by
- * (defined(__cplusplus) && __cplusplus >= 201703L),
- * fix the declaration for C++14 and lower here
- */
-# define KIT_TIMESPEC_GET_NEED_DECL_
-#endif
-
-#ifdef KIT_TIMESPEC_GET_NEED_DECL_
-/*-------------------- 7.25.7 Time functions --------------------*/
-// 7.25.6.1
+#ifdef KIT_NEED_TIMESPEC_GET
int timespec_get(struct timespec *ts, int base);
-# undef KIT_TIMESPEC_GET_NEED_DECL_
#endif
#ifdef __cplusplus
}
#endif
-#endif /* KIT_TIME_H */
+#endif
diff --git a/source/test/unittests/atomic.test.c b/source/test/unittests/atomic.test.c
index c909cb0..b8cf0ac 100644
--- a/source/test/unittests/atomic.test.c
+++ b/source/test/unittests/atomic.test.c
@@ -1,5 +1,5 @@
#include "../../kit/atomic.h"
-#include "../../kit/threads.h"
+#include "../../kit/thread.h"
#define KIT_TEST_FILE atomic
#include "../../kit_test/test.h"
diff --git a/source/test/unittests/condition_variable.test.c b/source/test/unittests/condition_variable.test.c
index c855b0c..c5b0468 100644
--- a/source/test/unittests/condition_variable.test.c
+++ b/source/test/unittests/condition_variable.test.c
@@ -1,4 +1,5 @@
#include "../../kit/condition_variable.h"
+#include "../../kit/thread.h"
#define KIT_TEST_FILE condition_variable
#include "../../kit_test/test.h"
diff --git a/source/test/unittests/mersenne_twister_64.test.c b/source/test/unittests/mersenne_twister_64.test.c
index b986c55..80d1c2c 100644
--- a/source/test/unittests/mersenne_twister_64.test.c
+++ b/source/test/unittests/mersenne_twister_64.test.c
@@ -1,4 +1,5 @@
#include "../../kit/mersenne_twister_64.h"
+#include "../../kit/secure_random.h"
#define KIT_TEST_FILE mersenne_twister_64
#include "../../kit_test/test.h"
@@ -6,7 +7,8 @@
enum { SIZE = 1000 };
TEST("mt64 same seeds") {
- uint64_t seed = mt64_seed();
+ uint64_t seed;
+ secure_random(sizeof seed, &seed);
mt64_state_t foo, bar;
mt64_init(&foo, seed);
diff --git a/source/test/unittests/mutex.test.c b/source/test/unittests/mutex.test.c
index a898557..e597e59 100644
--- a/source/test/unittests/mutex.test.c
+++ b/source/test/unittests/mutex.test.c
@@ -1,4 +1,5 @@
#include "../../kit/mutex.h"
+#include "../../kit/thread.h"
#define KIT_TEST_FILE mutex
#include "../../kit_test/test.h"
diff --git a/source/test/unittests/secure_random.test.c b/source/test/unittests/secure_random.test.c
index eadae65..ec0a7b2 100644
--- a/source/test/unittests/secure_random.test.c
+++ b/source/test/unittests/secure_random.test.c
@@ -8,13 +8,9 @@ TEST("secure random") {
int v[20];
memset(v, 0, sizeof v);
- secure_random_init();
-
secure_random(40, v);
secure_random(40, v + 10);
- secure_random_cleanup();
-
int repeats = 0;
for (int i = 1; i < sizeof v / sizeof *v; i++)
diff --git a/source/test/unittests/thread.test.c b/source/test/unittests/thread.test.c
index 786e992..01198c2 100644
--- a/source/test/unittests/thread.test.c
+++ b/source/test/unittests/thread.test.c
@@ -1,4 +1,4 @@
-#include "../../kit/threads.h"
+#include "../../kit/thread.h"
#define KIT_TEST_FILE thread
#include "../../kit_test/test.h"