Commit | Line | Data |
d55594ae |
1 | #ifndef _WIN32THREAD_H |
2 | #define _WIN32THREAD_H |
3 | typedef struct win32_cond { LONG waiters; HANDLE sem; } perl_cond; |
ea0efc06 |
4 | typedef DWORD perl_key; |
5 | typedef HANDLE perl_thread; |
6 | |
4b026b9e |
7 | #ifndef DONT_USE_CRITICAL_SECTION |
8 | |
9 | /* Critical Sections used instead of mutexes: lightweight, |
ea0efc06 |
10 | * but can't be communicated to child processes, and can't get |
4b026b9e |
11 | * HANDLE to it for use elsewhere. |
ea0efc06 |
12 | */ |
d55594ae |
13 | typedef CRITICAL_SECTION perl_mutex; |
ea0efc06 |
14 | #define MUTEX_INIT(m) InitializeCriticalSection(m) |
15 | #define MUTEX_LOCK(m) EnterCriticalSection(m) |
16 | #define MUTEX_UNLOCK(m) LeaveCriticalSection(m) |
17 | #define MUTEX_DESTROY(m) DeleteCriticalSection(m) |
4b026b9e |
18 | |
d55594ae |
19 | #else |
ea0efc06 |
20 | |
4b026b9e |
21 | typedef HANDLE perl_mutex; |
ea0efc06 |
22 | #define MUTEX_INIT(m) \ |
23 | STMT_START { \ |
24 | if ((*(m) = CreateMutex(NULL,FALSE,NULL)) == NULL) \ |
25 | croak("panic: MUTEX_INIT"); \ |
26 | } STMT_END |
27 | #define MUTEX_LOCK(m) \ |
28 | STMT_START { \ |
29 | if (WaitForSingleObject(*(m),INFINITE) == WAIT_FAILED) \ |
30 | croak("panic: MUTEX_LOCK"); \ |
31 | } STMT_END |
32 | #define MUTEX_UNLOCK(m) \ |
33 | STMT_START { \ |
34 | if (ReleaseMutex(*(m)) == 0) \ |
35 | croak("panic: MUTEX_UNLOCK"); \ |
36 | } STMT_END |
37 | #define MUTEX_DESTROY(m) \ |
38 | STMT_START { \ |
39 | if (CloseHandle(*(m)) == 0) \ |
40 | croak("panic: MUTEX_DESTROY"); \ |
41 | } STMT_END |
42 | |
d55594ae |
43 | #endif |
44 | |
45 | /* These macros assume that the mutex associated with the condition |
46 | * will always be held before COND_{SIGNAL,BROADCAST,WAIT,DESTROY}, |
47 | * so there's no separate mutex protecting access to (c)->waiters |
48 | */ |
ea0efc06 |
49 | #define COND_INIT(c) \ |
4b026b9e |
50 | STMT_START { \ |
51 | (c)->waiters = 0; \ |
52 | (c)->sem = CreateSemaphore(NULL,0,LONG_MAX,NULL); \ |
53 | if ((c)->sem == NULL) \ |
54 | croak("panic: COND_INIT (%ld)",GetLastError()); \ |
ea0efc06 |
55 | } STMT_END |
d55594ae |
56 | |
ea0efc06 |
57 | #define COND_SIGNAL(c) \ |
4b026b9e |
58 | STMT_START { \ |
59 | if ((c)->waiters > 0 && \ |
60 | ReleaseSemaphore((c)->sem,1,NULL) == 0) \ |
61 | croak("panic: COND_SIGNAL (%ld)",GetLastError()); \ |
ea0efc06 |
62 | } STMT_END |
d55594ae |
63 | |
ea0efc06 |
64 | #define COND_BROADCAST(c) \ |
4b026b9e |
65 | STMT_START { \ |
66 | if ((c)->waiters > 0 && \ |
67 | ReleaseSemaphore((c)->sem,(c)->waiters,NULL) == 0) \ |
68 | croak("panic: COND_BROADCAST (%ld)",GetLastError());\ |
ea0efc06 |
69 | } STMT_END |
d55594ae |
70 | |
ea0efc06 |
71 | #define COND_WAIT(c, m) \ |
4b026b9e |
72 | STMT_START { \ |
73 | (c)->waiters++; \ |
74 | MUTEX_UNLOCK(m); \ |
75 | /* Note that there's no race here, since a \ |
76 | * COND_BROADCAST() on another thread will have seen the\ |
77 | * right number of waiters (i.e. including this one) */ \ |
78 | if (WaitForSingleObject((c)->sem,INFINITE)==WAIT_FAILED)\ |
79 | croak("panic: COND_WAIT (%ld)",GetLastError()); \ |
80 | /* XXX there may be an inconsequential race here */ \ |
81 | MUTEX_LOCK(m); \ |
82 | (c)->waiters--; \ |
ea0efc06 |
83 | } STMT_END |
d55594ae |
84 | |
ea0efc06 |
85 | #define COND_DESTROY(c) \ |
4b026b9e |
86 | STMT_START { \ |
87 | (c)->waiters = 0; \ |
88 | if (CloseHandle((c)->sem) == 0) \ |
89 | croak("panic: COND_DESTROY (%ld)",GetLastError()); \ |
ea0efc06 |
90 | } STMT_END |
91 | |
92 | #define DETACH(t) \ |
93 | STMT_START { \ |
46930d8f |
94 | if (CloseHandle((t)->self) == 0) { \ |
ea0efc06 |
95 | MUTEX_UNLOCK(&(t)->mutex); \ |
96 | croak("panic: DETACH"); \ |
97 | } \ |
98 | } STMT_END |
99 | |
100 | #define THR ((struct thread *) TlsGetValue(thr_key)) |
d55594ae |
101 | #define THREAD_CREATE(t, f) Perl_thread_create(t, f) |
102 | #define THREAD_POST_CREATE(t) NOOP |
103 | #define THREAD_RET_TYPE DWORD WINAPI |
104 | #define THREAD_RET_CAST(p) ((DWORD)(p)) |
ea0efc06 |
105 | |
d55594ae |
106 | typedef THREAD_RET_TYPE thread_func_t(void *); |
107 | |
108 | START_EXTERN_C |
109 | void Perl_alloc_thread_key _((void)); |
110 | int Perl_thread_create _((struct thread *thr, thread_func_t *fn)); |
235db74f |
111 | void Perl_set_thread_self _((struct thread *thr)); |
d55594ae |
112 | END_EXTERN_C |
113 | |
114 | #define INIT_THREADS NOOP |
115 | #define ALLOC_THREAD_KEY Perl_alloc_thread_key() |
235db74f |
116 | #define SET_THREAD_SELF(thr) Perl_set_thread_self(thr) |
ea0efc06 |
117 | |
118 | #define JOIN(t, avp) \ |
119 | STMT_START { \ |
46930d8f |
120 | if ((WaitForSingleObject((t)->self,INFINITE) == WAIT_FAILED) \ |
4b026b9e |
121 | || (GetExitCodeThread((t)->self,(LPDWORD)(avp)) == 0)) \ |
ea0efc06 |
122 | croak("panic: JOIN"); \ |
123 | } STMT_END |
124 | |
125 | #define SET_THR(t) \ |
126 | STMT_START { \ |
127 | if (TlsSetValue(thr_key, (void *) (t)) == 0) \ |
128 | croak("panic: TlsSetValue"); \ |
129 | } STMT_END |
130 | |
ea0efc06 |
131 | #define YIELD Sleep(0) |
d55594ae |
132 | |
133 | #endif /* _WIN32THREAD_H */ |