1 /* FTHREADS.H (c) Copyright "Fish" (David B. Trout), 2001-2012 */ 2 /* Fish's WIN32 version of pthreads */ 3 4 //////////////////////////////////////////////////////////////////////////////////// 5 // (c) Copyright "Fish" (David B. Trout), 2001-2009. Released under the Q Public License 6 // (http://www.hercules-390.org/herclic.html) as modifications to Hercules. 7 //////////////////////////////////////////////////////////////////////////////////// 8 9 #ifndef _FTHREADS_H_ 10 #define _FTHREADS_H_ 11 12 #include "hercules.h" 13 14 #ifndef _FTHREADS_C_ 15 #ifndef _HUTIL_DLL_ 16 #define FT_DLL_IMPORT DLL_IMPORT 17 #else /* _HUTIL_DLL_ */ 18 #define FT_DLL_IMPORT extern 19 #endif /* _HUTIL_DLL_ */ 20 #else 21 #define FT_DLL_IMPORT DLL_EXPORT 22 #endif 23 24 //////////////////////////////////////////////////////////////////////////////////// 25 // Just a handy macro to have around... 26 27 #define RC(rc) (rc) 28 29 //////////////////////////////////////////////////////////////////////////////////// 30 31 #define MyInitializeCriticalSection(pCS) (InitializeCriticalSectionAndSpinCount((CRITICAL_SECTION*)(pCS),3000)) 32 #define MyEnterCriticalSection(pCS) (EnterCriticalSection((CRITICAL_SECTION*)(pCS))) 33 #define MyTryEnterCriticalSection(pCS) (TryEnterCriticalSection((CRITICAL_SECTION*)(pCS))) 34 #define MyLeaveCriticalSection(pCS) (LeaveCriticalSection((CRITICAL_SECTION*)(pCS))) 35 #define MyDeleteCriticalSection(pCS) (DeleteCriticalSection((CRITICAL_SECTION*)(pCS))) 36 37 #ifdef _MSVC_ 38 #define MyCreateThread(sec,stack,start,parm,flags,tid) ((HANDLE) _beginthreadex((sec),(unsigned)(stack),(start),(parm),(flags),(tid))) 39 #define MyExitThread(code) (_endthreadex((code))) 40 #else // (Cygwin) 41 #define MyCreateThread(sec,stack,start,parm,flags,tid) (CreateThread((sec),(stack),(start),(parm),(flags),(tid))) 42 #define MyExitThread(code) (ExitThread((code))) 43 #endif // _MSVC_ 44 45 #define MyCreateEvent(sec,man,set,name) (CreateEvent((sec),(man),(set),(name))) 46 #define MySetEvent(h) (SetEvent((h))) 47 #define MyResetEvent(h) (ResetEvent((h))) 48 #define MyDeleteEvent(h) (CloseHandle((h))) 49 #define MyCloseHandle(h) (CloseHandle((h))) 50 51 #define MyWaitForSingleObject(h,millisecs) (WaitForSingleObject((h),(millisecs))) 52 53 //////////////////////////////////////////////////////////////////////////////////// 54 // (need struct timespec for fthread_cond_timedwait) 55 56 #if !defined(TIMESPEC_IN_SYS_TYPES_H) && !defined(TIMESPEC_IN_TIME_H) && (_MSC_VER < 1900) 57 // Avoid double definition for VS2015 as it defines timespec in ...\ucrt\time.h(39) 58 // (need to define it ourselves) 59 struct timespec 60 { 61 time_t tv_sec; // (seconds) 62 long tv_nsec; // (nanoseconds) 63 }; 64 #endif 65 66 //////////////////////////////////////////////////////////////////////////////////// 67 // fthread typedefs... 68 69 typedef void* FT_W32_HANDLE; // HANDLE 70 typedef unsigned long FT_W32_DWORD; // DWORD 71 72 typedef FT_W32_DWORD fthread_t; // thread id 73 typedef FT_W32_DWORD fthread_mutexattr_t; // mutex attribute 74 75 typedef void* (FT_THREAD_FUNC)(void*); // thread function 76 typedef FT_THREAD_FUNC* PFT_THREAD_FUNC; // thread function ptr 77 78 typedef struct _tagFTU_MUTEX // fthread "mutex" structure 79 { 80 FT_W32_DWORD dwMutexMagic; // (magic number) 81 FT_W32_HANDLE hMutex; // (ptr to actual mutex structure) 82 } 83 fthread_mutex_t; 84 85 typedef struct _tagFTU_COND // fthread "condition variable" structure 86 { 87 FT_W32_DWORD dwCondMagic; // (magic number) 88 FT_W32_HANDLE hCondVar; // (ptr to actual condition variable structure) 89 } 90 fthread_cond_t; 91 92 typedef struct _tagFTU_ATTR // fthread "thread attribute" structure 93 { 94 FT_W32_DWORD dwAttrMagic; // (magic number) 95 size_t nStackSize; // (initial stack size in bytes) 96 int nDetachState; // (requested detach state: detached/joinable) 97 } 98 fthread_attr_t; 99 100 //////////////////////////////////////////////////////////////////////////////////// 101 // fthread thread attribute types... 102 103 #define FTHREAD_CREATE_JOINABLE 0x4A6F696E // "Join" in ASCII 104 #define FTHREAD_CREATE_DETACHED 0x44697363 // "Disc" in ASCII 105 #define FTHREAD_CREATE_DEFAULT FTHREAD_CREATE_JOINABLE 106 107 //////////////////////////////////////////////////////////////////////////////////// 108 // Initialize a "thread attribute"... 109 110 FT_DLL_IMPORT 111 int fthread_attr_init 112 ( 113 fthread_attr_t* pThreadAttr 114 ); 115 116 //////////////////////////////////////////////////////////////////////////////////// 117 // Destroy a "thread attribute"... 118 119 FT_DLL_IMPORT 120 int fthread_attr_destroy 121 ( 122 fthread_attr_t* pThreadAttr 123 ); 124 125 //////////////////////////////////////////////////////////////////////////////////// 126 // Set a thread's "detachstate" attribute... 127 128 FT_DLL_IMPORT 129 int fthread_attr_setdetachstate 130 ( 131 fthread_attr_t* pThreadAttr, 132 int nDetachState 133 ); 134 135 //////////////////////////////////////////////////////////////////////////////////// 136 // Retrieve a thread's "detachstate" attribute... 137 138 FT_DLL_IMPORT 139 int fthread_attr_getdetachstate 140 ( 141 const fthread_attr_t* pThreadAttr, 142 int* pnDetachState 143 ); 144 145 //////////////////////////////////////////////////////////////////////////////////// 146 // Set a thread's initial stack size... 147 148 FT_DLL_IMPORT 149 int fthread_attr_setstacksize 150 ( 151 fthread_attr_t* pThreadAttr, 152 size_t nStackSize 153 ); 154 155 //////////////////////////////////////////////////////////////////////////////////// 156 // Retrieve a thread's initial stack size... 157 158 FT_DLL_IMPORT 159 int fthread_attr_getstacksize 160 ( 161 const fthread_attr_t* pThreadAttr, 162 size_t* pnStackSize 163 ); 164 165 //////////////////////////////////////////////////////////////////////////////////// 166 // Join a thread (i.e. wait for a thread's termination)... 167 168 FT_DLL_IMPORT 169 int fthread_join 170 ( 171 fthread_t dwThreadID, 172 void** pExitVal 173 ); 174 175 //////////////////////////////////////////////////////////////////////////////////// 176 // Detach a thread (i.e. ignore a thread's termination)... 177 178 FT_DLL_IMPORT 179 int fthread_detach 180 ( 181 fthread_t dwThreadID 182 ); 183 184 //////////////////////////////////////////////////////////////////////////////////// 185 // Create a new thread... 186 187 FT_DLL_IMPORT 188 int fthread_create 189 ( 190 fthread_t* pdwThreadID, 191 fthread_attr_t* pThreadAttr, 192 PFT_THREAD_FUNC pfnThreadFunc, 193 void* pvThreadArgs, 194 char* pszThreadName 195 ); 196 197 //////////////////////////////////////////////////////////////////////////////////// 198 // Exit from a thread... 199 200 FT_DLL_IMPORT 201 void fthread_exit 202 ( 203 void* ExitVal 204 ); 205 206 //////////////////////////////////////////////////////////////////////////////////// 207 // Return thread-id... 208 209 FT_DLL_IMPORT 210 fthread_t fthread_self 211 ( 212 ); 213 214 //////////////////////////////////////////////////////////////////////////////////// 215 // Compare thread-ids... 216 217 FT_DLL_IMPORT 218 int fthread_equal 219 ( 220 fthread_t pdwThreadID_1, 221 fthread_t pdwThreadID_2 222 ); 223 224 //////////////////////////////////////////////////////////////////////////////////// 225 // (thread signalling not [currently] supported (yet); always returns ENOTSUP...) 226 227 FT_DLL_IMPORT 228 int fthread_kill // FIXME: TODO: 229 ( 230 int dummy1, 231 int dummy2 232 ); 233 234 //////////////////////////////////////////////////////////////////////////////////// 235 // Initialize a "mutex"... 236 237 FT_DLL_IMPORT 238 int fthread_mutex_init 239 ( 240 fthread_mutex_t* pFT_MUTEX, 241 const fthread_mutexattr_t* pFT_MUTEX_ATTR 242 ); 243 244 //////////////////////////////////////////////////////////////////////////////////// 245 // Destroy a "mutex"... 246 247 FT_DLL_IMPORT 248 int fthread_mutex_destroy 249 ( 250 fthread_mutex_t* pFT_MUTEX 251 ); 252 253 //////////////////////////////////////////////////////////////////////////////////// 254 // Lock a "mutex"... 255 256 FT_DLL_IMPORT 257 int fthread_mutex_lock 258 ( 259 fthread_mutex_t* pFT_MUTEX 260 ); 261 262 //////////////////////////////////////////////////////////////////////////////////// 263 // Try to lock a "mutex"... 264 265 FT_DLL_IMPORT 266 int fthread_mutex_trylock 267 ( 268 fthread_mutex_t* pFT_MUTEX 269 ); 270 271 //////////////////////////////////////////////////////////////////////////////////// 272 // Unlock a "mutex"... 273 274 FT_DLL_IMPORT 275 int fthread_mutex_unlock 276 ( 277 fthread_mutex_t* pFT_MUTEX 278 ); 279 280 //////////////////////////////////////////////////////////////////////////////////// 281 // Initialize a "condition"... 282 283 FT_DLL_IMPORT 284 int fthread_cond_init 285 ( 286 fthread_cond_t* pFT_COND_VAR 287 ); 288 289 //////////////////////////////////////////////////////////////////////////////////// 290 // Destroy a "condition"... 291 292 FT_DLL_IMPORT 293 int fthread_cond_destroy 294 ( 295 fthread_cond_t* pFT_COND_VAR 296 ); 297 298 //////////////////////////////////////////////////////////////////////////////////// 299 // 'Signal' a "condition"... (causes ONE waiting thread to be released) 300 301 FT_DLL_IMPORT 302 int fthread_cond_signal 303 ( 304 fthread_cond_t* pFT_COND_VAR 305 ); 306 307 //////////////////////////////////////////////////////////////////////////////////// 308 // 'Broadcast' a "condition"... (causes ALL waiting threads to be released) 309 310 FT_DLL_IMPORT 311 int fthread_cond_broadcast 312 ( 313 fthread_cond_t* pFT_COND_VAR 314 ); 315 316 //////////////////////////////////////////////////////////////////////////////////// 317 // Wait for a "condition" to occur... 318 319 FT_DLL_IMPORT 320 int fthread_cond_wait 321 ( 322 fthread_cond_t* pFT_COND_VAR, 323 fthread_mutex_t* pFT_MUTEX 324 ); 325 326 //////////////////////////////////////////////////////////////////////////////////// 327 // Wait (but not forever) for a "condition" to occur... 328 329 FT_DLL_IMPORT 330 int fthread_cond_timedwait 331 ( 332 fthread_cond_t* pFT_COND_VAR, 333 fthread_mutex_t* pFT_MUTEX, 334 struct timespec* pTimeTimeout 335 ); 336 337 //////////////////////////////////////////////////////////////////////////////////// 338 // fthread mutex attribute types... 339 // 340 // FTHREAD_MUTEX_NORMAL This type of mutex does not detect deadlock. A thread 341 // attempting to relock this mutex without first unlocking 342 // it shall deadlock. Attempting to unlock a mutex locked 343 // by a different thread results in undefined behavior. 344 // Attempting to unlock an unlocked mutex results in 345 // undefined behavior. The FTHREAD_MUTEX_NORMAL mutex type 346 // is not currently supported by fthreads. 347 // 348 // FTHREAD_MUTEX_ERRORCHECK This type of mutex provides error checking. A thread 349 // attempting to relock this mutex without first unlocking 350 // it shall return with an error. A thread attempting to 351 // unlock a mutex which another thread has locked shall 352 // return with an error. A thread attempting to unlock an 353 // unlocked mutex shall return with an error. 354 // 355 // FTHREAD_MUTEX_RECURSIVE A thread attempting to relock this mutex without first 356 // unlocking it shall succeed in locking the mutex. The 357 // relocking deadlock which can occur with mutexes of type 358 // FTHREAD_MUTEX_NORMAL cannot occur with this type of mutex. 359 // Multiple locks of this mutex shall require the same number 360 // of unlocks to release the mutex before another thread 361 // can acquire the mutex. A thread attempting to unlock a 362 // mutex which another thread has locked shall return with 363 // an error. A thread attempting to unlock an unlocked mutex 364 // shall return with an error. 365 // 366 // FTHREAD_MUTEX_DEFAULT Attempting to recursively lock a mutex of this type results 367 // in undefined behavior. Attempting to unlock a mutex of this 368 // type which was not locked by the calling thread results 369 // in undefined behavior. Attempting to unlock a mutex of this 370 // type which is not locked results in undefined behavior. 371 // An implementation may map this mutex to one of the other 372 // mutex types. 373 374 #define FTHREAD_MUTEX_ERRORCHECK 0x4F6E6365 // "Once" in ASCII 375 #define FTHREAD_MUTEX_RECURSIVE 0x4D616E79 // "Many" in ASCII 376 #define FTHREAD_MUTEX_DEFAULT FTHREAD_MUTEX_ERRORCHECK 377 378 //////////////////////////////////////////////////////////////////////////////////// 379 // Initialize a "mutex" attribute... 380 381 FT_DLL_IMPORT 382 int fthread_mutexattr_init 383 ( 384 fthread_mutexattr_t* pFT_MUTEX_ATTR 385 ); 386 387 //////////////////////////////////////////////////////////////////////////////////// 388 // Destroy a "mutex" attribute... 389 390 FT_DLL_IMPORT 391 int fthread_mutexattr_destroy 392 ( 393 fthread_mutexattr_t* pFT_MUTEX_ATTR 394 ); 395 396 //////////////////////////////////////////////////////////////////////////////////// 397 // Retrieve "mutex" attribute type... 398 399 FT_DLL_IMPORT 400 int fthread_mutexattr_gettype 401 ( 402 const fthread_mutexattr_t* pFT_MUTEX_ATTR, 403 int* pnMutexType 404 ); 405 406 //////////////////////////////////////////////////////////////////////////////////// 407 // Set "mutex" attribute type... 408 409 FT_DLL_IMPORT 410 int fthread_mutexattr_settype 411 ( 412 fthread_mutexattr_t* pFT_MUTEX_ATTR, 413 int nMutexType 414 ); 415 416 //////////////////////////////////////////////////////////////////////////////////// 417 418 #endif // _FTHREADS_H_ 419