1 /* thread.h
2  *  Copyright (C) 2001-2003, Parrot Foundation.
3  *  Overview:
4  *     This is the api header for the windows thread primitives
5  *  Data Structure and Algorithms:
6  *  History:
7  *  Notes:
8  *  References:
9  */
10 
11 #ifndef PARROT_THR_WINDOWS_H_GUARD
12 #define PARROT_THR_WINDOWS_H_GUARD
13 
14 #  undef FASTCALL
15 #  define WIN32_LEAN_AND_MEAN
16 #  include <windows.h>
17 #  include <process.h>
18 #  include <limits.h>
19 #  undef CONST
20 
21 typedef CRITICAL_SECTION Parrot_mutex;
22 typedef struct Windows_cond {
23     HANDLE m_hSema;
24     LONG m_lWaiters;
25 } Parrot_cond;
26 typedef HANDLE Parrot_thread;
27 
28 #  define MUTEX_INIT(m) InitializeCriticalSectionAndSpinCount((PCRITICAL_SECTION)&(m), 4000)
29 #  define MUTEX_DESTROY(m) DeleteCriticalSection((PCRITICAL_SECTION)&(m))
30 
31 #  define COND_INIT(c) \
32      do { \
33        (c).m_hSema = CreateSemaphore(NULL, 0, LONG_MAX, NULL); \
34        (c).m_lWaiters = 0; \
35      } while (0)
36 
37 #  define COND_DESTROY(c) CloseHandle((c).m_hSema)
38 
39 #  define LOCK(m) EnterCriticalSection((PCRITICAL_SECTION)&(m))
40 #  define UNLOCK(m) LeaveCriticalSection((PCRITICAL_SECTION)&(m))
41 
42 #  define COND_WAIT(c, m) \
43      do { \
44        ++(c).m_lWaiters; \
45        UNLOCK(m); \
46        WaitForSingleObject((c).m_hSema, INFINITE); \
47        LOCK(m); \
48        --(c).m_lWaiters; \
49      } while (0)
50 
51 #  define COND_TIMED_WAIT(c, m, t, rc) \
52      do { \
53        FLOATVAL now; \
54        time_t sec; \
55        LONG nsec; \
56        DWORD diff; \
57        now = Parrot_floatval_time(); \
58        sec = (time_t)now; \
59        nsec = (LONG)((now - sec)*1000.0f)*1000000L; \
60        if ((t)->tv_sec > sec || ((t)->tv_sec == sec && (t)->tv_nsec > nsec)) \
61        { \
62          ++(c).m_lWaiters; \
63          UNLOCK(m); \
64          diff = (DWORD)(((t)->tv_sec - sec)*1000L + ((t)->tv_nsec - nsec)/1000000L); \
65          (rc) = WaitForSingleObject((c).m_hSema, diff) != WAIT_OBJECT_0; \
66          LOCK(m); \
67          --(c).m_lWaiters; \
68        } \
69        else { \
70          (rc) = 1; \
71        } \
72      } while (0)
73 
74 #  define COND_SIGNAL(c) \
75      do { \
76        if ((c).m_lWaiters > 0) \
77          ReleaseSemaphore((c).m_hSema, 1, NULL); \
78      } while (0)
79 
80 #  define COND_BROADCAST(c) \
81      do { \
82        if ((c).m_lWaiters > 0) \
83          ReleaseSemaphore((c).m_hSema, (c).m_lWaiters, NULL); \
84      } while (0)
85 
86 #  define JOIN(t, ret) \
87      do { \
88        WaitForSingleObject((t), INFINITE); \
89        GetExitCodeThread((t), (LPDWORD)&(ret)); \
90        CloseHandle(t); \
91      } while (0)
92 
93 #  define DETACH(t) CloseHandle(t)
94 
95 /* If the compiler CRT library has a good _beginthreadXX() routine, use it instead of
96    the Win32 API CreateThread(). _beginthreadXX guards call to the thread start routine
97    with SEH to implement runtime errors and signal support. Also it frees calloc-ed
98    per-thread data block at exit */
99 #ifdef _MCS_VER1
100 #  define THREAD_CREATE_JOINABLE(t, func, arg) \
101        do { \
102          unsigned tid; \
103          (t) = (HANDLE)_beginthreadex(NULL, 0, unsigned (__stdcall * (func)) (void*), \
104                                      (void*)(arg), 0, &tid); \
105        } while (0)
106 #else
107 #  define THREAD_CREATE_JOINABLE(t, func, arg) \
108        do { \
109          DWORD tid; \
110          (t) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(func), (PVOID)(arg), 0, &tid); \
111        } while (0)
112 #endif
113 
114 #  define THREAD_CREATE_DETACHED(t, func, arg) \
115      do { \
116        THREAD_CREATE_JOINABLE((t), (func), (arg)); \
117        DETACH(t); \
118      } while (0)
119 
120 #  define CLEANUP_PUSH(f, a)
121 #  define CLEANUP_POP(a)
122 
123 typedef void (*Cleanup_Handler)(void *);
124 
125 #endif /* PARROT_THR_WINDOWS_H_GUARD */
126 
127 /*
128  * Local variables:
129  *   c-file-style: "parrot"
130  * End:
131  * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
132  */
133