From f0f23e874dd19a4fa3e41c8b489aa1f3fbd792c0 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Tue, 12 Sep 2023 03:18:06 +0200 Subject: Refactor; CAS atomics --- TODO | 4 +- build_and_test.sh | 4 +- source/kit/_static.c | 8 +- source/kit/allocator.c | 29 ++- source/kit/allocator.h | 22 +- source/kit/array_ref.c | 27 ++- source/kit/array_ref.h | 30 ++- source/kit/async_function.h | 13 +- source/kit/atomic.h | 304 +++++++++++++++----------- source/kit/atomic.win32.c | 171 +++++++++------ source/kit/bigint.h | 268 +++++++++++------------ source/kit/condition_variable.c | 1 - source/kit/condition_variable.h | 39 ---- source/kit/dynamic_array.c | 18 +- source/kit/dynamic_array.h | 32 ++- source/kit/file.c | 104 ++++----- source/kit/file.h | 25 +-- source/kit/input_buffer.c | 27 ++- source/kit/input_buffer.h | 12 +- source/kit/input_stream.c | 23 +- source/kit/input_stream.h | 3 +- source/kit/lower_bound.h | 10 +- source/kit/mersenne_twister_64.c | 29 +-- source/kit/mersenne_twister_64.h | 21 +- source/kit/move_back.h | 10 +- source/kit/mutex.c | 1 - source/kit/mutex.h | 53 ----- source/kit/secure_random.c | 105 ++------- source/kit/secure_random.h | 9 +- source/kit/sha256.c | 35 +-- source/kit/sha256.h | 11 +- source/kit/sockets.h | 20 +- source/kit/status.h | 4 +- source/kit/string_builder.c | 1 + source/kit/string_builder.h | 13 ++ source/kit/string_ref.h | 19 +- source/kit/thread.h | 89 -------- source/kit/thread.posix.c | 275 ------------------------ source/kit/thread.win32.c | 380 --------------------------------- source/kit/thread_defs.h | 22 -- source/kit/threads.h | 132 ++++++++++++ source/kit/threads.posix.c | 271 +++++++++++++++++++++++ source/kit/threads.win32.c | 376 ++++++++++++++++++++++++++++++++ source/kit/time.h | 2 +- source/kit/types.h | 4 + source/tests/atomic.test.c | 2 +- source/tests/bigint.test.c | 48 ++--- source/tests/condition_variable.test.c | 3 +- source/tests/file.test.c | 26 +-- source/tests/mutex.test.c | 3 +- source/tests/thread.test.c | 2 +- 51 files changed, 1530 insertions(+), 1610 deletions(-) delete mode 100644 source/kit/condition_variable.c delete mode 100644 source/kit/condition_variable.h delete mode 100644 source/kit/mutex.c delete mode 100644 source/kit/mutex.h create mode 100644 source/kit/string_builder.c create mode 100644 source/kit/string_builder.h delete mode 100644 source/kit/thread.h delete mode 100644 source/kit/thread.posix.c delete mode 100644 source/kit/thread.win32.c delete mode 100644 source/kit/thread_defs.h create mode 100644 source/kit/threads.h create mode 100644 source/kit/threads.posix.c create mode 100644 source/kit/threads.win32.c diff --git a/TODO b/TODO index e3a3827..3011831 100644 --- a/TODO +++ b/TODO @@ -16,6 +16,8 @@ To-Do - Win32 (Windows) - Cocoa (macOS) - Emscripten (WebAssembly) -- Sockets tests +- String builder. +- UTF-8. +- Sockets tests. - HTTP 1 client. - Better atomics support. diff --git a/build_and_test.sh b/build_and_test.sh index 63bc27c..157f88a 100644 --- a/build_and_test.sh +++ b/build_and_test.sh @@ -77,9 +77,9 @@ case $(uname | tr '[:upper:]' '[:lower:]') in fi fi if [ "$COMPILE" = "cl.exe" ]; then - LINK_FLAGS="Shlwapi.lib" + LINK_FLAGS="Shlwapi.lib Advapi32.lib" else - LINK_FLAGS="-lShlwapi" + LINK_FLAGS="-lShlwapi -lAdvapi32" fi ;; *) diff --git a/source/kit/_static.c b/source/kit/_static.c index f098ab1..4d820ad 100644 --- a/source/kit/_static.c +++ b/source/kit/_static.c @@ -1,14 +1,12 @@ #include "allocator.c" #include "array_ref.c" -#include "atomic.win32.c" -#include "condition_variable.c" #include "dynamic_array.c" +#include "string_builder.c" #include "file.c" #include "input_buffer.c" #include "input_stream.c" #include "mersenne_twister_64.c" -#include "mutex.c" #include "secure_random.c" #include "sha256.c" -#include "thread.posix.c" -#include "thread.win32.c" +#include "threads.posix.c" +#include "threads.win32.c" diff --git a/source/kit/allocator.c b/source/kit/allocator.c index 149cddb..920da5a 100644 --- a/source/kit/allocator.c +++ b/source/kit/allocator.c @@ -1,16 +1,14 @@ #include "allocator.h" #include -#include +#include #ifndef KIT_DISABLE_SYSTEM_MALLOC # include -# include #endif -static void *kit_allocate_default_(int request, ptrdiff_t size, - ptrdiff_t previous_size, - void *pointer) { +static void *kit_allocate_default_(i32 request, i64 size, + i64 previous_size, void *pointer) { #ifndef KIT_DISABLE_SYSTEM_MALLOC switch (request) { case KIT_ALLOCATE: @@ -43,10 +41,10 @@ static void *kit_allocate_default_(int request, ptrdiff_t size, if (size == previous_size) return pointer; - uint8_t *p = NULL; + u8 *p = NULL; if (size > 0) { - p = (uint8_t *) malloc(size); + p = (u8 *) malloc(size); if (p != NULL) { if (size > 0 && previous_size > 0) @@ -83,9 +81,9 @@ static void *kit_allocate_default_(int request, ptrdiff_t size, } static void *kit_allocate_from_buffer_(kit_allocator_t *alloc, - int request, ptrdiff_t size, - ptrdiff_t previous_size, - void *pointer) { + i32 request, i64 size, + i64 previous_size, + void *pointer) { assert(alloc != NULL); assert(pointer == NULL || pointer < alloc->data); @@ -130,7 +128,7 @@ static void *kit_allocate_from_buffer_(kit_allocator_t *alloc, if (previous_size != 0 && pointer == NULL) return NULL; - if ((uint8_t *) pointer + previous_size == alloc->data) { + if ((u8 *) pointer + previous_size == alloc->data) { if (alloc->size < size - previous_size) return NULL; alloc->bytes += size - previous_size; @@ -141,7 +139,7 @@ static void *kit_allocate_from_buffer_(kit_allocator_t *alloc, if (alloc->size < size) return NULL; - uint8_t *p = alloc->bytes; + u8 *p = alloc->bytes; alloc->bytes += size; alloc->size -= size; @@ -163,9 +161,8 @@ static void *kit_allocate_from_buffer_(kit_allocator_t *alloc, return NULL; } #ifndef KIT_ENABLE_CUSTOM_ALLOC_DISPATCH -void *kit_alloc_dispatch(kit_allocator_t *alloc, int request, - ptrdiff_t size, ptrdiff_t previous_size, - void *pointer) { +void *kit_alloc_dispatch(kit_allocator_t *alloc, i32 request, + i64 size, i64 previous_size, void *pointer) { if (alloc == NULL) return kit_allocate_default_(request, size, previous_size, pointer); @@ -193,7 +190,7 @@ kit_allocator_t kit_alloc_default(void) { return alloc; } -kit_allocator_t kit_alloc_buffer(ptrdiff_t size, void *buffer) { +kit_allocator_t kit_alloc_buffer(i64 size, void *buffer) { kit_allocator_t alloc = { .type = KIT_ALLOC_TYPE_BUFFER, .size = size, .data = buffer }; diff --git a/source/kit/allocator.h b/source/kit/allocator.h index b344d4b..3fcfe9b 100644 --- a/source/kit/allocator.h +++ b/source/kit/allocator.h @@ -1,12 +1,7 @@ #ifndef KIT_ALLOCATOR_H #define KIT_ALLOCATOR_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include -#include +#include "types.h" #ifdef __cplusplus extern "C" { @@ -28,11 +23,11 @@ enum { }; typedef struct { - int type; - ptrdiff_t size; + i32 type; + i64 size; union { - uint8_t *bytes; - void *data; + u8 *bytes; + void *data; }; } kit_allocator_t; @@ -41,13 +36,12 @@ typedef struct { // // See KIT_ENABLE_CUSTOM_ALLOC_DISPATCH macro. // -void *kit_alloc_dispatch(kit_allocator_t *alloc, int request, - ptrdiff_t size, ptrdiff_t previous_size, - void *pointer); +void *kit_alloc_dispatch(kit_allocator_t *alloc, i32 request, + i64 size, i64 previous_size, void *poi32er); kit_allocator_t kit_alloc_default(void); -kit_allocator_t kit_alloc_buffer(ptrdiff_t size, void *buffer); +kit_allocator_t kit_alloc_buffer(i64 size, void *buffer); #ifdef __cplusplus } diff --git a/source/kit/array_ref.c b/source/kit/array_ref.c index 4c1b1a4..a9df2c4 100644 --- a/source/kit/array_ref.c +++ b/source/kit/array_ref.c @@ -2,35 +2,34 @@ #include -int kit_ar_equal_bytes(ptrdiff_t left_element_size, - ptrdiff_t left_size, void *left_data, - ptrdiff_t right_element_size, - ptrdiff_t right_size, void *right_data) { - ptrdiff_t i; +i8 kit_ar_equal_bytes(i64 left_element_size, i64 left_size, + void *left_data, i64 right_element_size, + i64 right_size, void *right_data) { + i64 i; if (left_element_size != right_element_size) return 0; if (left_size != right_size) return 0; for (i = 0; i < left_size; i++) - if (memcmp((char *) left_data + i * left_element_size, - (char *) right_data + i * left_element_size, + if (memcmp((u8 *) left_data + i * left_element_size, + (u8 *) right_data + i * left_element_size, left_element_size) != 0) return 0; return 1; } -int kit_ar_compare(ptrdiff_t left_element_size, ptrdiff_t left_size, - void *left_data, ptrdiff_t right_element_size, - ptrdiff_t right_size, void *right_data, - kit_ar_compare_fn compare) { - ptrdiff_t i; +i8 kit_ar_compare(i64 left_element_size, i64 left_size, + void *left_data, i64 right_element_size, + i64 right_size, void *right_data, + kit_ar_compare_fn compare) { + i64 i; if (left_element_size < right_element_size) return -1; if (left_element_size > right_element_size) return 1; for (i = 0; i < left_size && i < right_size; i++) { - int c = compare((char *) left_data + i * left_element_size, - (char *) right_data + i * left_element_size); + i8 c = compare((u8 *) left_data + i * left_element_size, + (u8 *) right_data + i * left_element_size); if (c != 0) return c; } diff --git a/source/kit/array_ref.h b/source/kit/array_ref.h index 02f7370..20851f9 100644 --- a/source/kit/array_ref.h +++ b/source/kit/array_ref.h @@ -1,38 +1,32 @@ #ifndef KIT_ARRAY_REF_H #define KIT_ARRAY_REF_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include -#include +#include "types.h" #ifdef __cplusplus extern "C" { #endif -typedef int (*kit_ar_compare_fn)(void *left, void *right); +typedef i8 (*kit_ar_compare_fn)(void *left, void *right); -int kit_ar_equal_bytes(ptrdiff_t left_element_size, - ptrdiff_t left_size, void *left_data, - ptrdiff_t right_element_size, - ptrdiff_t right_size, void *right_data); +i8 kit_ar_equal_bytes(i64 left_element_size, i64 left_size, + void *left_data, i64 right_element_size, + i64 right_size, void *right_data); -int kit_ar_compare(ptrdiff_t left_element_size, ptrdiff_t left_size, - void *left_data, ptrdiff_t right_element_size, - ptrdiff_t right_size, void *right_data, - kit_ar_compare_fn compare); +i8 kit_ar_compare(i64 left_element_size, i64 left_size, + void *left_data, i64 right_element_size, + i64 right_size, void *right_data, + kit_ar_compare_fn compare); #define KIT_AR(type_) \ struct { \ - ptrdiff_t size; \ - type_ *values; \ + i64 size; \ + type_ *values; \ } #define KIT_AR_WRAP(name_, element_type_, array_) \ struct { \ - ptrdiff_t size; \ + i64 size; \ element_type_ *values; \ } name_ = { .size = (sizeof(array_) / sizeof((array_)[0])), \ .values = (array_) } diff --git a/source/kit/async_function.h b/source/kit/async_function.h index f7a04e7..2c126ab 100644 --- a/source/kit/async_function.h +++ b/source/kit/async_function.h @@ -1,11 +1,8 @@ #ifndef KIT_ASYNC_FUNCTION_H #define KIT_ASYNC_FUNCTION_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif +#include "types.h" -#include #include #ifdef __cplusplus @@ -19,15 +16,15 @@ extern "C" { #endif typedef struct { - int _; + i32 _; } kit_af_void; typedef void (*kit_af_state_machine)(void *self_void_); #define KIT_AF_STATE_DATA \ struct { \ - int _index; \ - ptrdiff_t _id; \ + i32 _index; \ + i32 _id; \ kit_af_state_machine _state_machine; \ } @@ -185,7 +182,7 @@ static void kit_async_function_dispatch(void *promise) { #define KIT_AF_FINISHED_N(return_, promises_, size_) \ do { \ - int kit_af_index_; \ + i32 kit_af_index_; \ (return_) = 1; \ for (kit_af_index_ = 0; kit_af_index_ < (size_); \ kit_af_index_++) \ diff --git a/source/kit/atomic.h b/source/kit/atomic.h index 4d56def..f10402b 100644 --- a/source/kit/atomic.h +++ b/source/kit/atomic.h @@ -1,11 +1,7 @@ #ifndef KIT_ATOMIC_H #define KIT_ATOMIC_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include +#include "types.h" #ifndef _MSC_VER # include @@ -15,6 +11,7 @@ # include # define KIT_ATOMIC(type_) type_ volatile +# define _Atomic volatile # ifdef __cplusplus extern "C" { @@ -29,134 +26,191 @@ enum { memory_order_seq_cst }; -void kit_atomic_store_explicit_8(uint8_t volatile *var, uint8_t value, - int memory_order); - -void kit_atomic_store_explicit_16(uint16_t volatile *var, - uint16_t value, int memory_order); - -void kit_atomic_store_explicit_32(uint32_t volatile *var, - uint32_t value, int memory_order); - -void kit_atomic_store_explicit_64(uint64_t volatile *var, - uint64_t value, int memory_order); - -uint8_t kit_atomic_load_explicit_8(uint8_t volatile *var, - int memory_order); - -uint16_t kit_atomic_load_explicit_16(uint16_t volatile *var, - int memory_order); - -uint32_t kit_atomic_load_explicit_32(uint32_t volatile *var, - int memory_order); - -uint64_t kit_atomic_load_explicit_64(uint64_t volatile *var, - int memory_order); - -uint8_t kit_atomic_exchange_explicit_8(uint8_t volatile *var, - uint8_t value, - int memory_order); - -uint16_t kit_atomic_exchange_explicit_16(uint16_t volatile *var, - uint16_t value, - int memory_order); - -uint32_t kit_atomic_exchange_explicit_32(uint32_t volatile *var, - uint32_t value, - int memory_order); - -uint64_t kit_atomic_exchange_explicit_64(uint64_t volatile *var, - uint64_t value, - int memory_order); - -uint8_t kit_atomic_fetch_add_explicit_8(uint8_t volatile *var, - uint8_t value, - int memory_order); - -uint16_t kit_atomic_fetch_add_explicit_16(uint16_t volatile *var, - uint16_t value, - int memory_order); - -uint32_t kit_atomic_fetch_add_explicit_32(uint32_t volatile *var, - uint32_t value, - int memory_order); - -uint64_t kit_atomic_fetch_add_explicit_64(uint64_t volatile *var, - uint64_t value, - int memory_order); - -# define atomic_store_explicit(var_, value_, memory_order_) \ - do { \ - assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ - sizeof *(var_) == 4 || sizeof *(var_) == 8); \ - if (sizeof *(var_) == 1) \ - kit_atomic_store_explicit_8((uint8_t volatile *) (var_), \ - (uint8_t) (value_), \ - (memory_order_)); \ - if (sizeof *(var_) == 2) \ - kit_atomic_store_explicit_16((uint16_t volatile *) (var_), \ - (uint16_t) (value_), \ - (memory_order_)); \ - if (sizeof *(var_) == 4) \ - kit_atomic_store_explicit_32((uint32_t volatile *) (var_), \ - (uint32_t) (value_), \ - (memory_order_)); \ - if (sizeof *(var_) == 8) \ - kit_atomic_store_explicit_64((uint64_t volatile *) (var_), \ - (uint64_t) (value_), \ - (memory_order_)); \ +void kit_atomic_store_explicit_8(u8 volatile *var, u8 value, + i32 memory_order); + +void kit_atomic_store_explicit_16(u16 volatile *var, u16 value, + i32 memory_order); + +void kit_atomic_store_explicit_32(u32 volatile *var, u32 value, + i32 memory_order); + +void kit_atomic_store_explicit_64(u64 volatile *var, u64 value, + i32 memory_order); + +u8 kit_atomic_load_explicit_8(u8 volatile *var, i32 memory_order); + +u16 kit_atomic_load_explicit_16(u16 volatile *var, i32 memory_order); + +u32 kit_atomic_load_explicit_32(u32 volatile *var, i32 memory_order); + +u64 kit_atomic_load_explicit_64(u64 volatile *var, i32 memory_order); + +u8 kit_atomic_exchange_explicit_8(u8 volatile *var, u8 value, + i32 memory_order); + +u16 kit_atomic_exchange_explicit_16(u16 volatile *var, u16 value, + i32 memory_order); + +u32 kit_atomic_exchange_explicit_32(u32 volatile *var, u32 value, + i32 memory_order); + +u64 kit_atomic_exchange_explicit_64(u64 volatile *var, u64 value, + i32 memory_order); + +i32 kit_atomic_compare_exchange_explicit_8(u8 volatile *var, + u8 *expected, u8 value, + i32 memory_order_succ_, + i32 memory_order_fail_); + +i32 kit_atomic_compare_exchange_explicit_16(u16 volatile *var, + u16 *expected, u16 value, + i32 memory_order_succ_, + i32 memory_order_fail_); + +i32 kit_atomic_compare_exchange_explicit_32(u32 volatile *var, + u32 *expected, u32 value, + i32 memory_order_succ_, + i32 memory_order_fail_); + +i32 kit_atomic_compare_exchange_explicit_64(u64 volatile *var, + u64 *expected, u64 value, + i32 memory_order_succ_, + i32 memory_order_fail_); + +u8 kit_atomic_fetch_add_explicit_8(u8 volatile *var, u8 value, + i32 memory_order); + +u16 kit_atomic_fetch_add_explicit_16(u16 volatile *var, u16 value, + i32 memory_order); + +u32 kit_atomic_fetch_add_explicit_32(u32 volatile *var, u32 value, + i32 memory_order); + +u64 kit_atomic_fetch_add_explicit_64(u64 volatile *var, u64 value, + i32 memory_order); + +# define atomic_store_explicit(var_, value_, memory_order_) \ + do { \ + assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ + sizeof *(var_) == 4 || sizeof *(var_) == 8); \ + if (sizeof *(var_) == 1) \ + kit_atomic_store_explicit_8((u8 volatile *) (var_), \ + (u8) (value_), (memory_order_)); \ + if (sizeof *(var_) == 2) \ + kit_atomic_store_explicit_16((u16 volatile *) (var_), \ + (u16) (value_), \ + (memory_order_)); \ + if (sizeof *(var_) == 4) \ + kit_atomic_store_explicit_32((u32 volatile *) (var_), \ + (u32) (value_), \ + (memory_order_)); \ + if (sizeof *(var_) == 8) \ + kit_atomic_store_explicit_64((u64 volatile *) (var_), \ + (u64) (value_), \ + (memory_order_)); \ } while (0) -# define atomic_load_explicit(var_, memory_order_) \ - (assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ - sizeof *(var_) == 4 || sizeof *(var_) == 8), \ - (sizeof *(var_) == 1 \ - ? kit_atomic_load_explicit_8((uint8_t volatile *) (var_), \ - (memory_order_)) \ - : sizeof *(var_) == 2 \ - ? kit_atomic_load_explicit_16( \ - (uint16_t volatile *) (var_), (memory_order_)) \ - : sizeof *(var_) == 4 \ - ? kit_atomic_load_explicit_32( \ - (uint32_t volatile *) (var_), (memory_order_)) \ - : kit_atomic_load_explicit_64( \ - (uint64_t volatile *) (var_), (memory_order_)))) +# define atomic_load_explicit(var_, memory_order_) \ + (assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ + sizeof *(var_) == 4 || sizeof *(var_) == 8), \ + (sizeof *(var_) == 1 \ + ? kit_atomic_load_explicit_8((u8 volatile *) (var_), \ + (memory_order_)) \ + : sizeof *(var_) == 2 \ + ? kit_atomic_load_explicit_16((u16 volatile *) (var_), \ + (memory_order_)) \ + : sizeof *(var_) == 4 \ + ? kit_atomic_load_explicit_32((u32 volatile *) (var_), \ + (memory_order_)) \ + : kit_atomic_load_explicit_64((u64 volatile *) (var_), \ + (memory_order_)))) # define atomic_exchange_explicit(var_, value_, memory_order_) \ (assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ sizeof *(var_) == 4 || sizeof *(var_) == 8), \ (sizeof *(var_) == 1 ? kit_atomic_exchange_explicit_8( \ - (uint8_t volatile *) (var_), \ - (uint8_t) (value_), (memory_order_)) \ - : sizeof *(var_) == 2 \ - ? kit_atomic_exchange_explicit_16( \ - (uint16_t volatile *) (var_), (uint16_t) (value_), \ - (memory_order_)) \ - : sizeof *(var_) == 4 \ - ? kit_atomic_exchange_explicit_32( \ - (uint32_t volatile *) (var_), (uint32_t) (value_), \ - (memory_order_)) \ - : kit_atomic_exchange_explicit_64( \ - (uint64_t volatile *) (var_), (uint64_t) (value_), \ - (memory_order_)))) - -# define atomic_fetch_add_explicit(var_, value_, memory_order_) \ - (assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ - sizeof *(var_) == 4 || sizeof *(var_) == 8), \ - (sizeof *(var_) == 1 ? kit_atomic_fetch_add_explicit_8( \ - (uint8_t volatile *) (var_), \ - (uint8_t) (value_), (memory_order_)) \ - : sizeof *(var_) == 2 \ - ? kit_atomic_fetch_add_explicit_16( \ - (uint16_t volatile *) (var_), (uint16_t) (value_), \ - (memory_order_)) \ + (u8 volatile *) (var_), \ + (u8) (value_), (memory_order_)) \ + : sizeof *(var_) == 2 ? kit_atomic_exchange_explicit_16( \ + (u16 volatile *) (var_), \ + (u16) (value_), (memory_order_)) \ : sizeof *(var_) == 4 \ - ? kit_atomic_fetch_add_explicit_32( \ - (uint32_t volatile *) (var_), (uint32_t) (value_), \ - (memory_order_)) \ - : kit_atomic_fetch_add_explicit_64( \ - (uint64_t volatile *) (var_), (uint64_t) (value_), \ - (memory_order_)))) + ? kit_atomic_exchange_explicit_32((u32 volatile *) (var_), \ + (u32) (value_), \ + (memory_order_)) \ + : kit_atomic_exchange_explicit_64((u64 volatile *) (var_), \ + (u64) (value_), \ + (memory_order_)))) + +# define atomic_compare_exchange_strong_explicit( \ + var_, expected_, value_, memory_order_succ_, \ + memory_order_fail_) \ + (assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ + sizeof *(var_) == 4 || sizeof *(var_) == 8), \ + (sizeof *(var_) == 1 \ + ? kit_atomic_compare_exchange_explicit_8( \ + (u8 volatile *) (var_), (u8 *) (expected_), \ + (u8) (value_), (memory_order_succ_), \ + (memory_order_fail_)) \ + : sizeof *(var_) == 2 \ + ? kit_atomic_compare_exchange_explicit_16( \ + (u16 volatile *) (var_), (u16 *) (expected_), \ + (u16) (value_), (memory_order_succ_), \ + (memory_order_fail_)) \ + : sizeof *(var_) == 4 \ + ? kit_atomic_compare_exchange_explicit_32( \ + (u32 volatile *) (var_), (u32 *) (expected_), \ + (u32) (value_), (memory_order_succ_), \ + (memory_order_fail_)) \ + : kit_atomic_compare_exchange_explicit_64( \ + (u64 volatile *) (var_), (u64 *) (expected_), \ + (u64) (value_), (memory_order_succ_), \ + (memory_order_fail_)))) + +# define atomic_compare_exchange_weak_explicit( \ + var_, expected_, value_, memory_order_succ_, \ + memory_order_fail_) \ + atomic_compare_exchange_strong_explicit(var_, expected_, value_, \ + memory_order_succ_, \ + memory_order_fail_) + +# define atomic_fetch_add_explicit(var_, value_, memory_order_) \ + (assert(sizeof *(var_) == 1 || sizeof *(var_) == 2 || \ + sizeof *(var_) == 4 || sizeof *(var_) == 8), \ + (sizeof *(var_) == 1 ? kit_atomic_fetch_add_explicit_8( \ + (u8 volatile *) (var_), \ + (u8) (value_), (memory_order_)) \ + : sizeof *(var_) == 2 ? kit_atomic_fetch_add_explicit_16( \ + (u16 volatile *) (var_), \ + (u16) (value_), (memory_order_)) \ + : sizeof *(var_) == 4 ? kit_atomic_fetch_add_explicit_32( \ + (u32 volatile *) (var_), \ + (u32) (value_), (memory_order_)) \ + : kit_atomic_fetch_add_explicit_64( \ + (u64 volatile *) (var_), \ + (u64) (value_), (memory_order_)))) + +# define atomic_store(var_, value_) \ + atomic_store(var_, value_, memory_order_seq_cst) + +# define atomic_load(var_) atomic_load(var_, memory_order_seq_cst) + +# define atomic_exchange(var_, value_) \ + atomic_exchange(var_, value_, memory_order_seq_cst) + +# define atomic_compare_exchange_strong(var_, expected_, value_) \ + atomic_compare_exchange_strong_explicit(var_, expected_, value_, \ + memory_order_seq_cst, \ + memory_order_seq_cst) + +# define atomic_compare_exchange_weak(var_, expected_, value_) \ + atomic_compare_exchange_weak_explicit(var_, expected_, value_, \ + memory_order_seq_cst, \ + memory_order_seq_cst) + +# define atomic_fetch_add(var_, value_) \ + atomic_fetch_add(var_, value_, memory_order_seq_cst) #endif #ifndef KIT_DISABLE_SHORT_NAMES diff --git a/source/kit/atomic.win32.c b/source/kit/atomic.win32.c index 31f4e33..791f8fe 100644 --- a/source/kit/atomic.win32.c +++ b/source/kit/atomic.win32.c @@ -7,8 +7,8 @@ static_assert(sizeof(int) == 4, "Wrong int size"); # include -void kit_atomic_store_explicit_8(uint8_t volatile *var, uint8_t value, - int memory_order) { +void kit_atomic_store_explicit_8(u8 volatile *var, u8 value, + i32 memory_order) { char volatile *dst = (char volatile *) var; char src = (char) value; @@ -18,8 +18,8 @@ void kit_atomic_store_explicit_8(uint8_t volatile *var, uint8_t value, } } -void kit_atomic_store_explicit_16(uint16_t volatile *var, - uint16_t value, int memory_order) { +void kit_atomic_store_explicit_16(u16 volatile *var, u16 value, + i32 memory_order) { short volatile *dst = (short volatile *) var; short src = (short) value; @@ -29,8 +29,8 @@ void kit_atomic_store_explicit_16(uint16_t volatile *var, } } -void kit_atomic_store_explicit_32(uint32_t volatile *var, - uint32_t value, int memory_order) { +void kit_atomic_store_explicit_32(u32 volatile *var, u32 value, + i32 memory_order) { int volatile *dst = (int volatile *) var; int src = (int) value; @@ -40,8 +40,8 @@ void kit_atomic_store_explicit_32(uint32_t volatile *var, } } -void kit_atomic_store_explicit_64(uint64_t volatile *var, - uint64_t value, int memory_order) { +void kit_atomic_store_explicit_64(u64 volatile *var, u64 value, + i32 memory_order) { __int64 volatile *dst = (__int64 volatile *) var; __int64 src = (__int64) value; @@ -51,134 +51,183 @@ void kit_atomic_store_explicit_64(uint64_t volatile *var, # ifdef _WIN64 _InterlockedExchange64(dst, src); # else + assert(0); _InterlockedExchange((int volatile *) dst, (int) src); # endif } } -uint8_t kit_atomic_load_explicit_8(volatile uint8_t *var, - int memory_order) { +u8 kit_atomic_load_explicit_8(volatile u8 *var, i32 memory_order) { char volatile *dst = (char volatile *) var; if (memory_order == memory_order_relaxed) - return (uint8_t) *dst; + return (u8) *dst; - return (uint8_t) _InterlockedOr8(dst, 0); + return (u8) _InterlockedOr8(dst, 0); } -uint16_t kit_atomic_load_explicit_16(uint16_t volatile *var, - int memory_order) { +u16 kit_atomic_load_explicit_16(u16 volatile *var, i32 memory_order) { short volatile *dst = (short volatile *) var; if (memory_order == memory_order_relaxed) - return (uint16_t) *dst; + return (u16) *dst; - return (uint16_t) _InterlockedOr16(dst, 0); + return (u16) _InterlockedOr16(dst, 0); } -uint32_t kit_atomic_load_explicit_32(uint32_t volatile *var, - int memory_order) { +u32 kit_atomic_load_explicit_32(u32 volatile *var, i32 memory_order) { int volatile *dst = (int volatile *) var; if (memory_order == memory_order_relaxed) - return (uint32_t) *dst; + return (u32) *dst; - return (uint32_t) _InterlockedOr(dst, 0); + return (u32) _InterlockedOr(dst, 0); } -uint64_t kit_atomic_load_explicit_64(uint64_t volatile *var, - int memory_order) { +u64 kit_atomic_load_explicit_64(u64 volatile *var, i32 memory_order) { __int64 volatile *dst = (__int64 volatile *) var; if (memory_order == memory_order_relaxed) - return (uint64_t) *dst; + return (u64) *dst; # ifdef _WIN64 - return (uint64_t) _InterlockedOr64(dst, 0); + return (u64) _InterlockedOr64(dst, 0); # else - return (uint64_t) _InterlockedOr((int volatile *) dst, 0); + assert(0); + return (u64) _InterlockedOr((int volatile *) dst, 0); # endif } -uint8_t kit_atomic_exchange_explicit_8(volatile uint8_t *var, - uint8_t value, - int memory_order) { +u8 kit_atomic_exchange_explicit_8(volatile u8 *var, u8 value, + i32 memory_order) { char volatile *dst = (char volatile *) var; char src = (char) value; - return (uint8_t) _InterlockedExchange8(dst, src); + return (u8) _InterlockedExchange8(dst, src); } -uint16_t kit_atomic_exchange_explicit_16(uint16_t volatile *var, - uint16_t value, - int memory_order) { +u16 kit_atomic_exchange_explicit_16(u16 volatile *var, u16 value, + i32 memory_order) { short volatile *dst = (short volatile *) var; short src = (short) value; - return (uint16_t) _InterlockedExchange16(dst, src); + return (u16) _InterlockedExchange16(dst, src); } -uint32_t kit_atomic_exchange_explicit_32(uint32_t volatile *var, - uint32_t value, - int memory_order) { +u32 kit_atomic_exchange_explicit_32(u32 volatile *var, u32 value, + i32 memory_order) { int volatile *dst = (int volatile *) var; int src = (int) value; - return (uint32_t) _InterlockedExchange(dst, src); + return (u32) _InterlockedExchange(dst, src); } -uint64_t kit_atomic_exchange_explicit_64(uint64_t volatile *var, - uint64_t value, - int memory_order) { +u64 kit_atomic_exchange_explicit_64(u64 volatile *var, u64 value, + i32 memory_order) { __int64 volatile *dst = (__int64 volatile *) var; __int64 src = (__int64) value; # ifdef _WIN64 - return (uint64_t) _InterlockedExchange64(dst, src); + return (u64) _InterlockedExchange64(dst, src); # else - return (uint64_t) _InterlockedExchange((int volatile *) dst, - (int) src); + assert(0); + return (u64) _InterlockedExchange((int volatile *) dst, (int) src); # endif } -uint8_t kit_atomic_fetch_add_explicit_8(volatile uint8_t *var, - uint8_t value, - int memory_order) { +int kit_atomic_compare_exchange_explicit_8(volatile u8 *var, + u8 *expected, u8 value, + i32 memory_order_succ_, + i32 memory_order_fail_) { char volatile *dst = (char volatile *) var; char src = (char) value; + char exp = (char) *expected; - return (uint8_t) _InterlockedExchangeAdd8(dst, src); + *expected = (u8) _InterlockedCompareExchange8(dst, src, exp); + + return exp == (char) *expected; +} + +int kit_atomic_compare_exchange_explicit_16(u16 volatile *var, + u16 *expected, u16 value, + i32 memory_order_succ_, + i32 memory_order_fail_) { + short volatile *dst = (short volatile *) var; + short src = (short) value; + short exp = (short) *expected; + + *expected = (u16) _InterlockedCompareExchange16(dst, src, exp); + + return exp == (short) *expected; +} + +int kit_atomic_compare_exchange_explicit_32(u32 volatile *var, + u32 *expected, u32 value, + i32 memory_order_succ_, + i32 memory_order_fail_) { + int volatile *dst = (int volatile *) var; + int src = (int) value; + int exp = (int) *expected; + + *expected = (u32) _InterlockedCompareExchange(dst, src, exp); + + return exp == (int) *expected; +} + +int kit_atomic_compare_exchange_explicit_64(u64 volatile *var, + u64 *expected, u64 value, + i32 memory_order_succ_, + i32 memory_order_fail_) { + __int64 volatile *dst = (__int64 volatile *) var; + __int64 src = (__int64) value; + __int64 exp = (__int64) *expected; + +# ifdef _WIN64 + *expected = (u64) _InterlockedCompareExchange64(dst, src, exp); +# else + assert(0); + *expected = (u64) _InterlockedCompareExchange((int volatile *) dst, + (int) src, (int) exp); +# endif + + return exp == (__int64) *expected; +} + +u8 kit_atomic_fetch_add_explicit_8(volatile u8 *var, u8 value, + i32 memory_order) { + char volatile *dst = (char volatile *) var; + char src = (char) value; + + return (u8) _InterlockedExchangeAdd8(dst, src); } -uint16_t kit_atomic_fetch_add_explicit_16(uint16_t volatile *var, - uint16_t value, - int memory_order) { +u16 kit_atomic_fetch_add_explicit_16(u16 volatile *var, u16 value, + i32 memory_order) { short volatile *dst = (short volatile *) var; short src = (short) value; - return (uint16_t) _InterlockedExchangeAdd16(dst, src); + return (u16) _InterlockedExchangeAdd16(dst, src); } -uint32_t kit_atomic_fetch_add_explicit_32(uint32_t volatile *var, - uint32_t value, - int memory_order) { +u32 kit_atomic_fetch_add_explicit_32(u32 volatile *var, u32 value, + i32 memory_order) { int volatile *dst = (int volatile *) var; int src = (int) value; - return (uint32_t) _InterlockedExchangeAdd(dst, src); + return (u32) _InterlockedExchangeAdd(dst, src); } -uint64_t kit_atomic_fetch_add_explicit_64(uint64_t volatile *var, - uint64_t value, - int memory_order) { +u64 kit_atomic_fetch_add_explicit_64(u64 volatile *var, u64 value, + i32 memory_order) { __int64 volatile *dst = (__int64 volatile *) var; __int64 src = (__int64) value; # ifdef _WIN64 - return (uint64_t) _InterlockedExchangeAdd64(dst, src); + return (u64) _InterlockedExchangeAdd64(dst, src); # else - return (uint64_t) _InterlockedExchangeAdd((int volatile *) dst, - (int) src); + assert(0); + return (u64) _InterlockedExchangeAdd((int volatile *) dst, + (int) src); # endif } diff --git a/source/kit/bigint.h b/source/kit/bigint.h index 7343b56..9f9ba16 100644 --- a/source/kit/bigint.h +++ b/source/kit/bigint.h @@ -15,21 +15,17 @@ extern "C" { #endif #if __STDC_VERSION__ >= 199901L -static_assert(sizeof(uint8_t) == 1, "uint8_t size should be 1 byte"); -static_assert(sizeof(uint32_t) == 4, - "uint32_t size should be 4 bytes"); -static_assert(sizeof(uint64_t) == 8, - "uint64_t size should be 8 bytes"); +static_assert(sizeof(u8) == 1, "u8 size should be 1 byte"); +static_assert(sizeof(u32) == 4, "u32 size should be 4 bytes"); +static_assert(sizeof(u64) == 8, "u64 size should be 8 bytes"); static_assert(KIT_BIGINT_SIZE > 0 && (KIT_BIGINT_SIZE % 8) == 0, "Invalid big integer size"); #endif typedef struct { - uint32_t v[KIT_BIGINT_SIZE / 4]; + u32 v[KIT_BIGINT_SIZE / 4]; } kit_bigint_t; -typedef uint_fast8_t kit_bit_t; - #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-function" @@ -38,38 +34,38 @@ typedef uint_fast8_t kit_bit_t; # pragma GCC optimize("O3") #endif -static kit_bigint_t kit_bi_uint32(uint32_t x) { +static kit_bigint_t kit_bi_u32(u32 x) { kit_bigint_t z; memset(&z, 0, sizeof z); z.v[0] = x; return z; } -static kit_bigint_t kit_bi_uint64(uint64_t x) { +static kit_bigint_t kit_bi_u64(u64 x) { kit_bigint_t z; memset(&z, 0, sizeof z); - z.v[0] = (uint32_t) (x & 0xffffffff); - z.v[1] = (uint32_t) (x >> 32); + z.v[0] = (u32) (x & 0xffffffff); + z.v[1] = (u32) (x >> 32); return z; } -static kit_bigint_t kit_bi_int32(int32_t x) { +static kit_bigint_t kit_bi_i32(i32 x) { kit_bigint_t z; memset(&z, x < 0 ? -1 : 0, sizeof z); z.v[0] = x; return z; } -static kit_bigint_t kit_bi_int64(int64_t x) { +static kit_bigint_t kit_bi_i64(i64 x) { kit_bigint_t z; memset(&z, x < 0 ? -1 : 0, sizeof z); - z.v[0] = (uint32_t) (((uint64_t) x) & 0xffffffff); - z.v[1] = (uint32_t) (((uint64_t) x) >> 32); + z.v[0] = (u32) (((u64) x) & 0xffffffff); + z.v[1] = (u32) (((u64) x) >> 32); return z; } static int kit_bi_is_zero(kit_bigint_t x) { - ptrdiff_t i; + i64 i; for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) if (x.v[i] != 0) return 0; @@ -86,7 +82,7 @@ static int kit_bi_equal(kit_bigint_t x, kit_bigint_t y) { } static int kit_bi_compare(kit_bigint_t x, kit_bigint_t y) { - ptrdiff_t i; + i64 i; for (i = KIT_BIGINT_SIZE / 4 - 1; i >= 0; i--) if (x.v[i] < y.v[i]) return -1; @@ -95,55 +91,55 @@ static int kit_bi_compare(kit_bigint_t x, kit_bigint_t y) { return 0; } -static ptrdiff_t kit_bi_significant_bit_count(kit_bigint_t x) { - ptrdiff_t n = KIT_BIGINT_SIZE / 4 - 1; +static i64 kit_bi_significant_bit_count(kit_bigint_t x) { + i64 n = KIT_BIGINT_SIZE / 4 - 1; while (n > 0 && x.v[n] == 0) n--; - uint32_t val = x.v[n]; + u32 val = x.v[n]; if (val == 0) return 0; - ptrdiff_t bits = (val & 0x80000000u) != 0 ? 32 - : (val & 0x40000000u) != 0 ? 31 - : (val & 0x20000000u) != 0 ? 30 - : (val & 0x10000000u) != 0 ? 29 - : (val & 0x8000000u) != 0 ? 28 - : (val & 0x4000000u) != 0 ? 27 - : (val & 0x2000000u) != 0 ? 26 - : (val & 0x1000000u) != 0 ? 25 - : (val & 0x800000u) != 0 ? 24 - : (val & 0x400000u) != 0 ? 23 - : (val & 0x200000u) != 0 ? 22 - : (val & 0x100000u) != 0 ? 21 - : (val & 0x80000u) != 0 ? 20 - : (val & 0x40000u) != 0 ? 19 - : (val & 0x20000u) != 0 ? 18 - : (val & 0x10000u) != 0 ? 17 - : (val & 0x8000u) != 0 ? 16 - : (val & 0x4000u) != 0 ? 15 - : (val & 0x2000u) != 0 ? 14 - : (val & 0x1000u) != 0 ? 13 - : (val & 0x800u) != 0 ? 12 - : (val & 0x400u) != 0 ? 11 - : (val & 0x200u) != 0 ? 10 - : (val & 0x100u) != 0 ? 9 - : (val & 0x80u) != 0 ? 8 - : (val & 0x40u) != 0 ? 7 - : (val & 0x20u) != 0 ? 6 - : (val & 0x10u) != 0 ? 5 - : (val & 0x08u) != 0 ? 4 - : (val & 0x04u) != 0 ? 3 - : (val & 0x02u) != 0 ? 2 - : 1; + i64 bits = (val & 0x80000000u) != 0 ? 32 + : (val & 0x40000000u) != 0 ? 31 + : (val & 0x20000000u) != 0 ? 30 + : (val & 0x10000000u) != 0 ? 29 + : (val & 0x8000000u) != 0 ? 28 + : (val & 0x4000000u) != 0 ? 27 + : (val & 0x2000000u) != 0 ? 26 + : (val & 0x1000000u) != 0 ? 25 + : (val & 0x800000u) != 0 ? 24 + : (val & 0x400000u) != 0 ? 23 + : (val & 0x200000u) != 0 ? 22 + : (val & 0x100000u) != 0 ? 21 + : (val & 0x80000u) != 0 ? 20 + : (val & 0x40000u) != 0 ? 19 + : (val & 0x20000u) != 0 ? 18 + : (val & 0x10000u) != 0 ? 17 + : (val & 0x8000u) != 0 ? 16 + : (val & 0x4000u) != 0 ? 15 + : (val & 0x2000u) != 0 ? 14 + : (val & 0x1000u) != 0 ? 13 + : (val & 0x800u) != 0 ? 12 + : (val & 0x400u) != 0 ? 11 + : (val & 0x200u) != 0 ? 10 + : (val & 0x100u) != 0 ? 9 + : (val & 0x80u) != 0 ? 8 + : (val & 0x40u) != 0 ? 7 + : (val & 0x20u) != 0 ? 6 + : (val & 0x10u) != 0 ? 5 + : (val & 0x08u) != 0 ? 4 + : (val & 0x04u) != 0 ? 3 + : (val & 0x02u) != 0 ? 2 + : 1; return n * 32 + bits; } static kit_bigint_t kit_bi_and(kit_bigint_t x, kit_bigint_t y) { kit_bigint_t z; - ptrdiff_t i; + i64 i; for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) z.v[i] = x.v[i] & y.v[i]; @@ -152,7 +148,7 @@ static kit_bigint_t kit_bi_and(kit_bigint_t x, kit_bigint_t y) { static kit_bigint_t kit_bi_or(kit_bigint_t x, kit_bigint_t y) { kit_bigint_t z; - ptrdiff_t i; + i64 i; for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) z.v[i] = x.v[i] | y.v[i]; @@ -161,20 +157,20 @@ static kit_bigint_t kit_bi_or(kit_bigint_t x, kit_bigint_t y) { static kit_bigint_t kit_bi_xor(kit_bigint_t x, kit_bigint_t y) { kit_bigint_t z; - ptrdiff_t i; + i64 i; for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) z.v[i] = x.v[i] ^ y.v[i]; return z; } -static kit_bigint_t kit_bi_shl_uint(kit_bigint_t x, uint32_t y) { +static kit_bigint_t kit_bi_shl_uint(kit_bigint_t x, u32 y) { kit_bigint_t z; memset(&z, 0, sizeof z); - ptrdiff_t words = (ptrdiff_t) (y / 32); - ptrdiff_t bits = (ptrdiff_t) (y % 32); - ptrdiff_t i; + i64 words = (i64) (y / 32); + i64 bits = (i64) (y % 32); + i64 i; for (i = words; i < KIT_BIGINT_SIZE / 4; i++) { z.v[i] |= x.v[i - words] << bits; @@ -185,13 +181,13 @@ static kit_bigint_t kit_bi_shl_uint(kit_bigint_t x, uint32_t y) { return z; } -static kit_bigint_t kit_bi_shr_uint(kit_bigint_t x, uint32_t y) { +static kit_bigint_t kit_bi_shr_uint(kit_bigint_t x, u32 y) { kit_bigint_t z; memset(&z, 0, sizeof z); - ptrdiff_t words = (ptrdiff_t) (y / 32); - ptrdiff_t bits = (ptrdiff_t) (y % 32); - ptrdiff_t i; + i64 words = (i64) (y / 32); + i64 bits = (i64) (y % 32); + i64 i; for (i = KIT_BIGINT_SIZE / 4 - words - 1; i >= 0; i--) { z.v[i] |= x.v[i + words] >> bits; @@ -202,8 +198,7 @@ static kit_bigint_t kit_bi_shr_uint(kit_bigint_t x, uint32_t y) { return z; } -static kit_bit_t kit_bi_carry(uint32_t x, uint32_t y, - kit_bit_t carry) { +static i8 kit_bi_carry(u32 x, u32 y, i8 carry) { assert(carry == 0 || carry == 1); return 0xffffffffu - x < y || 0xffffffffu - x - y < carry ? 1 : 0; } @@ -212,8 +207,8 @@ static kit_bit_t kit_bi_carry(uint32_t x, uint32_t y, */ static kit_bigint_t kit_bi_inc(kit_bigint_t x) { kit_bigint_t z; - kit_bit_t carry = 1; - ptrdiff_t i; + i8 carry = 1; + i64 i; for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { z.v[i] = x.v[i] + carry; @@ -227,8 +222,8 @@ static kit_bigint_t kit_bi_inc(kit_bigint_t x) { */ static kit_bigint_t kit_bi_dec(kit_bigint_t x) { kit_bigint_t z; - kit_bit_t carry = 0; - ptrdiff_t i; + i8 carry = 0; + i64 i; for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { z.v[i] = x.v[i] + 0xffffffff + carry; @@ -242,8 +237,8 @@ static kit_bigint_t kit_bi_dec(kit_bigint_t x) { */ static kit_bigint_t kit_bi_add(kit_bigint_t x, kit_bigint_t y) { kit_bigint_t z; - kit_bit_t carry = 0; - ptrdiff_t i; + i8 carry = 0; + i64 i; for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { z.v[i] = x.v[i] + y.v[i] + carry; @@ -257,8 +252,8 @@ static kit_bigint_t kit_bi_add(kit_bigint_t x, kit_bigint_t y) { */ static kit_bigint_t kit_bi_neg(kit_bigint_t x) { kit_bigint_t y; - kit_bit_t carry = 1; - ptrdiff_t i; + i8 carry = 1; + i64 i; for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { y.v[i] = (x.v[i] ^ 0xffffffff) + carry; @@ -272,8 +267,8 @@ static kit_bigint_t kit_bi_neg(kit_bigint_t x) { */ static kit_bigint_t kit_bi_sub(kit_bigint_t x, kit_bigint_t y) { kit_bigint_t z; - kit_bit_t carry = 1; - ptrdiff_t i; + i8 carry = 1; + i64 i; for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { z.v[i] = x.v[i] + (y.v[i] ^ 0xffffffff) + carry; @@ -283,9 +278,9 @@ static kit_bigint_t kit_bi_sub(kit_bigint_t x, kit_bigint_t y) { return z; } -static kit_bigint_t kit_bi_mul_uint32(kit_bigint_t x, uint32_t y) { +static kit_bigint_t kit_bi_mul_u32(kit_bigint_t x, u32 y) { kit_bigint_t z; - ptrdiff_t i, k; + i64 i, k; memset(&z, 0, sizeof z); @@ -294,12 +289,12 @@ static kit_bigint_t kit_bi_mul_uint32(kit_bigint_t x, uint32_t y) { if (x.v[i] == 0) continue; - uint64_t carry = ((uint64_t) x.v[i]) * ((uint64_t) y); + u64 carry = ((u64) x.v[i]) * ((u64) y); for (k = i; k < KIT_BIGINT_SIZE / 4 && carry != 0; k++) { - uint64_t sum = ((uint64_t) z.v[k]) + carry; - z.v[k] = ((uint32_t) (sum & 0xffffffffull)); - carry = sum >> 32; + u64 sum = ((u64) z.v[k]) + carry; + z.v[k] = ((u32) (sum & 0xffffffffull)); + carry = sum >> 32; } } @@ -310,7 +305,7 @@ static kit_bigint_t kit_bi_mul_uint32(kit_bigint_t x, uint32_t y) { */ static kit_bigint_t kit_bi_mul(kit_bigint_t x, kit_bigint_t y) { kit_bigint_t z; - ptrdiff_t i, j, k; + i64 i, j, k; memset(&z, 0, sizeof z); @@ -322,12 +317,12 @@ static kit_bigint_t kit_bi_mul(kit_bigint_t x, kit_bigint_t y) { if (y.v[j] == 0) continue; - uint64_t carry = ((uint64_t) x.v[i]) * ((uint64_t) y.v[j]); + u64 carry = ((u64) x.v[i]) * ((u64) y.v[j]); for (k = i + j; k < KIT_BIGINT_SIZE / 4 && carry != 0; k++) { - uint64_t sum = ((uint64_t) z.v[k]) + carry; - z.v[k] = ((uint32_t) (sum & 0xffffffffull)); - carry = sum >> 32; + u64 sum = ((u64) z.v[k]) + carry; + z.v[k] = ((u32) (sum & 0xffffffffull)); + carry = sum >> 32; } } } @@ -336,7 +331,7 @@ static kit_bigint_t kit_bi_mul(kit_bigint_t x, kit_bigint_t y) { } typedef struct { - kit_bit_t undefined; + i8 undefined; kit_bigint_t quotient; kit_bigint_t remainder; } kit_bi_division_t; @@ -347,20 +342,20 @@ static kit_bi_division_t kit_bi_udiv(kit_bigint_t x, kit_bigint_t y) { kit_bi_division_t z; memset(&z, 0, sizeof z); - ptrdiff_t y_bits = kit_bi_significant_bit_count(y); + i64 y_bits = kit_bi_significant_bit_count(y); if (y_bits == 0) { z.undefined = 1; return z; } - ptrdiff_t x_bits = kit_bi_significant_bit_count(x); - ptrdiff_t shift = x_bits - y_bits; + i64 x_bits = kit_bi_significant_bit_count(x); + i64 shift = x_bits - y_bits; z.remainder = x; - z.quotient = kit_bi_uint32(0); + z.quotient = kit_bi_u32(0); - y = kit_bi_shl_uint(y, (uint32_t) shift); + y = kit_bi_shl_uint(y, (u32) shift); while (shift >= 0) { if (kit_bi_compare(z.remainder, y) >= 0) { @@ -400,21 +395,21 @@ static kit_bi_division_t kit_bi_div(kit_bigint_t x, kit_bigint_t y) { return z; } -static void kit_bi_serialize(kit_bigint_t in, uint8_t *out) { - ptrdiff_t i; +static void kit_bi_serialize(kit_bigint_t in, u8 *out) { + i64 i; assert(out != NULL); for (i = 0; i < KIT_BIGINT_SIZE / 4; i++) { - out[i * 4] = (uint8_t) (in.v[i] & 0xff); - out[i * 4 + 1] = (uint8_t) ((in.v[i] >> 8) & 0xff); - out[i * 4 + 2] = (uint8_t) ((in.v[i] >> 16) & 0xff); - out[i * 4 + 3] = (uint8_t) ((in.v[i] >> 24) & 0xff); + out[i * 4] = (u8) (in.v[i] & 0xff); + out[i * 4 + 1] = (u8) ((in.v[i] >> 8) & 0xff); + out[i * 4 + 2] = (u8) ((in.v[i] >> 16) & 0xff); + out[i * 4 + 3] = (u8) ((in.v[i] >> 24) & 0xff); } } -static kit_bigint_t kit_bi_deserialize(uint8_t *in) { - ptrdiff_t i; +static kit_bigint_t kit_bi_deserialize(u8 *in) { + i64 i; kit_bigint_t out; assert(in != NULL); @@ -422,50 +417,50 @@ static kit_bigint_t kit_bi_deserialize(uint8_t *in) { memset(&out, 0, sizeof out); for (i = 0; i < KIT_BIGINT_SIZE; i++) - out.v[i / 4] |= ((uint32_t) in[i]) << (8 * (i % 4)); + out.v[i / 4] |= ((u32) in[i]) << (8 * (i % 4)); return out; } -static uint8_t kit_bin_digit(char hex) { +static u8 kit_bin_digit(char hex) { assert(hex == '0' || hex == '1'); return hex == '1' ? 1 : 0; } static kit_bigint_t kit_bi_from_bin(kit_str_t bin) { kit_bigint_t z; - ptrdiff_t i; + i64 i; memset(&z, 0, sizeof z); for (i = 0; i < bin.size && i / 8 < KIT_BIGINT_SIZE; i++) { - uint8_t digit = kit_bin_digit(bin.values[bin.size - i - 1]); + u8 digit = kit_bin_digit(bin.values[bin.size - i - 1]); z.v[i / 32] |= digit << (i % 32); } return z; } -static uint8_t kit_dec_digit(char c) { +static u8 kit_dec_digit(char c) { assert('c' >= '0' && c <= '9'); - return c >= '0' && c <= '9' ? (uint8_t) (c - '0') : 0; + return c >= '0' && c <= '9' ? (u8) (c - '0') : 0; } static kit_bigint_t kit_bi_from_dec(kit_str_t dec) { - kit_bigint_t z = kit_bi_uint32(0); - kit_bigint_t factor = kit_bi_uint32(1); - ptrdiff_t i; + kit_bigint_t z = kit_bi_u32(0); + kit_bigint_t factor = kit_bi_u32(1); + i64 i; for (i = 0; i < dec.size; i++) { - uint32_t digit = kit_dec_digit(dec.values[dec.size - i - 1]); - z = kit_bi_add(z, kit_bi_mul_uint32(factor, digit)); - factor = kit_bi_mul_uint32(factor, 10); + u32 digit = kit_dec_digit(dec.values[dec.size - i - 1]); + z = kit_bi_add(z, kit_bi_mul_u32(factor, digit)); + factor = kit_bi_mul_u32(factor, 10); } return z; } -static uint8_t kit_hex_digit(char hex) { +static u8 kit_hex_digit(char hex) { assert((hex >= '0' && hex <= '9') || (hex >= 'a' && hex <= 'f') || (hex >= 'A' && hex <= 'F')); @@ -481,19 +476,19 @@ static uint8_t kit_hex_digit(char hex) { static kit_bigint_t kit_bi_from_hex(kit_str_t hex) { kit_bigint_t z; - ptrdiff_t i; + i64 i; memset(&z, 0, sizeof z); for (i = 0; i < hex.size && i / 2 < KIT_BIGINT_SIZE; i++) { - uint8_t digit = kit_hex_digit(hex.values[hex.size - i - 1]); + u8 digit = kit_hex_digit(hex.values[hex.size - i - 1]); z.v[i / 8] |= digit << (4 * (i % 8)); } return z; } -static uint8_t KIT_BASE32_DIGITS[] = { +static u8 KIT_BASE32_DIGITS[] = { ['1'] = 0, ['2'] = 1, ['3'] = 2, ['4'] = 3, ['5'] = 4, ['6'] = 5, ['7'] = 6, ['8'] = 7, ['9'] = 8, ['a'] = 9, ['b'] = 10, ['c'] = 11, ['d'] = 12, ['e'] = 13, ['f'] = 14, @@ -503,19 +498,18 @@ static uint8_t KIT_BASE32_DIGITS[] = { ['y'] = 30, ['z'] = 31 }; -static uint8_t kit_base32_digit(char c) { +static u8 kit_base32_digit(char c) { assert(c >= '\0' && c < sizeof KIT_BASE32_DIGITS); - assert(c == '1' || - KIT_BASE32_DIGITS[(size_t) (unsigned char) c] != 0); + assert(c == '1' || KIT_BASE32_DIGITS[(size_t) (u8) c] != 0); return c >= '\0' && c < sizeof KIT_BASE32_DIGITS - ? KIT_BASE32_DIGITS[(size_t) (unsigned char) c] + ? KIT_BASE32_DIGITS[(size_t) (u8) c] : 0; } static kit_bigint_t kit_bi_from_base32(kit_str_t base32) { kit_bigint_t z; - ptrdiff_t i; + i64 i; memset(&z, 0, sizeof z); @@ -527,7 +521,7 @@ static kit_bigint_t kit_bi_from_base32(kit_str_t base32) { return z; } -static uint8_t KIT_BASE58_DIGITS[] = { +static u8 KIT_BASE58_DIGITS[] = { ['1'] = 0, ['2'] = 1, ['3'] = 2, ['4'] = 3, ['5'] = 4, ['6'] = 5, ['7'] = 6, ['8'] = 7, ['9'] = 8, ['A'] = 9, ['B'] = 10, ['C'] = 11, ['D'] = 12, ['E'] = 13, ['F'] = 14, @@ -542,26 +536,24 @@ static uint8_t KIT_BASE58_DIGITS[] = { ['x'] = 55, ['y'] = 56, ['z'] = 57 }; -static uint8_t kit_base58_digit(char c) { +static u8 kit_base58_digit(char c) { assert(c >= '\0' && c < sizeof KIT_BASE58_DIGITS); - assert(c == '1' || - KIT_BASE58_DIGITS[(size_t) (unsigned char) c] != 0); + assert(c == '1' || KIT_BASE58_DIGITS[(size_t) (u8) c] != 0); return c >= '\0' && c < sizeof KIT_BASE58_DIGITS - ? KIT_BASE58_DIGITS[(size_t) (unsigned char) c] + ? KIT_BASE58_DIGITS[(size_t) (u8) c] : 0; } static kit_bigint_t kit_bi_from_base58(kit_str_t base58) { - kit_bigint_t z = kit_bi_uint32(0); - kit_bigint_t factor = kit_bi_uint32(1); - ptrdiff_t i; + kit_bigint_t z = kit_bi_u32(0); + kit_bigint_t factor = kit_bi_u32(1); + i64 i; for (i = 0; i < base58.size; i++) { - uint32_t digit = kit_base58_digit( - base58.values[base58.size - i - 1]); - z = kit_bi_add(z, kit_bi_mul_uint32(factor, digit)); - factor = kit_bi_mul_uint32(factor, 58); + u32 digit = kit_base58_digit(base58.values[base58.size - i - 1]); + z = kit_bi_add(z, kit_bi_mul_u32(factor, digit)); + factor = kit_bi_mul_u32(factor, 58); } return z; @@ -589,10 +581,10 @@ static kit_bigint_t kit_bi_from_base58(kit_str_t base58) { #ifndef KIT_DISABLE_SHORT_NAMES # define bigint_t kit_bigint_t -# define bi_uint32 kit_bi_uint32 -# define bi_uint64 kit_bi_uint64 -# define bi_int32 kit_bi_int32 -# define bi_int64 kit_bi_int64 +# define bi_u32 kit_bi_u32 +# define bi_u64 kit_bi_u64 +# define bi_i32 kit_bi_i32 +# define bi_i64 kit_bi_i64 # define bi_is_zero kit_bi_is_zero # define bi_is_neg kit_bi_is_neg # define bi_equal kit_bi_equal diff --git a/source/kit/condition_variable.c b/source/kit/condition_variable.c deleted file mode 100644 index b18e402..0000000 --- a/source/kit/condition_variable.c +++ /dev/null @@ -1 +0,0 @@ -#include "condition_variable.h" diff --git a/source/kit/condition_variable.h b/source/kit/condition_variable.h deleted file mode 100644 index c27022e..0000000 --- a/source/kit/condition_variable.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef KIT_CONDITION_VARIABLE_H -#define KIT_CONDITION_VARIABLE_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_, - struct timespec const *__restrict); -int cnd_wait(cnd_t *, mtx_t *mtx_); - -# ifdef __cplusplus -} -# endif - -#endif - -#endif diff --git a/source/kit/dynamic_array.c b/source/kit/dynamic_array.c index 5ba60fc..2b17d07 100644 --- a/source/kit/dynamic_array.c +++ b/source/kit/dynamic_array.c @@ -3,8 +3,8 @@ #include #include -void kit_da_init(kit_da_void_t *array, ptrdiff_t element_size, - ptrdiff_t size, kit_allocator_t *alloc) { +void kit_da_init(kit_da_void_t *array, i64 element_size, i64 size, + kit_allocator_t *alloc) { assert(array != NULL); assert(element_size > 0); assert(size >= 0); @@ -23,17 +23,15 @@ void kit_da_init(kit_da_void_t *array, ptrdiff_t element_size, array->alloc = alloc; } -static ptrdiff_t eval_capacity(ptrdiff_t current_cap, - ptrdiff_t required_cap) { +static i64 eval_capacity(i64 current_cap, i64 required_cap) { if (current_cap == 0) return required_cap; - ptrdiff_t cap = current_cap; + i64 cap = current_cap; while (cap < required_cap) cap *= 2; return cap; } -void kit_da_resize(kit_da_void_t *array, ptrdiff_t element_size, - ptrdiff_t size) { +void kit_da_resize(kit_da_void_t *array, i64 element_size, i64 size) { assert(array != NULL); assert(element_size > 0); assert(size >= 0); @@ -41,7 +39,7 @@ void kit_da_resize(kit_da_void_t *array, ptrdiff_t element_size, if (size <= array->capacity) { array->size = size; } else { - ptrdiff_t capacity = eval_capacity(array->capacity, size); + i64 capacity = eval_capacity(array->capacity, size); void *bytes = kit_alloc_dispatch( array->alloc, KIT_ALLOCATE, element_size * capacity, 0, NULL); @@ -59,8 +57,8 @@ void kit_da_resize(kit_da_void_t *array, ptrdiff_t element_size, } } -void kit_da_resize_exact(kit_da_void_t *array, ptrdiff_t element_size, - ptrdiff_t capacity) { +void kit_da_resize_exact(kit_da_void_t *array, i64 element_size, + i64 capacity) { assert(array != NULL); assert(element_size > 0); assert(capacity >= 0); diff --git a/source/kit/dynamic_array.h b/source/kit/dynamic_array.h index d2f2a6b..dbb18d9 100644 --- a/source/kit/dynamic_array.h +++ b/source/kit/dynamic_array.h @@ -8,27 +8,26 @@ extern "C" { #endif typedef struct { - ptrdiff_t capacity; - ptrdiff_t size; + i64 capacity; + i64 size; void *values; kit_allocator_t *alloc; } kit_da_void_t; -void kit_da_init(kit_da_void_t *array, ptrdiff_t element_size, - ptrdiff_t size, kit_allocator_t *alloc); +void kit_da_init(kit_da_void_t *array, i64 element_size, i64 size, + kit_allocator_t *alloc); -void kit_da_resize(kit_da_void_t *array, ptrdiff_t element_size, - ptrdiff_t size); +void kit_da_resize(kit_da_void_t *array, i64 element_size, i64 size); -void kit_da_resize_exact(kit_da_void_t *array, ptrdiff_t element_size, - ptrdiff_t size); +void kit_da_resize_exact(kit_da_void_t *array, i64 element_size, + i64 size); /* Dynamic array type definition. */ #define KIT_DA(element_type_) \ struct { \ - ptrdiff_t capacity; \ - ptrdiff_t size; \ + i64 capacity; \ + i64 size; \ element_type_ *values; \ kit_allocator_t *alloc; \ } @@ -70,7 +69,7 @@ void kit_da_resize_exact(kit_da_void_t *array, ptrdiff_t element_size, */ #define KIT_DA_APPEND(array_, value_) \ do { \ - ptrdiff_t kit_index_back_ = (array_).size; \ + i64 kit_index_back_ = (array_).size; \ KIT_DA_RESIZE((array_), kit_index_back_ + 1); \ if (kit_index_back_ < (array_).size) \ (array_).values[kit_index_back_] = (value_); \ @@ -80,9 +79,9 @@ void kit_da_resize_exact(kit_da_void_t *array, ptrdiff_t element_size, */ #define KIT_DA_INSERT(array_, index_, value_) \ do { \ - ptrdiff_t kit_i_; \ - ptrdiff_t kit_index_back_ = (array_).size; \ - ptrdiff_t kit_indert_n_ = (index_); \ + i64 kit_i_; \ + i64 kit_index_back_ = (array_).size; \ + i64 kit_indert_n_ = (index_); \ KIT_DA_RESIZE((array_), kit_index_back_ + 1); \ if (kit_index_back_ + 1 == (array_).size) { \ for (kit_i_ = kit_index_back_; kit_i_ > kit_indert_n_; \ @@ -96,19 +95,16 @@ void kit_da_resize_exact(kit_da_void_t *array, ptrdiff_t element_size, */ #define KIT_DA_ERASE(array_, index_) \ do { \ - ptrdiff_t i_; \ + i64 i_; \ for (i_ = (index_) + 1; i_ < (array_).size; i_++) \ (array_).values[i_ - 1] = (array_).values[i_]; \ KIT_DA_RESIZE((array_), (array_).size - 1); \ } while (0) -typedef KIT_DA(char) kit_string_t; - #ifndef KIT_DISABLE_SHORT_NAMES # define da_void_t kit_da_void_t # define da_init kit_da_init # define da_resize kit_da_resize -# define string_t kit_string_t # define DA KIT_DA # define DA_INIT KIT_DA_INIT diff --git a/source/kit/file.c b/source/kit/file.c index fd24390..6a7f740 100644 --- a/source/kit/file.c +++ b/source/kit/file.c @@ -26,15 +26,16 @@ enum { PATH_BUF_SIZE = 4096 }; # define st_mtim st_mtimespec #endif -static int is_delim(char c) { +static i32 is_delim(char c) { return c == '/' || c == '\\'; } -static kit_string_t kit_get_env_(char *name, kit_allocator_t *alloc) { - char *val = getenv(name); - ptrdiff_t size = val != NULL ? (ptrdiff_t) strlen(val) : 0; +static kit_str_builder_t kit_get_env_(char *name, + kit_allocator_t *alloc) { + char *val = getenv(name); + i64 size = val != NULL ? (i64) strlen(val) : 0; - string_t result; + str_builder_t result; DA_INIT(result, size, alloc); assert(result.size == size); @@ -46,11 +47,12 @@ static kit_string_t kit_get_env_(char *name, kit_allocator_t *alloc) { return result; } -kit_string_t kit_path_norm(kit_str_t path, kit_allocator_t *alloc) { - str_t parent = SZ(".."); - ptrdiff_t i, i1, j; +kit_str_builder_t kit_path_norm(kit_str_t path, + kit_allocator_t *alloc) { + str_t parent = SZ(".."); + i64 i, i1, j; - string_t norm; + str_builder_t norm; DA_INIT(norm, path.size, alloc); assert(norm.size == path.size); @@ -65,8 +67,8 @@ kit_string_t kit_path_norm(kit_str_t path, kit_allocator_t *alloc) { str_t s = { .size = i - i1 - 1, .values = path.values + i1 + 1 }; if (AR_EQUAL(s, parent)) { - int have_parent = 0; - ptrdiff_t i0 = 0; + i32 have_parent = 0; + i64 i0 = 0; for (j = 0; j < i1; j++) { if (norm.values[j] != '\0') @@ -86,7 +88,7 @@ kit_string_t kit_path_norm(kit_str_t path, kit_allocator_t *alloc) { i1 = i; } - ptrdiff_t size = 0; + i64 size = 0; for (i = 0; i < norm.size; i++) { if (norm.values[i] != '\0') { @@ -102,11 +104,11 @@ kit_string_t kit_path_norm(kit_str_t path, kit_allocator_t *alloc) { return norm; } -kit_string_t kit_path_join(kit_str_t left, kit_str_t right, - kit_allocator_t *alloc) { - ptrdiff_t left_size = left.size; - ptrdiff_t right_size = right.size; - char *right_values = right.values; +kit_str_builder_t kit_path_join(kit_str_t left, kit_str_t right, + kit_allocator_t *alloc) { + i64 left_size = left.size; + i64 right_size = right.size; + char *right_values = right.values; if (left_size > 0 && is_delim(left.values[left_size - 1])) left_size--; @@ -115,7 +117,7 @@ kit_string_t kit_path_join(kit_str_t left, kit_str_t right, right_values++; } - kit_string_t joined; + kit_str_builder_t joined; DA_INIT(joined, left_size + right_size + 1, alloc); assert(joined.size == left_size + right_size + 1); @@ -129,8 +131,8 @@ kit_string_t kit_path_join(kit_str_t left, kit_str_t right, return joined; } -kit_string_t kit_path_user(kit_allocator_t *alloc) { - kit_string_t user = kit_get_env_(KIT_ENV_HOME, alloc); +kit_str_builder_t kit_path_user(kit_allocator_t *alloc) { + kit_str_builder_t user = kit_get_env_(KIT_ENV_HOME, alloc); if (user.size == 0) { DA_RESIZE(user, 1); if (user.size == 1) @@ -139,8 +141,8 @@ kit_string_t kit_path_user(kit_allocator_t *alloc) { return user; } -kit_string_t kit_path_cache(kit_allocator_t *alloc) { - kit_string_t cache, user; +kit_str_builder_t kit_path_cache(kit_allocator_t *alloc) { + kit_str_builder_t cache, user; #if defined(_WIN32) && !defined(__CYGWIN__) cache = kit_get_env_("LOCALAPPDATA", alloc); @@ -167,12 +169,12 @@ kit_string_t kit_path_cache(kit_allocator_t *alloc) { return cache; } -kit_str_t kit_path_index(kit_str_t path, ptrdiff_t index) { +kit_str_t kit_path_index(kit_str_t path, i64 index) { str_t s = { .size = 0, .values = NULL }; - ptrdiff_t i0 = 0; - ptrdiff_t i = 0; - ptrdiff_t n = 0; + i64 i0 = 0; + i64 i = 0; + i64 n = 0; for (; i < path.size; i++) { if (!is_delim(path.values[i])) @@ -197,12 +199,12 @@ kit_str_t kit_path_index(kit_str_t path, ptrdiff_t index) { return s; } -kit_str_t kit_path_take(kit_str_t path, ptrdiff_t count) { +kit_str_t kit_path_take(kit_str_t path, i64 count) { str_t s = { .size = 0, .values = path.values }; - ptrdiff_t i0 = 0; - ptrdiff_t i = 0; - ptrdiff_t n = 0; + i64 i0 = 0; + i64 i = 0; + i64 n = 0; for (; i < path.size; i++) { if (!is_delim(path.values[i])) @@ -235,7 +237,7 @@ static void win32_prepare_path_(WCHAR *buf, kit_str_t path) { buf[2] = L'?'; buf[3] = L'\\'; if (path.size > 0 && path.size + 5 < PATH_BUF_SIZE) - for (ptrdiff_t i = 0; i < path.size; i++) { + for (i64 i = 0; i < path.size; i++) { if (path.values[i] == '/') buf[4 + i] = L'\\'; else @@ -270,11 +272,11 @@ kit_status_t kit_file_create_folder(kit_str_t path) { } kit_status_t kit_file_create_folder_recursive(kit_str_t path) { - ptrdiff_t i; + i64 i; for (i = 0;; i++) { str_t part = kit_path_take(path, i); - int type = kit_path_type(part); + i32 type = kit_path_type(part); if (type == KIT_PATH_FILE) return KIT_ERROR_FILE_ALREADY_EXISTS; if (type == KIT_PATH_NONE) { @@ -309,8 +311,8 @@ kit_status_t kit_file_remove_folder(kit_str_t path) { kit_status_t kit_file_remove_recursive(kit_str_t path, kit_allocator_t *alloc) { - int type = kit_path_type(path); - ptrdiff_t i; + i32 type = kit_path_type(path); + i64 i; switch (type) { case KIT_PATH_FILE: return kit_file_remove(path); @@ -369,11 +371,10 @@ kit_file_info_t kit_file_info(kit_str_t path) { if (f != INVALID_HANDLE_VALUE) { FILETIME ft; if (GetFileTime(f, NULL, NULL, &ft) != 0) { - uint64_t nsec100 = (((uint64_t) ft.dwHighDateTime) << 32) | - (uint64_t) ft.dwLowDateTime; - result.time_modified_sec = (int64_t) (nsec100 / 10000000); - result.time_modified_nsec = (int32_t) (100 * - (nsec100 % 10000000)); + ui64 nsec100 = (((ui64) ft.dwHighDateTime) << 32) | + (ui64) ft.dwLowDateTime; + result.time_modified_sec = (i64) (nsec100 / 10000000); + result.time_modified_nsec = (i32) (100 * (nsec100 % 10000000)); } else { assert(0); } @@ -381,8 +382,7 @@ kit_file_info_t kit_file_info(kit_str_t path) { DWORD high; DWORD low = GetFileSize(f, &high); - result.size = (int64_t) ((((uint64_t) high) << 32) | - (uint64_t) low); + result.size = (i64) ((((ui64) high) << 32) | (ui64) low); result.status = KIT_OK; CloseHandle(f); @@ -391,14 +391,14 @@ kit_file_info_t kit_file_info(kit_str_t path) { #else struct stat info; if (stat(buf, &info) == 0 && S_ISREG(info.st_mode)) { - result.size = (int64_t) info.st_size; + result.size = (i64) info.st_size; # ifndef st_mtime /* No support for nanosecond timestamps. */ - result.time_modified_sec = (int64_t) info.st_mtime; + result.time_modified_sec = (i64) info.st_mtime; # else - result.time_modified_sec = (int64_t) info.st_mtim.tv_sec; - result.time_modified_nsec = (int32_t) info.st_mtim.tv_nsec; + result.time_modified_sec = (i64) info.st_mtim.tv_sec; + result.time_modified_nsec = (i32) info.st_mtim.tv_nsec; # endif result.status = KIT_OK; return result; @@ -432,14 +432,14 @@ kit_path_list_t kit_file_enum_folder(kit_str_t path, return result; do { - ptrdiff_t n = result.files.size; + i64 n = result.files.size; DA_RESIZE(result.files, n + 1); if (result.files.size != n + 1) { result.status = KIT_ERROR_BAD_ALLOC; break; } - ptrdiff_t size = 0; + i64 size = 0; while (size < MAX_PATH && data.cFileName[size] != L'\0') size++; DA_INIT(result.files.values[n], size, alloc); if (result.files.values[n].size != size) { @@ -448,7 +448,7 @@ kit_path_list_t kit_file_enum_folder(kit_str_t path, break; } - for (ptrdiff_t i = 0; i < size; i++) + for (i64 i = 0; i < size; i++) result.files.values[n].values[i] = data.cFileName[i]; } while (FindNextFileW(find, &data) != 0); @@ -468,14 +468,14 @@ kit_path_list_t kit_file_enum_folder(kit_str_t path, if (entry->d_name[0] == '.') continue; - ptrdiff_t n = result.files.size; + i64 n = result.files.size; DA_RESIZE(result.files, n + 1); if (result.files.size != n + 1) { result.status = KIT_ERROR_BAD_ALLOC; break; } - ptrdiff_t size = (ptrdiff_t) strlen(entry->d_name); + i64 size = (i64) strlen(entry->d_name); DA_INIT(result.files.values[n], size, alloc); if (result.files.values[n].size != size) { DA_RESIZE(result.files, n); @@ -494,7 +494,7 @@ kit_path_list_t kit_file_enum_folder(kit_str_t path, } void kit_path_list_destroy(kit_path_list_t list) { - ptrdiff_t i; + i64 i; for (i = 0; i < list.files.size; i++) DA_DESTROY(list.files.values[i]); DA_DESTROY(list.files); diff --git a/source/kit/file.h b/source/kit/file.h index 491779d..c3cb0b0 100644 --- a/source/kit/file.h +++ b/source/kit/file.h @@ -3,7 +3,7 @@ #include "dynamic_array.h" #include "status.h" -#include "string_ref.h" +#include "string_builder.h" #ifdef __cplusplus extern "C" { @@ -19,18 +19,19 @@ extern "C" { # define KIT_ENV_HOME "HOME" #endif -kit_string_t kit_path_norm(kit_str_t path, kit_allocator_t *alloc); +kit_str_builder_t kit_path_norm(kit_str_t path, + kit_allocator_t *alloc); -kit_string_t kit_path_join(kit_str_t left, kit_str_t right, - kit_allocator_t *alloc); +kit_str_builder_t kit_path_join(kit_str_t left, kit_str_t right, + kit_allocator_t *alloc); -kit_string_t kit_path_user(kit_allocator_t *alloc); +kit_str_builder_t kit_path_user(kit_allocator_t *alloc); -kit_string_t kit_path_cache(kit_allocator_t *alloc); +kit_str_builder_t kit_path_cache(kit_allocator_t *alloc); -kit_str_t kit_path_index(kit_str_t path, ptrdiff_t index); +kit_str_t kit_path_index(kit_str_t path, i64 index); -kit_str_t kit_path_take(kit_str_t path, ptrdiff_t count); +kit_str_t kit_path_take(kit_str_t path, i64 count); kit_status_t kit_file_create_folder(kit_str_t path); @@ -54,16 +55,16 @@ kit_path_type_t kit_path_type(kit_str_t path); typedef struct { kit_status_t status; - int64_t time_modified_sec; - int32_t time_modified_nsec; - int64_t size; + i64 time_modified_sec; + i32 time_modified_nsec; + i64 size; } kit_file_info_t; kit_file_info_t kit_file_info(kit_str_t path); typedef struct { kit_status_t status; - KIT_DA(kit_string_t) files; + KIT_DA(kit_str_builder_t) files; } kit_path_list_t; kit_path_list_t kit_file_enum_folder(kit_str_t path, diff --git a/source/kit/input_buffer.c b/source/kit/input_buffer.c index 362b7b8..c1ae748 100644 --- a/source/kit/input_buffer.c +++ b/source/kit/input_buffer.c @@ -4,10 +4,10 @@ #include typedef struct { - ptrdiff_t ref_count; - kit_is_handle_t upstream; - kit_allocator_t *alloc; - kit_string_t data; + i64 ref_count; + kit_is_handle_t upstream; + kit_allocator_t *alloc; + kit_str_builder_t data; } internal_buffer_t; static internal_buffer_t *kit_buf_init_(kit_is_handle_t upstream, @@ -49,26 +49,25 @@ static void kit_buf_release_(void *p) { } } -static void kit_buf_adjust_(void *p, ptrdiff_t size) { +static void kit_buf_adjust_(void *p, i64 size) { assert(p != NULL); assert(size >= 0); internal_buffer_t *buf = (internal_buffer_t *) p; - ptrdiff_t offset = buf->data.size; + i64 offset = buf->data.size; if (offset < size) { DA_RESIZE(buf->data, size); kit_str_t destination = { .size = size - offset, .values = buf->data.values + offset }; - ptrdiff_t n = KIT_IS_READ(buf->upstream, destination); + i64 n = KIT_IS_READ(buf->upstream, destination); DA_RESIZE(buf->data, offset + n); } } -static ptrdiff_t kit_buf_read_(void *p, ptrdiff_t offset, - kit_str_t destination) { +static i64 kit_buf_read_(void *p, i64 offset, kit_str_t destination) { internal_buffer_t *buf = (internal_buffer_t *) p; - ptrdiff_t n = destination.size < buf->data.size - offset + i64 n = destination.size < buf->data.size - offset ? destination.size : buf->data.size - offset; memcpy(destination.values, buf->data.values + offset, n); @@ -87,7 +86,7 @@ kit_ib_handle_t kit_ib_wrap(kit_is_handle_t upstream, return buf; } -kit_ib_handle_t kit_ib_read(kit_ib_handle_t buf, ptrdiff_t size) { +kit_ib_handle_t kit_ib_read(kit_ib_handle_t buf, i64 size) { kit_ib_handle_t next; memset(&next, 0, sizeof next); @@ -105,7 +104,7 @@ kit_ib_handle_t kit_ib_read(kit_ib_handle_t buf, ptrdiff_t size) { kit_str_t destination = { .size = next.data.size, .values = next.data.values }; - ptrdiff_t n = kit_buf_read_(buf.internal, buf.offset, destination); + i64 n = kit_buf_read_(buf.internal, buf.offset, destination); next.offset = buf.offset + n; next.internal = buf.internal; @@ -130,7 +129,7 @@ kit_ib_handle_t kit_ib_read_while( DA_INIT(next.data, 0, kit_buf_alloc_(buf.internal)); - ptrdiff_t size = 0; + i64 size = 0; for (;; ++size) { kit_buf_adjust_(buf.internal, buf.offset + size + 1); @@ -141,7 +140,7 @@ kit_ib_handle_t kit_ib_read_while( kit_str_t destination = { .size = 1, .values = next.data.values + size }; - ptrdiff_t n = kit_buf_read_(buf.internal, buf.offset + size, + i64 n = kit_buf_read_(buf.internal, buf.offset + size, destination); kit_str_t data = { .size = size + 1, .values = next.data.values }; diff --git a/source/kit/input_buffer.h b/source/kit/input_buffer.h index 0fa1f07..51fccbb 100644 --- a/source/kit/input_buffer.h +++ b/source/kit/input_buffer.h @@ -1,7 +1,7 @@ #ifndef KIT_INPUT_BUFFER_H #define KIT_INPUT_BUFFER_H -#include "dynamic_array.h" +#include "string_builder.h" #include "input_stream.h" #include "status.h" @@ -10,16 +10,16 @@ extern "C" { #endif typedef struct { - kit_status_t status; - ptrdiff_t offset; - void *internal; - kit_string_t data; + kit_status_t status; + i64 offset; + void *internal; + kit_str_builder_t data; } kit_ib_handle_t; kit_ib_handle_t kit_ib_wrap(kit_is_handle_t upstream, kit_allocator_t *alloc); -kit_ib_handle_t kit_ib_read(kit_ib_handle_t buf, ptrdiff_t size); +kit_ib_handle_t kit_ib_read(kit_ib_handle_t buf, i64 size); typedef int (*kit_ib_read_condition_fn)(kit_str_t data); diff --git a/source/kit/input_stream.c b/source/kit/input_stream.c index a975fef..369cf64 100644 --- a/source/kit/input_stream.c +++ b/source/kit/input_stream.c @@ -5,42 +5,41 @@ enum { KIT_INPUT_STREAM_STR, KIT_INPUT_STREAM_FILE }; typedef struct { - ptrdiff_t type; + i64 type; kit_allocator_t *alloc; } kit_is_state_basic_t; typedef struct { - ptrdiff_t type; + i64 type; kit_allocator_t *alloc; kit_str_t string; } kit_is_state_str_t; typedef struct { - ptrdiff_t type; + i64 type; kit_allocator_t *alloc; FILE *file; } kit_is_state_file_t; -static int kit_is_check_type_(void *state, ptrdiff_t type) { +static int kit_is_check_type_(void *state, i64 type) { kit_is_state_basic_t *basic = (kit_is_state_basic_t *) state; return basic != NULL && basic->type == type; } -static ptrdiff_t kit_read_str_(void *state, kit_str_t destination) { +static i64 kit_read_str_(void *state, kit_str_t destination) { if (!kit_is_check_type_(state, KIT_INPUT_STREAM_STR)) return 0; - kit_is_state_str_t *str = (kit_is_state_str_t *) state; - ptrdiff_t size = destination.size < str->string.size - ? destination.size - : str->string.size; + kit_is_state_str_t *str = (kit_is_state_str_t *) state; + i64 size = destination.size < str->string.size ? destination.size + : str->string.size; memcpy(destination.values, str->string.values, size); str->string.values += size; str->string.size -= size; return size; } -static ptrdiff_t kit_read_file_(void *state, kit_str_t destination) { +static i64 kit_read_file_(void *state, kit_str_t destination) { if (!kit_is_check_type_(state, KIT_INPUT_STREAM_FILE)) return 0; @@ -49,8 +48,8 @@ static ptrdiff_t kit_read_file_(void *state, kit_str_t destination) { if (f->file == NULL || feof(f->file)) return 0; - ptrdiff_t size = (ptrdiff_t) fread(destination.values, 1, - destination.size, f->file); + i64 size = (i64) fread(destination.values, 1, destination.size, + f->file); if (size <= 0) return 0; diff --git a/source/kit/input_stream.h b/source/kit/input_stream.h index 95a6187..d355983 100644 --- a/source/kit/input_stream.h +++ b/source/kit/input_stream.h @@ -10,8 +10,7 @@ extern "C" { #endif -typedef ptrdiff_t (*kit_is_read_fn)(void *state, - kit_str_t destination); +typedef i64 (*kit_is_read_fn)(void *state, kit_str_t destination); typedef struct { void *state; diff --git a/source/kit/lower_bound.h b/source/kit/lower_bound.h index f40c918..1ad670b 100644 --- a/source/kit/lower_bound.h +++ b/source/kit/lower_bound.h @@ -1,17 +1,19 @@ #ifndef KIT_LOWER_BOUND_H #define KIT_LOWER_BOUND_H +#include "types.h" + #ifdef __cplusplus extern "C" { #endif #define KIT_LOWER_BOUND_INL(return_val, size, ...) \ do { \ - ptrdiff_t position_ = 0; \ - ptrdiff_t count_ = (size); \ + i64 position_ = 0; \ + i64 count_ = (size); \ while (count_ > 0) { \ - ptrdiff_t const delta_ = count_ / 2; \ - ptrdiff_t const index_ = position_ + delta_; \ + i64 delta_ = count_ / 2; \ + i64 index_ = position_ + delta_; \ if (__VA_ARGS__) { \ position_ += delta_ + 1; \ count_ -= delta_ + 1; \ diff --git a/source/kit/mersenne_twister_64.c b/source/kit/mersenne_twister_64.c index 9bf238f..4032dc9 100644 --- a/source/kit/mersenne_twister_64.c +++ b/source/kit/mersenne_twister_64.c @@ -5,9 +5,9 @@ #define UM 0xffffffff80000000ull #define LM 0x7fffffffull -void kit_mt64_init_array(kit_mt64_state_t *state, ptrdiff_t size, - uint64_t *seed) { - ptrdiff_t i; +void kit_mt64_init_array(kit_mt64_state_t *state, i64 size, + u64 *seed) { + i64 i; for (i = 0; i < size && i < KIT_MT64_N; i++) state->mt[i] = seed[i]; for (state->index = size; state->index < KIT_MT64_N; state->index++) state->mt[state->index] = (6364136223846793005ull * @@ -17,40 +17,40 @@ void kit_mt64_init_array(kit_mt64_state_t *state, ptrdiff_t size, state->index); } -void kit_mt64_init(kit_mt64_state_t *state, uint64_t seed) { +void kit_mt64_init(kit_mt64_state_t *state, u64 seed) { kit_mt64_init_array(state, 1, &seed); } void kit_mt64_rotate(kit_mt64_state_t *state) { - static uint64_t mag01[2] = { 0ull, MATRIX_A }; + static u64 mag01[2] = { 0ull, MATRIX_A }; - uint64_t x; - int i; + u64 x; + i32 i; for (i = 0; i < KIT_MT64_N - MM; i++) { x = (state->mt[i] & UM) | (state->mt[i + 1] & LM); state->mt[i] = state->mt[i + MM] ^ (x >> 1u) ^ - mag01[(int) (x & 1ull)]; + mag01[(i32) (x & 1ull)]; } for (; i < KIT_MT64_N - 1; i++) { x = (state->mt[i] & UM) | (state->mt[i + 1] & LM); state->mt[i] = state->mt[i + (MM - KIT_MT64_N)] ^ (x >> 1u) ^ - mag01[(int) (x & 1ull)]; + mag01[(i32) (x & 1ull)]; } x = (state->mt[KIT_MT64_N - 1] & UM) | (state->mt[0] & LM); state->mt[KIT_MT64_N - 1] = state->mt[MM - 1] ^ (x >> 1u) ^ - mag01[(int) (x & 1ull)]; + mag01[(i32) (x & 1ull)]; state->index = 0; } -uint64_t kit_mt64_generate(kit_mt64_state_t *state) { +u64 kit_mt64_generate(kit_mt64_state_t *state) { if (state->index >= KIT_MT64_N) kit_mt64_rotate(state); - uint64_t x = state->mt[state->index++]; + u64 x = state->mt[state->index++]; x ^= (x >> 29u) & 0x5555555555555555ull; x ^= (x << 17u) & 0x71d67fffeda60000ull; @@ -59,3 +59,8 @@ uint64_t kit_mt64_generate(kit_mt64_state_t *state) { return x; } + +#undef MM +#undef MATRIX_A +#undef UM +#undef LM diff --git a/source/kit/mersenne_twister_64.h b/source/kit/mersenne_twister_64.h index 452fd73..c0c04a9 100644 --- a/source/kit/mersenne_twister_64.h +++ b/source/kit/mersenne_twister_64.h @@ -1,12 +1,7 @@ #ifndef KIT_MERSENNE_TWISTER_64_H #define KIT_MERSENNE_TWISTER_64_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include -#include +#include "types.h" #ifdef __cplusplus extern "C" { @@ -17,15 +12,15 @@ enum { }; typedef struct { - uint64_t mt[KIT_MT64_N]; - uint64_t index; + u64 mt[KIT_MT64_N]; + u64 index; } kit_mt64_state_t; -void kit_mt64_init_array(kit_mt64_state_t *state, ptrdiff_t size, - uint64_t *seed); -void kit_mt64_init(kit_mt64_state_t *state, uint64_t seed); -void kit_mt64_rotate(kit_mt64_state_t *state); -uint64_t kit_mt64_generate(kit_mt64_state_t *state); +void kit_mt64_init_array(kit_mt64_state_t *state, i64 size, + u64 *seed); +void kit_mt64_init(kit_mt64_state_t *state, u64 seed); +void kit_mt64_rotate(kit_mt64_state_t *state); +u64 kit_mt64_generate(kit_mt64_state_t *state); #ifndef KIT_DISABLE_SHORT_NAMES # define mt64_state_t kit_mt64_state_t diff --git a/source/kit/move_back.h b/source/kit/move_back.h index 0927321..7313a1e 100644 --- a/source/kit/move_back.h +++ b/source/kit/move_back.h @@ -1,9 +1,7 @@ #ifndef KIT_MOVE_BACK_H #define KIT_MOVE_BACK_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif +#include "types.h" #include @@ -13,9 +11,9 @@ extern "C" { #define KIT_MOVE_BACK_INL(new_size, array, ...) \ do { \ - ptrdiff_t index_; \ - ptrdiff_t end_ = (array).size; \ - unsigned char temp_[sizeof *(array).values]; \ + i64 index_; \ + i64 end_ = (array).size; \ + u8 temp_[sizeof *(array).values]; \ for (index_ = 0; index_ < end_;) { \ if (__VA_ARGS__) { \ end_--; \ diff --git a/source/kit/mutex.c b/source/kit/mutex.c deleted file mode 100644 index 320d4c7..0000000 --- a/source/kit/mutex.c +++ /dev/null @@ -1 +0,0 @@ -#include "mutex.h" diff --git a/source/kit/mutex.h b/source/kit/mutex.h deleted file mode 100644 index 254d5fa..0000000 --- a/source/kit/mutex.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef KIT_MUTEX_H -#define KIT_MUTEX_H - -#ifndef KIT_DISABLE_SYSTEM_THREADS -# ifndef _GNU_SOURCE -# define _GNU_SOURCE -# endif - -# include "thread_defs.h" -# include "time.h" - -# if !defined(_WIN32) || defined(__CYGWIN__) -# include -# 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_, - struct timespec const *__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 d51b4ec..56b46d7 100644 --- a/source/kit/secure_random.c +++ b/source/kit/secure_random.c @@ -1,118 +1,43 @@ #include "secure_random.h" -#include "condition_variable.h" -#include "mersenne_twister_64.h" -#include "mutex.h" - #include #include +#include #if defined(_WIN32) && !defined(__CYGWIN__) # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN 1 # endif -# include +# include +# include #else # include #endif -static uint64_t get_available_memory(void) { -#if defined(_WIN32) && !defined(__CYGWIN__) - MEMORYSTATUSEX status; - status.dwLength = sizeof(status); - GlobalMemoryStatusEx(&status); - return (uint64_t) status.ullTotalPhys; -#else - uint64_t pages = (uint64_t) sysconf(_SC_PHYS_PAGES); - uint64_t page_size = (uint64_t) sysconf(_SC_PAGE_SIZE); - return pages * page_size; -#endif -} - -#ifndef KIT_DISABLE_SYSTEM_THREADS -static once_flag kit_secure_random_fallback_flag; -static mtx_t kit_secure_random_fallback_mutex; - -static void secure_random_fallback_init(void) { - mtx_init(&kit_secure_random_fallback_mutex, mtx_plain); -} -#endif - -static void secure_random_fallback(ptrdiff_t size, void *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 - - /* Try to get some unpredictable system properties and use them to - * seed the pseudo random number generator. - */ - - static int8_t first_run = 1; - static uint64_t n = 0; - static uint64_t time_sec = 0; - static uint64_t time_nsec = 0; - struct timespec t; - - timespec_get(&t, TIME_UTC); - - kit_mt64_state_t state; - - if (first_run) { - first_run = 0; - uint64_t seed[] = { n, get_available_memory(), - (uint64_t) t.tv_sec, (uint64_t) t.tv_nsec }; - kit_mt64_init_array(&state, sizeof seed / sizeof *seed, seed); - } else { - uint64_t seed[] = { n, - get_available_memory(), - (uint64_t) t.tv_sec, - (uint64_t) t.tv_nsec, - (uint64_t) t.tv_sec - time_sec, - (uint64_t) t.tv_nsec - time_nsec }; - kit_mt64_init_array(&state, sizeof seed / sizeof *seed, seed); - } - - kit_mt64_rotate(&state); - - n = kit_mt64_generate(&state); - time_sec = (uint64_t) t.tv_sec; - time_nsec = (uint64_t) t.tv_nsec; - - for (ptrdiff_t i = 0; i < size; i++) - ((uint8_t *) data)[i] = (uint8_t) (kit_mt64_generate(&state) >> - 56); - -#ifndef KIT_DISABLE_SYSTEM_THREADS - mtx_unlock(&kit_secure_random_fallback_mutex); -#endif -} - -void kit_secure_random(ptrdiff_t size, void *data) { - assert(size > 0); +void kit_secure_random(i64 size, void *data) { + assert(size >= 0); assert(data != NULL); if (size <= 0 || data == NULL) return; #if defined(_WIN32) && !defined(__CYGWIN__) - secure_random_fallback(size, data); + HCRYPTPROV prov = NULL; + if (!CryptAcquireContextW(&prov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT) || + !CryptGenRandom(prov, (DWORD) size, (BYTE *) data) || + !CryptReleaseContext(prov, 0)) + abort(); #else FILE *f = fopen("/dev/urandom", "rb"); - assert(f != NULL); - if (f == NULL) { - secure_random_fallback(size, data); - return; - } + if (f == NULL) + abort(); - size_t n = fread(data, 1, size, f); + i64 n = (i64) fread(data, 1, size, f); fclose(f); - assert(n == size); - if (n != size) - secure_random_fallback(size, data); + abort(); #endif } diff --git a/source/kit/secure_random.h b/source/kit/secure_random.h index 5531a4a..36eca0d 100644 --- a/source/kit/secure_random.h +++ b/source/kit/secure_random.h @@ -1,18 +1,13 @@ #ifndef KIT_SECURE_RANDOM_H #define KIT_SECURE_RANDOM_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include -#include +#include "types.h" #ifdef __cplusplus extern "C" { #endif -void kit_secure_random(ptrdiff_t size, void *data); +void kit_secure_random(i64 size, void *data); #ifndef KIT_DISABLE_SHORT_NAMES # define secure_random kit_secure_random diff --git a/source/kit/sha256.c b/source/kit/sha256.c index beb1772..3abe972 100644 --- a/source/kit/sha256.c +++ b/source/kit/sha256.c @@ -13,7 +13,7 @@ #define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3)) #define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10)) -static uint32_t kit_sha256_k[64] = { +static u32 kit_sha256_k[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, @@ -29,16 +29,15 @@ static uint32_t kit_sha256_k[64] = { 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; -static void kit_sha256_transform(uint32_t *state, uint8_t *data) { +static void kit_sha256_transform(u32 *state, u8 *data) { assert(state != NULL); assert(data != NULL); - uint32_t a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + u32 a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; for (i = 0, j = 0; i < 16; ++i, j += 4) - m[i] = ((uint32_t) data[j] << 24) | - ((uint32_t) data[j + 1] << 16) | - ((uint32_t) data[j + 2] << 8) | ((uint32_t) data[j + 3]); + m[i] = ((u32) data[j] << 24) | ((u32) data[j + 1] << 16) | + ((u32) data[j + 2] << 8) | ((u32) data[j + 3]); for (; i < 64; ++i) m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; @@ -74,19 +73,18 @@ static void kit_sha256_transform(uint32_t *state, uint8_t *data) { state[7] += h; } -kit_sha256_hash_t kit_sha256(ptrdiff_t in_size, uint8_t *in_data) { +kit_sha256_hash_t kit_sha256(i64 in_size, u8 *in_data) { assert(in_size >= 0); assert(in_data != NULL); - uint32_t state[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, - 0xa54ff53a, 0x510e527f, 0x9b05688c, - 0x1f83d9ab, 0x5be0cd19 }; + u32 state[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; - uint8_t data[64]; + u8 data[64]; - ptrdiff_t i; - ptrdiff_t datalen = 0; - uint64_t bitlen = 0; + i64 i; + i64 datalen = 0; + u64 bitlen = 0; if (in_data != NULL) for (i = 0; i < in_size; ++i) { @@ -142,3 +140,12 @@ kit_sha256_hash_t kit_sha256(ptrdiff_t in_size, uint8_t *in_data) { return hash; } + +#undef ROTLEFT +#undef ROTRIGHT +#undef CH +#undef MAJ +#undef EP0 +#undef EP1 +#undef SIG0 +#undef SIG1 diff --git a/source/kit/sha256.h b/source/kit/sha256.h index 182ee80..92e9784 100644 --- a/source/kit/sha256.h +++ b/source/kit/sha256.h @@ -1,12 +1,7 @@ #ifndef KIT_SHA256_H #define KIT_SHA256_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include -#include +#include "types.h" #ifdef __cplusplus extern "C" { @@ -15,10 +10,10 @@ extern "C" { enum { KIT_SHA256_BLOCK_SIZE = 32 }; typedef struct { - uint8_t v[KIT_SHA256_BLOCK_SIZE]; + u8 v[KIT_SHA256_BLOCK_SIZE]; } kit_sha256_hash_t; -kit_sha256_hash_t kit_sha256(ptrdiff_t size, uint8_t *data); +kit_sha256_hash_t kit_sha256(i64 size, u8 *data); #ifdef __cplusplus } diff --git a/source/kit/sockets.h b/source/kit/sockets.h index 2d4af90..2c37fcb 100644 --- a/source/kit/sockets.h +++ b/source/kit/sockets.h @@ -1,10 +1,6 @@ #ifndef KIT_SOCKETS_H #define KIT_SOCKETS_H -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - #include "status.h" #ifndef KIT_DISABLE_SYSTEM_SOCKETS @@ -21,7 +17,7 @@ # include # define socket_t SOCKET -# define socklen_t int +# define socklen_t i32 # ifdef __cplusplus extern "C" { @@ -41,14 +37,14 @@ static kit_status_t kit_sockets_cleanup(void) { return KIT_OK; } -static int kit_socket_set_blocking(socket_t s) { +static i32 kit_socket_set_blocking(socket_t s) { u_long flag = 0; return ioctlsocket(s, FIONBIO, &flag) == 0 ? KIT_OK : KIT_ERROR_SOCKET_CONTROL_FAILED; } -static int kit_socket_set_nonblocking(socket_t s) { +static i32 kit_socket_set_nonblocking(socket_t s) { u_long flag = 1; return ioctlsocket(s, FIONBIO, &flag) == 0 ? KIT_OK @@ -72,7 +68,7 @@ static int kit_socket_set_nonblocking(socket_t s) { # include # include -# define socket_t int +# define socket_t i32 # define closesocket close # define INVALID_SOCKET -1 @@ -89,15 +85,15 @@ static kit_status_t kit_sockets_cleanup(void) { return KIT_OK; } -static int kit_socket_set_blocking(socket_t s) { - int const flags = fcntl(s, F_GETFL, 0); +static i32 kit_socket_set_blocking(socket_t s) { + i32 flags = fcntl(s, F_GETFL, 0); return fcntl(s, F_SETFL, flags & ~O_NONBLOCK) == 0 ? KIT_OK : KIT_ERROR_SOCKET_CONTROL_FAILED; } -static int kit_socket_set_nonblocking(socket_t s) { - int const flags = fcntl(s, F_GETFL, 0); +static i32 kit_socket_set_nonblocking(socket_t s) { + i32 flags = fcntl(s, F_GETFL, 0); return fcntl(s, F_SETFL, flags | O_NONBLOCK) == 0 ? KIT_OK : KIT_ERROR_SOCKET_CONTROL_FAILED; diff --git a/source/kit/status.h b/source/kit/status.h index e689c5f..7b98229 100644 --- a/source/kit/status.h +++ b/source/kit/status.h @@ -1,6 +1,8 @@ #ifndef KIT_STATUS_H #define KIT_STATUS_H +#include "types.h" + #ifdef __cplusplus extern "C" { #endif @@ -18,7 +20,7 @@ enum { KIT_ERROR_SOCKET_CONTROL_FAILED }; -typedef signed int kit_status_t; +typedef i32 kit_status_t; #ifdef __cplusplus } diff --git a/source/kit/string_builder.c b/source/kit/string_builder.c new file mode 100644 index 0000000..f76c3a4 --- /dev/null +++ b/source/kit/string_builder.c @@ -0,0 +1 @@ +#include "string_builder.h" diff --git a/source/kit/string_builder.h b/source/kit/string_builder.h new file mode 100644 index 0000000..c6d89ce --- /dev/null +++ b/source/kit/string_builder.h @@ -0,0 +1,13 @@ +#ifndef KIT_STRING_BUILDER_H +#define KIT_STRING_BUILDER_H + +#include "string_ref.h" +#include "dynamic_array.h" + +typedef KIT_DA(char) kit_str_builder_t; + +#ifndef KIT_DISABLE_SHORT_NAMES +# define str_builder_t kit_str_builder_t +#endif + +#endif diff --git a/source/kit/string_ref.h b/source/kit/string_ref.h index b171840..29ef8ab 100644 --- a/source/kit/string_ref.h +++ b/source/kit/string_ref.h @@ -9,9 +9,7 @@ extern "C" { #endif -typedef KIT_AR(char) kit_string_ref_t; - -typedef kit_string_ref_t kit_str_t; +typedef KIT_AR(char) kit_str_t; #ifdef __GNUC__ # pragma GCC diagnostic push @@ -21,19 +19,19 @@ typedef kit_string_ref_t kit_str_t; # pragma GCC optimize("O3") #endif -static kit_str_t kit_str(ptrdiff_t size, char *static_string) { +static kit_str_t kit_str(i64 size, char *static_string) { kit_str_t s = { .size = size, .values = static_string }; return s; } -/* Make a barbarian string for C standard library functions. - * Not thread safe. - * Use with caution. - */ +// Make a barbarian string for C standard library functions. +// Not thread safe. +// Use with caution. +// static char *kit_make_bs(kit_str_t s) { static char buf[8][4096]; - static int index = 0; - ptrdiff_t n = s.size; + static i32 index = 0; + i64 n = s.size; if (n > 4095) n = 4095; memcpy(buf[index], s.values, n); @@ -59,7 +57,6 @@ static char *kit_make_bs(kit_str_t s) { #ifndef KIT_DISABLE_SHORT_NAMES # define BS(string_) kit_make_bs(KIT_WRAP_STR(string_)) -# define string_ref_t kit_string_ref_t # define str_t kit_str_t # define SZ KIT_SZ diff --git a/source/kit/thread.h b/source/kit/thread.h deleted file mode 100644 index 92e6a5d..0000000 --- a/source/kit/thread.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef KIT_THREAD_H -#define KIT_THREAD_H - -#ifndef KIT_DISABLE_SYSTEM_THREADS -# ifndef _GNU_SOURCE -# define _GNU_SOURCE -# endif - -# include "thread_defs.h" - -# include -# include - -# if defined(__cplusplus) -# define _Noreturn [[noreturn]] -# elif defined(_MSC_VER) -# define _Noreturn __declspec(noreturn) -# endif - -# if !defined(_WIN32) || defined(__CYGWIN__) -# include -# 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 - -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/thread.posix.c b/source/kit/thread.posix.c deleted file mode 100644 index bcb089f..0000000 --- a/source/kit/thread.posix.c +++ /dev/null @@ -1,275 +0,0 @@ -#include "thread.h" - -#include "allocator.h" -#include "condition_variable.h" -#include "mutex.h" - -#ifndef KIT_DISABLE_SYSTEM_THREADS -# if !defined(_WIN32) || defined(__CYGWIN__) - -# include -# include -# include -# include -# include /* intptr_t */ -# include -# include - -# ifndef PTHREAD_STACK_MIN -# define PTHREAD_STACK_MIN 16384 -# endif - -/* -Configuration macro: - - EMULATED_THREADS_USE_NATIVE_TIMEDLOCK - Use pthread_mutex_timedlock() for `mtx_timedlock()' - Otherwise use mtx_trylock() + *busy loop* emulation. -*/ -# if !defined(__CYGWIN__) && !defined(__APPLE__) && \ - !defined(__NetBSD__) -# define EMULATED_THREADS_USE_NATIVE_TIMEDLOCK -# endif - -/* -Implementation limits: - - Conditionally emulation for "mutex with timeout" - (see EMULATED_THREADS_USE_NATIVE_TIMEDLOCK macro) -*/ -typedef struct { - thrd_start_t func; - void *arg; -} impl_thrd_param_t; - -static void *impl_thrd_routine(void *p) { - impl_thrd_param_t pack = *((impl_thrd_param_t *) p); - kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, p); - return (void *) (intptr_t) pack.func(pack.arg); -} - -void call_once(once_flag *flag, void (*func)(void)) { - pthread_once(flag, func); -} - -int cnd_broadcast(cnd_t *cond) { - assert(cond != NULL); - return (pthread_cond_broadcast(cond) == 0) ? thrd_success - : thrd_error; -} - -void cnd_destroy(cnd_t *cond) { - assert(cond); - pthread_cond_destroy(cond); -} - -int cnd_init(cnd_t *cond) { - assert(cond != NULL); - return (pthread_cond_init(cond, NULL) == 0) ? thrd_success - : thrd_error; -} - -int cnd_signal(cnd_t *cond) { - assert(cond != NULL); - return (pthread_cond_signal(cond) == 0) ? thrd_success : thrd_error; -} - -int cnd_timedwait(cnd_t *cond, mtx_t *mtx, - struct timespec const *abs_time) { - int rt; - - assert(mtx != NULL); - assert(cond != NULL); - assert(abs_time != NULL); - - rt = pthread_cond_timedwait(cond, mtx, abs_time); - if (rt == ETIMEDOUT) - return thrd_timedout; - return (rt == 0) ? thrd_success : thrd_error; -} - -int cnd_wait(cnd_t *cond, mtx_t *mtx) { - assert(mtx != NULL); - assert(cond != NULL); - return (pthread_cond_wait(cond, mtx) == 0) ? thrd_success - : thrd_error; -} - -void mtx_destroy(mtx_t *mtx) { - assert(mtx != NULL); - pthread_mutex_destroy(mtx); -} - -/* - * XXX: Workaround when building with -O0 and without pthreads link. - * - * In such cases constant folding and dead code elimination won't be - * available, thus the compiler will always add the pthread_mutexattr* - * functions into the binary. As we try to link, we'll fail as the - * symbols are unresolved. - * - * Ideally we'll enable the optimisations locally, yet that does not - * seem to work. - * - * So the alternative workaround is to annotate the symbols as weak. - * Thus the linker will be happy and things don't clash when building - * with -O1 or greater. - */ -# if defined(KIT_HAVE_FUNC_ATTRIBUTE_WEAK) && !defined(__CYGWIN__) -__attribute__((weak)) int pthread_mutexattr_init( - pthread_mutexattr_t *attr); - -__attribute__((weak)) int pthread_mutexattr_settype( - pthread_mutexattr_t *attr, int type); - -__attribute__((weak)) int pthread_mutexattr_destroy( - pthread_mutexattr_t *attr); -# endif - -int mtx_init(mtx_t *mtx, int type) { -# ifdef KIT_HAVE_PTHREAD_MUTEXATTR_SETTYPE - pthread_mutexattr_t attr; -# endif - assert(mtx != NULL); - if (type != mtx_plain && type != mtx_timed && - type != (mtx_plain | mtx_recursive) && - type != (mtx_timed | mtx_recursive)) - return thrd_error; - - if ((type & mtx_recursive) == 0) { - pthread_mutex_init(mtx, NULL); - return thrd_success; - } - -# ifdef KIT_HAVE_PTHREAD_MUTEXATTR_SETTYPE - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(mtx, &attr); - pthread_mutexattr_destroy(&attr); - return thrd_success; -# else - return thrd_error; -# endif -} - -int mtx_lock(mtx_t *mtx) { - assert(mtx != NULL); - return (pthread_mutex_lock(mtx) == 0) ? thrd_success : thrd_error; -} - -int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) { - assert(mtx != NULL); - assert(ts != NULL); - - { -# ifdef EMULATED_THREADS_USE_NATIVE_TIMEDLOCK - int rt; - rt = pthread_mutex_timedlock(mtx, ts); - if (rt == 0) - return thrd_success; - return (rt == ETIMEDOUT) ? thrd_timedout : thrd_error; -# else - time_t expire = time(NULL); - expire += ts->tv_sec; - while (mtx_trylock(mtx) != thrd_success) { - time_t now = time(NULL); - if (expire < now) - return thrd_timedout; - // busy loop! - thrd_yield(); - } - return thrd_success; -# endif - } -} - -int mtx_trylock(mtx_t *mtx) { - assert(mtx != NULL); - return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy; -} - -int mtx_unlock(mtx_t *mtx) { - assert(mtx != NULL); - return (pthread_mutex_unlock(mtx) == 0) ? thrd_success : thrd_error; -} - -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; - assert(thr != NULL); - assert(require_stack_size == 0 || - require_stack_size >= PTHREAD_STACK_MIN); - pthread_attr_t attr; - pthread_attr_t *attr_p = NULL; - if (require_stack_size > 0) { - ptrdiff_t const page_size = (ptrdiff_t) sysconf(_SC_PAGESIZE); - ptrdiff_t const delta = require_stack_size % page_size; - ptrdiff_t const stack_size = delta == 0 ? require_stack_size - : require_stack_size + - page_size - delta; - if (pthread_attr_init(&attr) != 0) - return thrd_nomem; - if (pthread_attr_setstacksize(&attr, (size_t) stack_size) != 0) - return thrd_wrong_stack_size; - attr_p = &attr; - } - - pack = (impl_thrd_param_t *) kit_alloc_dispatch( - NULL, KIT_ALLOCATE, sizeof(impl_thrd_param_t), 0, NULL); - if (!pack) { - if (attr_p) - pthread_attr_destroy(attr_p); - return thrd_nomem; - } - pack->func = func; - pack->arg = arg; - if (pthread_create(thr, attr_p, impl_thrd_routine, pack) != 0) { - kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, pack); - if (attr_p) - pthread_attr_destroy(attr_p); - return thrd_error; - } - if (attr_p) - pthread_attr_destroy(attr_p); - return thrd_success; -} - -int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { - return thrd_create_with_stack(thr, func, arg, 0); -} -thrd_t thrd_current(void) { - return pthread_self(); -} - -int thrd_detach(thrd_t thr) { - return (pthread_detach(thr) == 0) ? thrd_success : thrd_error; -} - -int thrd_equal(thrd_t thr0, thrd_t thr1) { - return pthread_equal(thr0, thr1); -} - -_Noreturn void thrd_exit(int res) { - pthread_exit((void *) (intptr_t) res); -} - -int thrd_join(thrd_t thr, int *res) { - void *code; - if (pthread_join(thr, &code) != 0) - return thrd_error; - if (res) - *res = (int) (intptr_t) code; - return thrd_success; -} - -int thrd_sleep(const struct timespec *time_point, - struct timespec *remaining) { - assert(time_point != NULL); - return nanosleep(time_point, remaining); -} - -void thrd_yield(void) { - sched_yield(); -} - -# endif -#endif diff --git a/source/kit/thread.win32.c b/source/kit/thread.win32.c deleted file mode 100644 index e7f84bf..0000000 --- a/source/kit/thread.win32.c +++ /dev/null @@ -1,380 +0,0 @@ -#include "thread.h" - -#include "allocator.h" -#include "condition_variable.h" -#include "mutex.h" - -#ifndef KIT_DISABLE_SYSTEM_THREADS -# if defined(_WIN32) && !defined(__CYGWIN__) - -# include -# include -# include -# include -# include -# include - -# ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN 1 -# endif -# include - -/* -Configuration macro: - - EMULATED_THREADS_USE_NATIVE_CALL_ONCE - Use native WindowsAPI one-time initialization function. - (requires WinVista or later) - Otherwise emulate by mtx_trylock() + *busy loop* for WinXP. - - EMULATED_THREADS_TSS_DTOR_SLOTNUM - Max registerable TSS dtor number. -*/ - -# if _WIN32_WINNT >= 0x0600 -/* 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 */ - -/* check configuration */ -# if defined(EMULATED_THREADS_USE_NATIVE_CALL_ONCE) && \ - (_WIN32_WINNT < 0x0600) -# error EMULATED_THREADS_USE_NATIVE_CALL_ONCE requires _WIN32_WINNT>=0x0600 -# endif - -static_assert(sizeof(cnd_t) == sizeof(CONDITION_VARIABLE), - "The size of cnd_t must equal to CONDITION_VARIABLE"); -static_assert(sizeof(thrd_t) == sizeof(HANDLE), - "The size of thrd_t must equal to HANDLE"); -static_assert(sizeof(tss_t) == sizeof(DWORD), - "The size of tss_t must equal to DWORD"); -static_assert(sizeof(mtx_t) == sizeof(CRITICAL_SECTION), - "The size of mtx_t must equal to CRITICAL_SECTION"); -static_assert(sizeof(once_flag) == sizeof(INIT_ONCE), - "The size of once_flag must equal to INIT_ONCE"); - -/* -Implementation limits: - - Conditionally emulation for "Initialization functions" - (see EMULATED_THREADS_USE_NATIVE_CALL_ONCE macro) - - Emulated `mtx_timelock()' with mtx_trylock() + *busy loop* -*/ - -typedef struct { - thrd_start_t func; - void *arg; - thrd_t thrd; -} impl_thrd_param_t; - -struct thrd_state { - thrd_t thrd; - bool handle_need_close; -}; - -static thread_local struct thrd_state impl_current_thread = { 0 }; - -static unsigned __stdcall impl_thrd_routine(void *p) { - impl_thrd_param_t *pack_p = (impl_thrd_param_t *) p; - impl_thrd_param_t pack; - int code; - impl_current_thread.thrd = pack_p->thrd; - impl_current_thread.handle_need_close = false; - memcpy(&pack, pack_p, sizeof(impl_thrd_param_t)); - kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, p); - code = pack.func(pack.arg); - return (unsigned) code; -} - -static time_t impl_timespec2msec(const struct timespec *ts) { - return (ts->tv_sec * 1000U) + (ts->tv_nsec / 1000000L); -} - -static DWORD impl_abs2relmsec(const struct timespec *abs_time) { - const time_t abs_ms = impl_timespec2msec(abs_time); - struct timespec now; - timespec_get(&now, TIME_UTC); - const time_t now_ms = impl_timespec2msec(&now); - const DWORD rel_ms = (abs_ms > now_ms) ? (DWORD) (abs_ms - now_ms) - : 0; - return rel_ms; -} - -# ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE -struct impl_call_once_param { - void (*func)(void); -}; - -static BOOL CALLBACK impl_call_once_callback(PINIT_ONCE InitOnce, - PVOID Parameter, - PVOID *Context) { - struct impl_call_once_param *param = (struct impl_call_once_param *) - Parameter; - (param->func)(); - ((void) InitOnce); - ((void) Context); /* suppress warning */ - return TRUE; -} -# endif /* ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE */ - -static struct impl_tss_dtor_entry { - tss_t key; - tss_dtor_t dtor; -} impl_tss_dtor_tbl[EMULATED_THREADS_TSS_DTOR_SLOTNUM]; - -static int impl_tss_dtor_register(tss_t key, tss_dtor_t dtor) { - int i; - for (i = 0; i < EMULATED_THREADS_TSS_DTOR_SLOTNUM; i++) { - if (!impl_tss_dtor_tbl[i].dtor) - break; - } - if (i == EMULATED_THREADS_TSS_DTOR_SLOTNUM) - return 1; - impl_tss_dtor_tbl[i].key = key; - impl_tss_dtor_tbl[i].dtor = dtor; - return 0; -} - -static void impl_tss_dtor_invoke(void) { - int i; - for (i = 0; i < EMULATED_THREADS_TSS_DTOR_SLOTNUM; i++) { - if (impl_tss_dtor_tbl[i].dtor) { - void *val = (void *) (size_t) TlsGetValue( - impl_tss_dtor_tbl[i].key); - if (val) - (impl_tss_dtor_tbl[i].dtor)(val); - } - } -} - -void call_once(once_flag *flag, void (*func)(void)) { - assert(flag && func); -# ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE - { - struct impl_call_once_param param; - param.func = func; - InitOnceExecuteOnce((PINIT_ONCE) flag, impl_call_once_callback, - (PVOID) ¶m, NULL); - } -# else - if (InterlockedCompareExchangePointer( - (PVOID volatile *) &flag->status, (PVOID) 1, (PVOID) 0) == - 0) { - (func)(); - InterlockedExchangePointer((PVOID volatile *) &flag->status, - (PVOID) 2); - } else { - while (flag->status == 1) { - // busy loop! - thrd_yield(); - } - } -# endif -} - -int cnd_broadcast(cnd_t *cond) { - assert(cond != NULL); - WakeAllConditionVariable((PCONDITION_VARIABLE) cond); - return thrd_success; -} - -void cnd_destroy(cnd_t *cond) { - assert(cond != NULL); - /* do nothing */ - (void) cond; -} - -int cnd_init(cnd_t *cond) { - assert(cond != NULL); - InitializeConditionVariable((PCONDITION_VARIABLE) cond); - return thrd_success; -} - -int cnd_signal(cnd_t *cond) { - assert(cond != NULL); - WakeConditionVariable((PCONDITION_VARIABLE) cond); - return thrd_success; -} - -int cnd_timedwait(cnd_t *cond, mtx_t *mtx, - const struct timespec *abs_time) { - assert(cond != NULL); - assert(mtx != NULL); - assert(abs_time != NULL); - const DWORD timeout = impl_abs2relmsec(abs_time); - if (SleepConditionVariableCS((PCONDITION_VARIABLE) cond, - (PCRITICAL_SECTION) mtx, timeout)) - return thrd_success; - return (GetLastError() == ERROR_TIMEOUT) ? thrd_timedout - : thrd_error; -} - -int cnd_wait(cnd_t *cond, mtx_t *mtx) { - assert(cond != NULL); - assert(mtx != NULL); - SleepConditionVariableCS((PCONDITION_VARIABLE) cond, - (PCRITICAL_SECTION) mtx, INFINITE); - return thrd_success; -} - -void mtx_destroy(mtx_t *mtx) { - assert(mtx); - DeleteCriticalSection((PCRITICAL_SECTION) mtx); -} - -int mtx_init(mtx_t *mtx, int type) { - assert(mtx != NULL); - if (type != mtx_plain && type != mtx_timed && - type != (mtx_plain | mtx_recursive) && - type != (mtx_timed | mtx_recursive)) - return thrd_error; - InitializeCriticalSection((PCRITICAL_SECTION) mtx); - return thrd_success; -} - -int mtx_lock(mtx_t *mtx) { - assert(mtx != NULL); - EnterCriticalSection((PCRITICAL_SECTION) mtx); - return thrd_success; -} - -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! */ - thrd_yield(); - } - return thrd_success; -} - -int mtx_trylock(mtx_t *mtx) { - assert(mtx != NULL); - return TryEnterCriticalSection((PCRITICAL_SECTION) mtx) - ? thrd_success - : thrd_busy; -} - -int mtx_unlock(mtx_t *mtx) { - assert(mtx != NULL); - LeaveCriticalSection((PCRITICAL_SECTION) mtx); - return thrd_success; -} - -int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg, - ptrdiff_t const stack_size) { - impl_thrd_param_t *pack; - uintptr_t handle; - assert(thr != NULL); - assert(stack_size >= 0 && stack_size < 0x100000000); - - pack = (impl_thrd_param_t *) kit_alloc_dispatch( - NULL, KIT_ALLOCATE, (sizeof(impl_thrd_param_t)), 0, NULL); - if (!pack) - return thrd_nomem; - pack->func = func; - pack->arg = arg; - handle = _beginthreadex(NULL, (unsigned) stack_size, - impl_thrd_routine, pack, CREATE_SUSPENDED, - NULL); - if (handle == 0) { - kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, pack); - if (errno == EAGAIN || errno == EACCES) - return thrd_nomem; - return thrd_error; - } - thr->handle = (void *) handle; - pack->thrd = *thr; - ResumeThread((HANDLE) handle); - return thrd_success; -} - -int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { - return thrd_create_with_stack(thr, func, arg, 0); -} - -thrd_t thrd_current(void) { - /* GetCurrentThread() returns a pseudo-handle, which we need - * to pass to DuplicateHandle(). Only the resulting handle can be - * used from other threads. - * - * Note that neither handle can be compared to the one by - * thread_create. Only the thread IDs - as returned by GetThreadId() - * and GetCurrentThreadId() can be compared directly. - * - * Other potential solutions would be: - * - define thrd_t as a thread Ids, but this would mean we'd need to - * OpenThread for many operations - * - use malloc'ed memory for thrd_t. This would imply using TLS for - * current thread. - * - * Neither is particularly nice. - * - * Life would be much easier if C11 threads had different - * abstractions for threads and thread IDs, just like C++11 threads - * does... - */ - struct thrd_state *state = &impl_current_thread; - if (state->thrd.handle == NULL) { - if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &(state->thrd.handle), - 0, FALSE, DUPLICATE_SAME_ACCESS)) { - abort(); - } - state->handle_need_close = true; - } - return state->thrd; -} - -int thrd_detach(thrd_t thr) { - CloseHandle(thr.handle); - return thrd_success; -} - -int thrd_equal(thrd_t thr0, thrd_t thr1) { - return GetThreadId(thr0.handle) == GetThreadId(thr1.handle); -} - -_Noreturn void thrd_exit(int res) { - _endthreadex((unsigned) res); -} - -int thrd_join(thrd_t thr, int *res) { - DWORD w, code; - if (thr.handle == NULL) { - return thrd_error; - } - w = WaitForSingleObject(thr.handle, INFINITE); - if (w != WAIT_OBJECT_0) - return thrd_error; - if (res) { - if (!GetExitCodeThread(thr.handle, &code)) { - CloseHandle(thr.handle); - return thrd_error; - } - *res = (int) code; - } - CloseHandle(thr.handle); - return thrd_success; -} - -int thrd_sleep(const struct timespec *time_point, - struct timespec *remaining) { - (void) remaining; - assert(time_point); - assert(!remaining); /* not implemented */ - Sleep((DWORD) impl_timespec2msec(time_point)); - return 0; -} - -void thrd_yield(void) { - SwitchToThread(); -} - -# endif -#endif diff --git a/source/kit/thread_defs.h b/source/kit/thread_defs.h deleted file mode 100644 index 0a9c033..0000000 --- a/source/kit/thread_defs.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef KIT_THREAD_DEFS_H -#define KIT_THREAD_DEFS_H - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - thrd_success = 0, - thrd_timedout, - thrd_error, - thrd_busy, - thrd_nomem, - thrd_wrong_stack_size -}; - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/source/kit/threads.h b/source/kit/threads.h new file mode 100644 index 0000000..8ff46ed --- /dev/null +++ b/source/kit/threads.h @@ -0,0 +1,132 @@ +#ifndef KIT_THREADS_H +#define KIT_THREADS_H +#ifndef KIT_DISABLE_SYSTEM_THREADS + +# include "time.h" + +# include +# include + +# if !defined(_WIN32) || defined(__CYGWIN__) +# include +# endif + +# if defined(__cplusplus) +# define _Noreturn [[noreturn]] +# elif defined(_MSC_VER) +# define _Noreturn __declspec(noreturn) +# 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 + +enum { + mtx_plain, + mtx_recursive, + mtx_timed, +}; + +enum { + thrd_success, + thrd_timedout, + thrd_error, + thrd_busy, + thrd_nomem, + thrd_wrong_stack_size +}; + +# if defined(_WIN32) && !defined(__CYGWIN__) +typedef struct { + void *DebugInfo; + long LockCount; + long RecursionCount; + void *OwningThread; + void *LockSemaphore; + uintptr_t SpinCount; +} mtx_t; + +typedef struct { + void *Ptr; +} cnd_t; + +typedef struct { + volatile uintptr_t status; +} once_flag; + +typedef struct { + void *handle; +} thrd_t; + +typedef unsigned long tss_t; +# else +typedef pthread_mutex_t mtx_t; +typedef pthread_cond_t cnd_t; +typedef pthread_once_t once_flag; +typedef pthread_t thrd_t; +typedef pthread_key_t tss_t; +# endif + +typedef void (*tss_dtor_t)(void *); +typedef int (*thrd_start_t)(void *); + +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_, + struct timespec const *__restrict); +int mtx_trylock(mtx_t *mtx_); +int mtx_unlock(mtx_t *mtx_); +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_, + struct timespec const *__restrict); +int cnd_wait(cnd_t *, 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); +_Noreturn void thrd_exit(int); +int thrd_join(thrd_t, int *); +int thrd_sleep(struct timespec const *, struct timespec *); +void thrd_yield(void); + +# ifdef __cplusplus +} +# endif + +#endif +#endif diff --git a/source/kit/threads.posix.c b/source/kit/threads.posix.c new file mode 100644 index 0000000..44465a3 --- /dev/null +++ b/source/kit/threads.posix.c @@ -0,0 +1,271 @@ +#include "threads.h" + +#ifndef KIT_DISABLE_SYSTEM_THREADS +# include "allocator.h" + +# if !defined(_WIN32) || defined(__CYGWIN__) +# include +# include +# include +# include +# include +# include + +# ifndef PTHREAD_STACK_MIN +# define PTHREAD_STACK_MIN 16384 +# endif + +/* +Configuration macro: + + EMULATED_THREADS_USE_NATIVE_TIMEDLOCK + Use pthread_mutex_timedlock() for `mtx_timedlock()' + Otherwise use mtx_trylock() + *busy loop* emulation. +*/ +# if !defined(__CYGWIN__) && !defined(__APPLE__) && \ + !defined(__NetBSD__) +# define EMULATED_THREADS_USE_NATIVE_TIMEDLOCK +# endif + +/* +Implementation limits: + - Conditionally emulation for "mutex with timeout" + (see EMULATED_THREADS_USE_NATIVE_TIMEDLOCK macro) +*/ +typedef struct { + thrd_start_t func; + void *arg; +} impl_thrd_param_t; + +static void *impl_thrd_routine(void *p) { + impl_thrd_param_t pack = *((impl_thrd_param_t *) p); + kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, p); + return (void *) (intptr_t) pack.func(pack.arg); +} + +void call_once(once_flag *flag, void (*func)(void)) { + pthread_once(flag, func); +} + +int cnd_broadcast(cnd_t *cond) { + assert(cond != NULL); + return (pthread_cond_broadcast(cond) == 0) ? thrd_success + : thrd_error; +} + +void cnd_destroy(cnd_t *cond) { + assert(cond); + pthread_cond_destroy(cond); +} + +int cnd_init(cnd_t *cond) { + assert(cond != NULL); + return (pthread_cond_init(cond, NULL) == 0) ? thrd_success + : thrd_error; +} + +int cnd_signal(cnd_t *cond) { + assert(cond != NULL); + return (pthread_cond_signal(cond) == 0) ? thrd_success : thrd_error; +} + +int cnd_timedwait(cnd_t *cond, mtx_t *mtx, + struct timespec const *abs_time) { + int rt; + + assert(mtx != NULL); + assert(cond != NULL); + assert(abs_time != NULL); + + rt = pthread_cond_timedwait(cond, mtx, abs_time); + if (rt == ETIMEDOUT) + return thrd_timedout; + return (rt == 0) ? thrd_success : thrd_error; +} + +int cnd_wait(cnd_t *cond, mtx_t *mtx) { + assert(mtx != NULL); + assert(cond != NULL); + return (pthread_cond_wait(cond, mtx) == 0) ? thrd_success + : thrd_error; +} + +void mtx_destroy(mtx_t *mtx) { + assert(mtx != NULL); + pthread_mutex_destroy(mtx); +} + +/* + * XXX: Workaround when building with -O0 and without pthreads link. + * + * In such cases constant folding and dead code elimination won't be + * available, thus the compiler will always add the pthread_mutexattr* + * functions into the binary. As we try to link, we'll fail as the + * symbols are unresolved. + * + * Ideally we'll enable the optimisations locally, yet that does not + * seem to work. + * + * So the alternative workaround is to annotate the symbols as weak. + * Thus the linker will be happy and things don't clash when building + * with -O1 or greater. + */ +# if defined(KIT_HAVE_FUNC_ATTRIBUTE_WEAK) && !defined(__CYGWIN__) +__attribute__((weak)) int pthread_mutexattr_init( + pthread_mutexattr_t *attr); + +__attribute__((weak)) int pthread_mutexattr_settype( + pthread_mutexattr_t *attr, int type); + +__attribute__((weak)) int pthread_mutexattr_destroy( + pthread_mutexattr_t *attr); +# endif + +int mtx_init(mtx_t *mtx, int type) { +# ifdef KIT_HAVE_PTHREAD_MUTEXATTR_SETTYPE + pthread_mutexattr_t attr; +# endif + assert(mtx != NULL); + if (type != mtx_plain && type != mtx_timed && + type != (mtx_plain | mtx_recursive) && + type != (mtx_timed | mtx_recursive)) + return thrd_error; + + if ((type & mtx_recursive) == 0) { + pthread_mutex_init(mtx, NULL); + return thrd_success; + } + +# ifdef KIT_HAVE_PTHREAD_MUTEXATTR_SETTYPE + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(mtx, &attr); + pthread_mutexattr_destroy(&attr); + return thrd_success; +# else + return thrd_error; +# endif +} + +int mtx_lock(mtx_t *mtx) { + assert(mtx != NULL); + return (pthread_mutex_lock(mtx) == 0) ? thrd_success : thrd_error; +} + +int mtx_timedlock(mtx_t *mtx, const struct timespec *ts) { + assert(mtx != NULL); + assert(ts != NULL); + + { +# ifdef EMULATED_THREADS_USE_NATIVE_TIMEDLOCK + int rt; + rt = pthread_mutex_timedlock(mtx, ts); + if (rt == 0) + return thrd_success; + return (rt == ETIMEDOUT) ? thrd_timedout : thrd_error; +# else + time_t expire = time(NULL); + expire += ts->tv_sec; + while (mtx_trylock(mtx) != thrd_success) { + time_t now = time(NULL); + if (expire < now) + return thrd_timedout; + // busy loop! + thrd_yield(); + } + return thrd_success; +# endif + } +} + +int mtx_trylock(mtx_t *mtx) { + assert(mtx != NULL); + return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy; +} + +int mtx_unlock(mtx_t *mtx) { + assert(mtx != NULL); + return (pthread_mutex_unlock(mtx) == 0) ? thrd_success : thrd_error; +} + +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; + assert(thr != NULL); + assert(require_stack_size == 0 || + require_stack_size >= PTHREAD_STACK_MIN); + pthread_attr_t attr; + pthread_attr_t *attr_p = NULL; + if (require_stack_size > 0) { + ptrdiff_t const page_size = (ptrdiff_t) sysconf(_SC_PAGESIZE); + ptrdiff_t const delta = require_stack_size % page_size; + ptrdiff_t const stack_size = delta == 0 ? require_stack_size + : require_stack_size + + page_size - delta; + if (pthread_attr_init(&attr) != 0) + return thrd_nomem; + if (pthread_attr_setstacksize(&attr, (size_t) stack_size) != 0) + return thrd_wrong_stack_size; + attr_p = &attr; + } + + pack = (impl_thrd_param_t *) kit_alloc_dispatch( + NULL, KIT_ALLOCATE, sizeof(impl_thrd_param_t), 0, NULL); + if (!pack) { + if (attr_p) + pthread_attr_destroy(attr_p); + return thrd_nomem; + } + pack->func = func; + pack->arg = arg; + if (pthread_create(thr, attr_p, impl_thrd_routine, pack) != 0) { + kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, pack); + if (attr_p) + pthread_attr_destroy(attr_p); + return thrd_error; + } + if (attr_p) + pthread_attr_destroy(attr_p); + return thrd_success; +} + +int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { + return thrd_create_with_stack(thr, func, arg, 0); +} +thrd_t thrd_current(void) { + return pthread_self(); +} + +int thrd_detach(thrd_t thr) { + return (pthread_detach(thr) == 0) ? thrd_success : thrd_error; +} + +int thrd_equal(thrd_t thr0, thrd_t thr1) { + return pthread_equal(thr0, thr1); +} + +_Noreturn void thrd_exit(int res) { + pthread_exit((void *) (intptr_t) res); +} + +int thrd_join(thrd_t thr, int *res) { + void *code; + if (pthread_join(thr, &code) != 0) + return thrd_error; + if (res) + *res = (int) (intptr_t) code; + return thrd_success; +} + +int thrd_sleep(const struct timespec *time_point, + struct timespec *remaining) { + assert(time_point != NULL); + return nanosleep(time_point, remaining); +} + +void thrd_yield(void) { + sched_yield(); +} + +# endif +#endif diff --git a/source/kit/threads.win32.c b/source/kit/threads.win32.c new file mode 100644 index 0000000..414f15a --- /dev/null +++ b/source/kit/threads.win32.c @@ -0,0 +1,376 @@ +#include "threads.h" + +#ifndef KIT_DISABLE_SYSTEM_THREADS +# include "allocator.h" + +# if defined(_WIN32) && !defined(__CYGWIN__) +# include +# include +# include +# include +# include + +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# include + +/* +Configuration macro: + + EMULATED_THREADS_USE_NATIVE_CALL_ONCE + Use native WindowsAPI one-time initialization function. + (requires WinVista or later) + Otherwise emulate by mtx_trylock() + *busy loop* for WinXP. + + EMULATED_THREADS_TSS_DTOR_SLOTNUM + Max registerable TSS dtor number. +*/ + +# if _WIN32_WINNT >= 0x0600 +/* 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 */ + +/* check configuration */ +# if defined(EMULATED_THREADS_USE_NATIVE_CALL_ONCE) && \ + (_WIN32_WINNT < 0x0600) +# error EMULATED_THREADS_USE_NATIVE_CALL_ONCE requires _WIN32_WINNT>=0x0600 +# endif + +static_assert(sizeof(cnd_t) == sizeof(CONDITION_VARIABLE), + "The size of cnd_t must equal to CONDITION_VARIABLE"); +static_assert(sizeof(thrd_t) == sizeof(HANDLE), + "The size of thrd_t must equal to HANDLE"); +static_assert(sizeof(tss_t) == sizeof(DWORD), + "The size of tss_t must equal to DWORD"); +static_assert(sizeof(mtx_t) == sizeof(CRITICAL_SECTION), + "The size of mtx_t must equal to CRITICAL_SECTION"); +static_assert(sizeof(once_flag) == sizeof(INIT_ONCE), + "The size of once_flag must equal to INIT_ONCE"); + +/* +Implementation limits: + - Conditionally emulation for "Initialization functions" + (see EMULATED_THREADS_USE_NATIVE_CALL_ONCE macro) + - Emulated `mtx_timelock()' with mtx_trylock() + *busy loop* +*/ + +typedef struct { + thrd_start_t func; + void *arg; + thrd_t thrd; +} impl_thrd_param_t; + +struct thrd_state { + thrd_t thrd; + int handle_need_close; +}; + +static thread_local struct thrd_state impl_current_thread = { 0 }; + +static unsigned __stdcall impl_thrd_routine(void *p) { + impl_thrd_param_t *pack_p = (impl_thrd_param_t *) p; + impl_thrd_param_t pack; + int code; + impl_current_thread.thrd = pack_p->thrd; + impl_current_thread.handle_need_close = 0; + memcpy(&pack, pack_p, sizeof(impl_thrd_param_t)); + kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, p); + code = pack.func(pack.arg); + return (unsigned) code; +} + +static time_t impl_timespec2msec(const struct timespec *ts) { + return (ts->tv_sec * 1000U) + (ts->tv_nsec / 1000000L); +} + +static DWORD impl_abs2relmsec(const struct timespec *abs_time) { + const time_t abs_ms = impl_timespec2msec(abs_time); + struct timespec now; + timespec_get(&now, TIME_UTC); + const time_t now_ms = impl_timespec2msec(&now); + const DWORD rel_ms = (abs_ms > now_ms) ? (DWORD) (abs_ms - now_ms) + : 0; + return rel_ms; +} + +# ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE +struct impl_call_once_param { + void (*func)(void); +}; + +static BOOL CALLBACK impl_call_once_callback(PINIT_ONCE InitOnce, + PVOID Parameter, + PVOID *Context) { + struct impl_call_once_param *param = (struct impl_call_once_param *) + Parameter; + (param->func)(); + ((void) InitOnce); + ((void) Context); /* suppress warning */ + return TRUE; +} +# endif /* ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE */ + +static struct impl_tss_dtor_entry { + tss_t key; + tss_dtor_t dtor; +} impl_tss_dtor_tbl[EMULATED_THREADS_TSS_DTOR_SLOTNUM]; + +static int impl_tss_dtor_register(tss_t key, tss_dtor_t dtor) { + int i; + for (i = 0; i < EMULATED_THREADS_TSS_DTOR_SLOTNUM; i++) { + if (!impl_tss_dtor_tbl[i].dtor) + break; + } + if (i == EMULATED_THREADS_TSS_DTOR_SLOTNUM) + return 1; + impl_tss_dtor_tbl[i].key = key; + impl_tss_dtor_tbl[i].dtor = dtor; + return 0; +} + +static void impl_tss_dtor_invoke(void) { + int i; + for (i = 0; i < EMULATED_THREADS_TSS_DTOR_SLOTNUM; i++) { + if (impl_tss_dtor_tbl[i].dtor) { + void *val = (void *) (size_t) TlsGetValue( + impl_tss_dtor_tbl[i].key); + if (val) + (impl_tss_dtor_tbl[i].dtor)(val); + } + } +} + +void call_once(once_flag *flag, void (*func)(void)) { + assert(flag && func); +# ifdef EMULATED_THREADS_USE_NATIVE_CALL_ONCE + { + struct impl_call_once_param param; + param.func = func; + InitOnceExecuteOnce((PINIT_ONCE) flag, impl_call_once_callback, + (PVOID) ¶m, NULL); + } +# else + if (InterlockedCompareExchangePointer( + (PVOID volatile *) &flag->status, (PVOID) 1, (PVOID) 0) == + 0) { + (func)(); + InterlockedExchangePointer((PVOID volatile *) &flag->status, + (PVOID) 2); + } else { + while (flag->status == 1) { + // busy loop! + thrd_yield(); + } + } +# endif +} + +int cnd_broadcast(cnd_t *cond) { + assert(cond != NULL); + WakeAllConditionVariable((PCONDITION_VARIABLE) cond); + return thrd_success; +} + +void cnd_destroy(cnd_t *cond) { + assert(cond != NULL); + /* do nothing */ + (void) cond; +} + +int cnd_init(cnd_t *cond) { + assert(cond != NULL); + InitializeConditionVariable((PCONDITION_VARIABLE) cond); + return thrd_success; +} + +int cnd_signal(cnd_t *cond) { + assert(cond != NULL); + WakeConditionVariable((PCONDITION_VARIABLE) cond); + return thrd_success; +} + +int cnd_timedwait(cnd_t *cond, mtx_t *mtx, + const struct timespec *abs_time) { + assert(cond != NULL); + assert(mtx != NULL); + assert(abs_time != NULL); + const DWORD timeout = impl_abs2relmsec(abs_time); + if (SleepConditionVariableCS((PCONDITION_VARIABLE) cond, + (PCRITICAL_SECTION) mtx, timeout)) + return thrd_success; + return (GetLastError() == ERROR_TIMEOUT) ? thrd_timedout + : thrd_error; +} + +int cnd_wait(cnd_t *cond, mtx_t *mtx) { + assert(cond != NULL); + assert(mtx != NULL); + SleepConditionVariableCS((PCONDITION_VARIABLE) cond, + (PCRITICAL_SECTION) mtx, INFINITE); + return thrd_success; +} + +void mtx_destroy(mtx_t *mtx) { + assert(mtx); + DeleteCriticalSection((PCRITICAL_SECTION) mtx); +} + +int mtx_init(mtx_t *mtx, int type) { + assert(mtx != NULL); + if (type != mtx_plain && type != mtx_timed && + type != (mtx_plain | mtx_recursive) && + type != (mtx_timed | mtx_recursive)) + return thrd_error; + InitializeCriticalSection((PCRITICAL_SECTION) mtx); + return thrd_success; +} + +int mtx_lock(mtx_t *mtx) { + assert(mtx != NULL); + EnterCriticalSection((PCRITICAL_SECTION) mtx); + return thrd_success; +} + +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! */ + thrd_yield(); + } + return thrd_success; +} + +int mtx_trylock(mtx_t *mtx) { + assert(mtx != NULL); + return TryEnterCriticalSection((PCRITICAL_SECTION) mtx) + ? thrd_success + : thrd_busy; +} + +int mtx_unlock(mtx_t *mtx) { + assert(mtx != NULL); + LeaveCriticalSection((PCRITICAL_SECTION) mtx); + return thrd_success; +} + +int thrd_create_with_stack(thrd_t *thr, thrd_start_t func, void *arg, + ptrdiff_t const stack_size) { + impl_thrd_param_t *pack; + uintptr_t handle; + assert(thr != NULL); + assert(stack_size >= 0 && stack_size < 0x100000000); + + pack = (impl_thrd_param_t *) kit_alloc_dispatch( + NULL, KIT_ALLOCATE, (sizeof(impl_thrd_param_t)), 0, NULL); + if (!pack) + return thrd_nomem; + pack->func = func; + pack->arg = arg; + handle = _beginthreadex(NULL, (unsigned) stack_size, + impl_thrd_routine, pack, CREATE_SUSPENDED, + NULL); + if (handle == 0) { + kit_alloc_dispatch(NULL, KIT_DEALLOCATE, 0, 0, pack); + if (errno == EAGAIN || errno == EACCES) + return thrd_nomem; + return thrd_error; + } + thr->handle = (void *) handle; + pack->thrd = *thr; + ResumeThread((HANDLE) handle); + return thrd_success; +} + +int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { + return thrd_create_with_stack(thr, func, arg, 0); +} + +thrd_t thrd_current(void) { + /* GetCurrentThread() returns a pseudo-handle, which we need + * to pass to DuplicateHandle(). Only the resulting handle can be + * used from other threads. + * + * Note that neither handle can be compared to the one by + * thread_create. Only the thread IDs - as returned by GetThreadId() + * and GetCurrentThreadId() can be compared directly. + * + * Other potential solutions would be: + * - define thrd_t as a thread Ids, but this would mean we'd need to + * OpenThread for many operations + * - use malloc'ed memory for thrd_t. This would imply using TLS for + * current thread. + * + * Neither is particularly nice. + * + * Life would be much easier if C11 threads had different + * abstractions for threads and thread IDs, just like C++11 threads + * does... + */ + struct thrd_state *state = &impl_current_thread; + if (state->thrd.handle == NULL) { + if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &(state->thrd.handle), + 0, FALSE, DUPLICATE_SAME_ACCESS)) { + abort(); + } + state->handle_need_close = 1; + } + return state->thrd; +} + +int thrd_detach(thrd_t thr) { + CloseHandle(thr.handle); + return thrd_success; +} + +int thrd_equal(thrd_t thr0, thrd_t thr1) { + return GetThreadId(thr0.handle) == GetThreadId(thr1.handle); +} + +_Noreturn void thrd_exit(int res) { + _endthreadex((unsigned) res); +} + +int thrd_join(thrd_t thr, int *res) { + DWORD w, code; + if (thr.handle == NULL) { + return thrd_error; + } + w = WaitForSingleObject(thr.handle, INFINITE); + if (w != WAIT_OBJECT_0) + return thrd_error; + if (res) { + if (!GetExitCodeThread(thr.handle, &code)) { + CloseHandle(thr.handle); + return thrd_error; + } + *res = (int) code; + } + CloseHandle(thr.handle); + return thrd_success; +} + +int thrd_sleep(const struct timespec *time_point, + struct timespec *remaining) { + (void) remaining; + assert(time_point); + assert(!remaining); /* not implemented */ + Sleep((DWORD) impl_timespec2msec(time_point)); + return 0; +} + +void thrd_yield(void) { + SwitchToThread(); +} + +# endif +#endif diff --git a/source/kit/time.h b/source/kit/time.h index 01fa239..1b57e08 100644 --- a/source/kit/time.h +++ b/source/kit/time.h @@ -15,7 +15,7 @@ # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN 1 # endif -# include +# include # define KIT_TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS 116444736000000000ull # define KIT_TIMESPEC_IMPL_TICKS_PER_SECONDS 10000000ull diff --git a/source/kit/types.h b/source/kit/types.h index 0251b75..b83ba39 100644 --- a/source/kit/types.h +++ b/source/kit/types.h @@ -1,6 +1,10 @@ #ifndef KIT_TYPES_H #define KIT_TYPES_H +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + typedef signed char i8; typedef signed short i16; typedef signed int i32; diff --git a/source/tests/atomic.test.c b/source/tests/atomic.test.c index efb5a61..061f5d6 100644 --- a/source/tests/atomic.test.c +++ b/source/tests/atomic.test.c @@ -1,5 +1,5 @@ #include "../kit/atomic.h" -#include "../kit/thread.h" +#include "../kit/threads.h" #define KIT_TEST_FILE atomic #include "../kit/kit_test.h" diff --git a/source/tests/bigint.test.c b/source/tests/bigint.test.c index 8efea16..94fd9ef 100644 --- a/source/tests/bigint.test.c +++ b/source/tests/bigint.test.c @@ -4,9 +4,9 @@ #define KIT_TEST_FILE bigint #include "../kit/kit_test.h" -#if __STDC_VERSION__ >= 199901L -static_assert(sizeof(bigint_t) == 256, "KIT_BIGINT_SIZE check"); -#endif +TEST("bigint size check") { + REQUIRE_EQ(sizeof(bigint_t), 256); +} TEST("bigint bin hex") { REQUIRE(bi_equal(HEX("10"), BIN("10000"))); @@ -34,7 +34,7 @@ TEST("bigint hex sub") { } TEST("bigint base58") { - REQUIRE(bi_equal(BASE58("31"), bi_uint32(58 * 2))); + REQUIRE(bi_equal(BASE58("31"), bi_u32(58 * 2))); } TEST("bigint base58 add") { @@ -58,26 +58,26 @@ TEST("bigint base58 mul") { } TEST("bigint div") { - REQUIRE(bi_equal(bi_div(bi_int32(-1), bi_int32(-1)).quotient, - bi_int32(1))); - REQUIRE(bi_equal(bi_div(bi_int32(-1), bi_int32(-1)).remainder, - bi_int32(0))); - REQUIRE(bi_equal(bi_div(bi_int32(-3), bi_int32(2)).quotient, - bi_int32(-2))); - REQUIRE(bi_equal(bi_div(bi_int32(-3), bi_int32(2)).remainder, - bi_int32(1))); - REQUIRE(bi_equal(bi_div(bi_int32(3), bi_int32(-2)).quotient, - bi_int32(-1))); - REQUIRE(bi_equal(bi_div(bi_int32(3), bi_int32(-2)).remainder, - bi_int32(1))); - REQUIRE(bi_equal(bi_div(bi_int32(-3), bi_int32(4)).quotient, - bi_int32(-1))); - REQUIRE(bi_equal(bi_div(bi_int32(-3), bi_int32(4)).remainder, - bi_int32(3))); - REQUIRE(bi_equal(bi_div(bi_int32(3), bi_int32(-4)).quotient, - bi_int32(0))); - REQUIRE(bi_equal(bi_div(bi_int32(3), bi_int32(-4)).remainder, - bi_int32(3))); + REQUIRE( + bi_equal(bi_div(bi_i32(-1), bi_i32(-1)).quotient, bi_i32(1))); + REQUIRE( + bi_equal(bi_div(bi_i32(-1), bi_i32(-1)).remainder, bi_i32(0))); + REQUIRE( + bi_equal(bi_div(bi_i32(-3), bi_i32(2)).quotient, bi_i32(-2))); + REQUIRE( + bi_equal(bi_div(bi_i32(-3), bi_i32(2)).remainder, bi_i32(1))); + REQUIRE( + bi_equal(bi_div(bi_i32(3), bi_i32(-2)).quotient, bi_i32(-1))); + REQUIRE( + bi_equal(bi_div(bi_i32(3), bi_i32(-2)).remainder, bi_i32(1))); + REQUIRE( + bi_equal(bi_div(bi_i32(-3), bi_i32(4)).quotient, bi_i32(-1))); + REQUIRE( + bi_equal(bi_div(bi_i32(-3), bi_i32(4)).remainder, bi_i32(3))); + REQUIRE( + bi_equal(bi_div(bi_i32(3), bi_i32(-4)).quotient, bi_i32(0))); + REQUIRE( + bi_equal(bi_div(bi_i32(3), bi_i32(-4)).remainder, bi_i32(3))); REQUIRE( bi_equal(bi_div(HEX("100"), HEX("10")).quotient, HEX("10"))); diff --git a/source/tests/condition_variable.test.c b/source/tests/condition_variable.test.c index fc2edd4..9deb9ae 100644 --- a/source/tests/condition_variable.test.c +++ b/source/tests/condition_variable.test.c @@ -1,5 +1,4 @@ -#include "../kit/condition_variable.h" -#include "../kit/thread.h" +#include "../kit/threads.h" #define KIT_TEST_FILE condition_variable #include "../kit/kit_test.h" diff --git a/source/tests/file.test.c b/source/tests/file.test.c index 0ca7b91..e6071a1 100644 --- a/source/tests/file.test.c +++ b/source/tests/file.test.c @@ -6,14 +6,14 @@ #include "../kit/kit_test.h" TEST("file path cache") { - string_t user = path_user(NULL); - string_t cache = path_cache(NULL); + str_builder_t user = path_user(NULL); + str_builder_t cache = path_cache(NULL); DA_RESIZE(cache, cache.size + 1); cache.values[cache.size - 1] = '\0'; DA_RESIZE(cache, cache.size - 1); - string_t expected = + str_builder_t expected = #if defined(_WIN32) && !defined(__CYGWIN__) path_join(WRAP_STR(user), SZ("AppData" PATH_DELIM "Local"), NULL); @@ -35,7 +35,7 @@ TEST("file path normalize one") { str_t foo = SZ("foo/bar/../baz"); str_t foo_norm = SZ("foo" PATH_DELIM "baz"); - string_t bar = path_norm(foo, NULL); + str_builder_t bar = path_norm(foo, NULL); REQUIRE(AR_EQUAL(foo_norm, bar)); @@ -46,7 +46,7 @@ TEST("file path normalize two") { str_t foo = SZ("foo/bar/../../baz"); str_t foo_norm = SZ("baz"); - string_t bar = path_norm(foo, NULL); + str_builder_t bar = path_norm(foo, NULL); REQUIRE(AR_EQUAL(foo_norm, bar)); @@ -57,7 +57,7 @@ TEST("file path normalize parent") { str_t foo = SZ("../baz"); str_t foo_norm = SZ(".." PATH_DELIM "baz"); - string_t bar = path_norm(foo, NULL); + str_builder_t bar = path_norm(foo, NULL); REQUIRE(AR_EQUAL(foo_norm, bar)); @@ -68,7 +68,7 @@ TEST("file path normalize double parent") { str_t foo = SZ("foo/../../baz"); str_t foo_norm = SZ(".." PATH_DELIM "baz"); - string_t bar = path_norm(foo, NULL); + str_builder_t bar = path_norm(foo, NULL); REQUIRE(AR_EQUAL(foo_norm, bar)); @@ -79,7 +79,7 @@ TEST("file path normalize windows delim") { str_t foo = SZ("foo\\bar\\..\\baz"); str_t foo_norm = SZ("foo" PATH_DELIM "baz"); - string_t bar = path_norm(foo, NULL); + str_builder_t bar = path_norm(foo, NULL); REQUIRE(AR_EQUAL(foo_norm, bar)); @@ -91,7 +91,7 @@ TEST("file path join no delim") { str_t bar = SZ("bar"); str_t joined = SZ("foo" PATH_DELIM "bar"); - string_t foobar = path_join(foo, bar, NULL); + str_builder_t foobar = path_join(foo, bar, NULL); REQUIRE(AR_EQUAL(joined, foobar)); @@ -103,7 +103,7 @@ TEST("file path join delim left") { str_t bar = SZ("bar"); str_t joined = SZ("foo" PATH_DELIM "bar"); - string_t foobar = path_join(foo, bar, NULL); + str_builder_t foobar = path_join(foo, bar, NULL); REQUIRE(AR_EQUAL(joined, foobar)); @@ -115,7 +115,7 @@ TEST("file path join delim right") { str_t bar = SZ("/bar"); str_t joined = SZ("foo" PATH_DELIM "bar"); - string_t foobar = path_join(foo, bar, NULL); + str_builder_t foobar = path_join(foo, bar, NULL); REQUIRE(AR_EQUAL(joined, foobar)); @@ -127,7 +127,7 @@ TEST("file path join delim both") { str_t bar = SZ("/bar"); str_t joined = SZ("foo" PATH_DELIM "bar"); - string_t foobar = path_join(foo, bar, NULL); + str_builder_t foobar = path_join(foo, bar, NULL); REQUIRE(AR_EQUAL(joined, foobar)); @@ -135,7 +135,7 @@ TEST("file path join delim both") { } TEST("file path user") { - string_t user = path_user(NULL); + str_builder_t user = path_user(NULL); REQUIRE(user.size > 0); diff --git a/source/tests/mutex.test.c b/source/tests/mutex.test.c index 8d52c69..578e48b 100644 --- a/source/tests/mutex.test.c +++ b/source/tests/mutex.test.c @@ -1,5 +1,4 @@ -#include "../kit/mutex.h" -#include "../kit/thread.h" +#include "../kit/threads.h" #define KIT_TEST_FILE mutex #include "../kit/kit_test.h" diff --git a/source/tests/thread.test.c b/source/tests/thread.test.c index 46c9597..8f849cd 100644 --- a/source/tests/thread.test.c +++ b/source/tests/thread.test.c @@ -1,4 +1,4 @@ -#include "../kit/thread.h" +#include "../kit/threads.h" #define KIT_TEST_FILE thread #include "../kit/kit_test.h" -- cgit v1.2.3