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