1 /* 2 * C11 <threads.h> emulation library 3 * 4 * (C) Copyright yohhoy 2012. 5 * Copyright 2022 Yonggang Luo 6 * Distributed under the Boost Software License, Version 1.0. 7 * 8 * Permission is hereby granted, free of charge, to any person or organization 9 * obtaining a copy of the software and accompanying documentation covered by 10 * this license (the "Software") to use, reproduce, display, distribute, 11 * execute, and transmit the Software, and to prepare [[derivative work]]s of the 12 * Software, and to permit third-parties to whom the Software is furnished to 13 * do so, all subject to the following: 14 * 15 * The copyright notices in the Software and this entire statement, including 16 * the above license grant, this restriction and the following disclaimer, 17 * must be included in all copies of the Software, in whole or in part, and 18 * all derivative works of the Software, unless such copies or derivative 19 * works are solely in the form of machine-executable object code generated by 20 * a source language processor. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 25 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 26 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 * DEALINGS IN THE SOFTWARE. 29 */ 30 31 #ifndef C11_THREADS_H_INCLUDED_ 32 #define C11_THREADS_H_INCLUDED_ 33 34 #include "c11/time.h" 35 36 #include <errno.h> 37 #include <limits.h> 38 #include <stdlib.h> 39 40 #if defined(_WIN32) && !defined(HAVE_PTHREAD) 41 # include <io.h> /* close */ 42 # include <process.h> /* _exit */ 43 #elif defined(HAVE_PTHREAD) 44 # include <pthread.h> 45 # include <unistd.h> /* close, _exit */ 46 #else 47 # error Not supported on this platform. 48 #endif 49 50 #if defined(HAVE_THRD_CREATE) 51 #include <threads.h> 52 #else 53 54 /*---------------------------- macros ---------------------------*/ 55 56 #ifndef _Thread_local 57 # if defined(__cplusplus) 58 /* C++11 doesn't need `_Thread_local` keyword or macro */ 59 # elif !defined(__STDC_NO_THREADS__) 60 /* threads are optional in C11, _Thread_local present in this condition */ 61 # elif defined(_MSC_VER) 62 # define _Thread_local __declspec(thread) 63 # elif defined(__GNUC__) 64 # define _Thread_local __thread 65 # else 66 /* Leave _Thread_local undefined so that use of _Thread_local would not promote 67 * to a non-thread-local global variable 68 */ 69 # endif 70 #endif 71 72 #if !defined(__cplusplus) 73 /* 74 * C11 thread_local() macro 75 * C++11 and above already have thread_local keyword 76 */ 77 # ifndef thread_local 78 # define thread_local _Thread_local 79 # endif 80 #endif 81 82 #ifdef __cplusplus 83 extern "C" { 84 #endif 85 86 /*---------------------------- types ----------------------------*/ 87 typedef void (*tss_dtor_t)(void *); 88 typedef int (*thrd_start_t)(void *); 89 90 #if defined(_WIN32) && !defined(HAVE_PTHREAD) 91 typedef struct 92 { 93 void *Ptr; 94 } cnd_t; 95 /* Define thrd_t as struct type intentionally for avoid use of thrd_t as pointer type */ 96 typedef struct 97 { 98 void *handle; 99 } thrd_t; 100 typedef unsigned long tss_t; 101 typedef struct 102 { 103 void *DebugInfo; 104 long LockCount; 105 long RecursionCount; 106 void *OwningThread; 107 void *LockSemaphore; 108 uintptr_t SpinCount; 109 } mtx_t; /* Mock of CRITICAL_SECTION */ 110 typedef struct 111 { 112 volatile uintptr_t status; 113 } once_flag; 114 # define ONCE_FLAG_INIT {0} 115 # define TSS_DTOR_ITERATIONS 1 116 #elif defined(HAVE_PTHREAD) 117 typedef pthread_cond_t cnd_t; 118 typedef pthread_t thrd_t; 119 typedef pthread_key_t tss_t; 120 typedef pthread_mutex_t mtx_t; 121 typedef pthread_once_t once_flag; 122 # define ONCE_FLAG_INIT PTHREAD_ONCE_INIT 123 # ifdef PTHREAD_DESTRUCTOR_ITERATIONS 124 # define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS 125 # else 126 # define TSS_DTOR_ITERATIONS 1 // assume TSS dtor MAY be called at least once. 127 # endif 128 #else 129 # error Not supported on this platform. 130 #endif 131 132 /*-------------------- enumeration constants --------------------*/ 133 enum 134 { 135 mtx_plain = 0x1, 136 mtx_recursive = 0x2, 137 mtx_timed = 0x4, 138 }; 139 140 enum 141 { 142 thrd_success = 0, // succeeded 143 thrd_timedout, // timed out 144 thrd_error, // failed 145 thrd_busy, // resource busy 146 thrd_nomem // out of memory 147 }; 148 149 /*-------------------------- functions --------------------------*/ 150 151 void call_once(once_flag *, void (*)(void)); 152 int cnd_broadcast(cnd_t *); 153 void cnd_destroy(cnd_t *); 154 int cnd_init(cnd_t *); 155 int cnd_signal(cnd_t *); 156 int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict __mtx, 157 const struct timespec *__restrict); 158 int cnd_wait(cnd_t *, mtx_t *__mtx); 159 void mtx_destroy(mtx_t *__mtx); 160 int mtx_init(mtx_t *__mtx, int); 161 int mtx_lock(mtx_t *__mtx); 162 int mtx_timedlock(mtx_t *__restrict __mtx, 163 const struct timespec *__restrict); 164 int mtx_trylock(mtx_t *__mtx); 165 int mtx_unlock(mtx_t *__mtx); 166 int thrd_create(thrd_t *, thrd_start_t, void *); 167 thrd_t thrd_current(void); 168 int thrd_detach(thrd_t); 169 int thrd_equal(thrd_t, thrd_t); 170 #if defined(__cplusplus) 171 [[ noreturn ]] 172 #else 173 _Noreturn 174 #endif 175 void thrd_exit(int); 176 int thrd_join(thrd_t, int *); 177 int thrd_sleep(const struct timespec *, struct timespec *); 178 void thrd_yield(void); 179 int tss_create(tss_t *, tss_dtor_t); 180 void tss_delete(tss_t); 181 void *tss_get(tss_t); 182 int tss_set(tss_t, void *); 183 184 #ifdef __cplusplus 185 } 186 #endif 187 188 #endif /* HAVE_THRD_CREATE */ 189 190 #endif /* C11_THREADS_H_INCLUDED_ */ 191