Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 684 lines (579 sloc) 14.974 kb
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
1 /* -*-c-*- */
2 /**********************************************************************
3
c334a09 Koichi Sasada * common.mk, *.ci: renamed to *.c.
ko1 authored
4 thread_win32.c -
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
5
6 $Author$
7
d907cbc Koichi Sasada * blockinlining.c, compile.c, compile.h, debug.c, debug.h,
ko1 authored
8 Copyright (C) 2004-2007 Koichi Sasada
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
9
10 **********************************************************************/
11
12 #ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
13
14 #include <process.h>
15
16 #define WIN32_WAIT_TIMEOUT 10 /* 10 ms */
17 #undef Sleep
18
19 #define native_thread_yield() Sleep(0)
ae317b5 Koichi Sasada * yarvcore.h, thread.c: fix to use pthread on cygwin.
ko1 authored
20 #define remove_signal_thread_list(th)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
21
6fc746d Nobuyoshi Nakada * thread.c (is_ruby_native_thread): check properly. [ruby-dev:31166]
nobu authored
22 static volatile DWORD ruby_native_thread_key = TLS_OUT_OF_INDEXES;
23
5f131b6 Nobuyoshi Nakada * thread_win32.c, include/ruby/win32.h: add prototypes.
nobu authored
24 static int w32_wait_events(HANDLE *events, int count, DWORD timeout, rb_thread_t *th);
25 static int native_mutex_lock(rb_thread_lock_t *lock);
26 static int native_mutex_unlock(rb_thread_lock_t *lock);
27
450463d Koichi Sasada * thread.c, vm_core.h: make gvl_acquire/release/init/destruct
ko1 authored
28 static void
29 w32_error(const char *func)
30 {
31 LPVOID lpMsgBuf;
32 DWORD err = GetLastError();
33 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
34 FORMAT_MESSAGE_FROM_SYSTEM |
35 FORMAT_MESSAGE_IGNORE_INSERTS,
36 NULL,
37 err,
38 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
39 (LPTSTR) & lpMsgBuf, 0, NULL) == 0)
40 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
41 FORMAT_MESSAGE_FROM_SYSTEM |
42 FORMAT_MESSAGE_IGNORE_INSERTS,
43 NULL,
44 err,
45 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
46 (LPTSTR) & lpMsgBuf, 0, NULL);
47 rb_bug("%s: %s", func, (char*)lpMsgBuf);
48 }
49
50 static int
51 w32_mutex_lock(HANDLE lock)
52 {
53 DWORD result;
54 while (1) {
55 thread_debug("native_mutex_lock: %p\n", lock);
56 result = w32_wait_events(&lock, 1, INFINITE, 0);
57 switch (result) {
58 case WAIT_OBJECT_0:
59 /* get mutex object */
60 thread_debug("acquire mutex: %p\n", lock);
61 return 0;
62 case WAIT_OBJECT_0 + 1:
63 /* interrupt */
64 errno = EINTR;
65 thread_debug("acquire mutex interrupted: %p\n", lock);
66 return 0;
67 case WAIT_TIMEOUT:
68 thread_debug("timeout mutex: %p\n", lock);
69 break;
70 case WAIT_ABANDONED:
71 rb_bug("win32_mutex_lock: WAIT_ABANDONED");
72 break;
73 default:
f0445d1 Nobuyoshi Nakada * thread_win32.c (gvl_release, gvl_init): suppress warnings.
nobu authored
74 rb_bug("win32_mutex_lock: unknown result (%ld)", result);
450463d Koichi Sasada * thread.c, vm_core.h: make gvl_acquire/release/init/destruct
ko1 authored
75 break;
76 }
77 }
78 return 0;
79 }
80
81 static HANDLE
82 w32_mutex_create(void)
83 {
84 HANDLE lock = CreateMutex(NULL, FALSE, NULL);
85 if (lock == NULL) {
86 w32_error("native_mutex_initialize");
87 }
88 return lock;
89 }
90
91 #define GVL_DEBUG 0
92
93 static void
94 gvl_acquire(rb_vm_t *vm, rb_thread_t *th)
95 {
96 w32_mutex_lock(vm->gvl.lock);
97 if (GVL_DEBUG) fprintf(stderr, "gvl acquire (%p): acquire\n", th);
98 }
99
100 static void
101 gvl_release(rb_vm_t *vm)
102 {
103 ReleaseMutex(vm->gvl.lock);
104 }
105
106 static void
107 gvl_atfork(rb_vm_t *vm)
108 {
109 rb_bug("gvl_atfork() is called on win32");
110 }
111
112 static void
113 gvl_init(rb_vm_t *vm)
114 {
115 if (GVL_DEBUG) fprintf(stderr, "gvl init\n");
116 vm->gvl.lock = w32_mutex_create();
117 }
118
119 static void
120 gvl_destroy(rb_vm_t *vm)
121 {
122 if (GVL_DEBUG) fprintf(stderr, "gvl destroy\n");
123 CloseHandle(vm->gvl.lock);
124 }
125
6fc746d Nobuyoshi Nakada * thread.c (is_ruby_native_thread): check properly. [ruby-dev:31166]
nobu authored
126 static rb_thread_t *
127 ruby_thread_from_native(void)
128 {
129 return TlsGetValue(ruby_native_thread_key);
130 }
131
132 static int
133 ruby_thread_set_native(rb_thread_t *th)
134 {
135 return TlsSetValue(ruby_native_thread_key, th);
136 }
137
f40d2c9 akr * vm.c (Init_BareVM): call Init_native_thread here.
akr authored
138 void
6fc746d Nobuyoshi Nakada * thread.c (is_ruby_native_thread): check properly. [ruby-dev:31166]
nobu authored
139 Init_native_thread(void)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
140 {
9c57438 Koichi Sasada * blockinlining.c, error.c, eval.c, eval_error.h, eval_intern.h,
ko1 authored
141 rb_thread_t *th = GET_THREAD();
6fc746d Nobuyoshi Nakada * thread.c (is_ruby_native_thread): check properly. [ruby-dev:31166]
nobu authored
142
143 ruby_native_thread_key = TlsAlloc();
b451955 unak * thread_win32.c (Init_native_thread): need to call
unak authored
144 ruby_thread_set_native(th);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
145 DuplicateHandle(GetCurrentProcess(),
146 GetCurrentThread(),
147 GetCurrentProcess(),
148 &th->thread_id, 0, FALSE, DUPLICATE_SAME_ACCESS);
149
150 th->native_thread_data.interrupt_event = CreateEvent(0, TRUE, FALSE, 0);
151
152 thread_debug("initial thread (th: %p, thid: %p, event: %p)\n",
153 th, GET_THREAD()->thread_id,
154 th->native_thread_data.interrupt_event);
155 }
156
157 static void
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
158 w32_set_event(HANDLE handle)
159 {
160 if (SetEvent(handle) == 0) {
5bc85d6 unak * thread_win32.c (w32_error): should report the function.
unak authored
161 w32_error("w32_set_event");
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
162 }
163 }
164
165 static void
166 w32_reset_event(HANDLE handle)
167 {
168 if (ResetEvent(handle) == 0) {
5bc85d6 unak * thread_win32.c (w32_error): should report the function.
unak authored
169 w32_error("w32_reset_event");
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
170 }
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
171 }
172
173 static int
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
174 w32_wait_events(HANDLE *events, int count, DWORD timeout, rb_thread_t *th)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
175 {
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
176 HANDLE *targets = events;
00f60d0 unak * thread_win32.ci (w32_wait_events): check whether interrupt_event is
unak authored
177 HANDLE intr;
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
178 DWORD ret;
179
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
180 thread_debug(" w32_wait_events events:%p, count:%d, timeout:%ld, th:%p\n",
181 events, count, timeout, th);
00f60d0 unak * thread_win32.ci (w32_wait_events): check whether interrupt_event is
unak authored
182 if (th && (intr = th->native_thread_data.interrupt_event)) {
450463d Koichi Sasada * thread.c, vm_core.h: make gvl_acquire/release/init/destruct
ko1 authored
183 gvl_acquire(th->vm, th);
bd21118 wanabe * thread_win32.c (w32_wait_events): get GVL before handle interrupt
wanabe authored
184 if (intr == th->native_thread_data.interrupt_event) {
185 w32_reset_event(intr);
186 if (RUBY_VM_INTERRUPTED(th)) {
187 w32_set_event(intr);
188 }
189
190 targets = ALLOCA_N(HANDLE, count + 1);
191 memcpy(targets, events, sizeof(HANDLE) * count);
192
193 targets[count++] = intr;
194 thread_debug(" * handle: %p (count: %d, intr)\n", intr, count);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
195 }
450463d Koichi Sasada * thread.c, vm_core.h: make gvl_acquire/release/init/destruct
ko1 authored
196 gvl_release(th->vm);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
197 }
198
199 thread_debug(" WaitForMultipleObjects start (count: %d)\n", count);
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
200 ret = WaitForMultipleObjects(count, targets, FALSE, timeout);
87e4ad0 Nobuyoshi Nakada * io.c, signal.c, thread.c, thread_win32.c, include/ruby/intern.h:
nobu authored
201 thread_debug(" WaitForMultipleObjects end (ret: %lu)\n", ret);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
202
060f18c wanabe * thread_win32.c (w32_wait_events, w32_close_handle): suppress warnings.
wanabe authored
203 if (ret == (DWORD)(WAIT_OBJECT_0 + count - 1) && th) {
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
204 errno = EINTR;
205 }
060f18c wanabe * thread_win32.c (w32_wait_events, w32_close_handle): suppress warnings.
wanabe authored
206 if (ret == WAIT_FAILED && THREAD_DEBUG) {
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
207 int i;
208 DWORD dmy;
209 for (i = 0; i < count; i++) {
210 thread_debug(" * error handle %d - %s\n", i,
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
211 GetHandleInformation(targets[i], &dmy) ? "OK" : "NG");
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
212 }
213 }
214 return ret;
215 }
216
3453b2b Koichi Sasada * gc.h, vm_core.h: decl of rb_gc_save_machine_context()
ko1 authored
217 static void ubf_handle(void *ptr);
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
218 #define ubf_select ubf_handle
219
220 int
c034fce Nobuyoshi Nakada * process.c (rb_waitpid_blocking, rb_waitpid): use UBF feature.
nobu authored
221 rb_w32_wait_events_blocking(HANDLE *events, int num, DWORD timeout)
222 {
223 return w32_wait_events(events, num, timeout, GET_THREAD());
224 }
225
226 int
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
227 rb_w32_wait_events(HANDLE *events, int num, DWORD timeout)
228 {
229 int ret;
230
3453b2b Koichi Sasada * gc.h, vm_core.h: decl of rb_gc_save_machine_context()
ko1 authored
231 BLOCKING_REGION(ret = rb_w32_wait_events_blocking(events, num, timeout),
4b645dc Yusuke Endoh * thread.c, thread_win32.c, vm_core.h: try to remove false positive of
mame authored
232 ubf_handle, GET_THREAD());
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
233 return ret;
234 }
235
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
236 static void
237 w32_close_handle(HANDLE handle)
238 {
239 if (CloseHandle(handle) == 0) {
5bc85d6 unak * thread_win32.c (w32_error): should report the function.
unak authored
240 w32_error("w32_close_handle");
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
241 }
242 }
243
244 static void
245 w32_resume_thread(HANDLE handle)
246 {
060f18c wanabe * thread_win32.c (w32_wait_events, w32_close_handle): suppress warnings.
wanabe authored
247 if (ResumeThread(handle) == (DWORD)-1) {
5bc85d6 unak * thread_win32.c (w32_error): should report the function.
unak authored
248 w32_error("w32_resume_thread");
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
249 }
250 }
251
2840fa6 Nobuyoshi Nakada * common.mk: inverted rules order.
nobu authored
252 #ifdef _MSC_VER
253 #define HAVE__BEGINTHREADEX 1
254 #else
255 #undef HAVE__BEGINTHREADEX
256 #endif
257
258 #ifdef HAVE__BEGINTHREADEX
259 #define start_thread (HANDLE)_beginthreadex
9e0f3e0 Nobuyoshi Nakada * thread_win32.c (thread_errno): CreateThread does not set errno.
nobu authored
260 #define thread_errno errno
2840fa6 Nobuyoshi Nakada * common.mk: inverted rules order.
nobu authored
261 typedef unsigned long (_stdcall *w32_thread_start_func)(void*);
262 #else
263 #define start_thread CreateThread
9e0f3e0 Nobuyoshi Nakada * thread_win32.c (thread_errno): CreateThread does not set errno.
nobu authored
264 #define thread_errno rb_w32_map_errno(GetLastError())
2840fa6 Nobuyoshi Nakada * common.mk: inverted rules order.
nobu authored
265 typedef LPTHREAD_START_ROUTINE w32_thread_start_func;
266 #endif
267
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
268 static HANDLE
2840fa6 Nobuyoshi Nakada * common.mk: inverted rules order.
nobu authored
269 w32_create_thread(DWORD stack_size, w32_thread_start_func func, void *val)
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
270 {
2840fa6 Nobuyoshi Nakada * common.mk: inverted rules order.
nobu authored
271 return start_thread(0, stack_size, func, val, CREATE_SUSPENDED, 0);
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
272 }
273
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
274 int
275 rb_w32_sleep(unsigned long msec)
276 {
277 return w32_wait_events(0, 0, msec, GET_THREAD());
278 }
279
280 int WINAPI
281 rb_w32_Sleep(unsigned long msec)
282 {
283 int ret;
284
3453b2b Koichi Sasada * gc.h, vm_core.h: decl of rb_gc_save_machine_context()
ko1 authored
285 BLOCKING_REGION(ret = rb_w32_sleep(msec),
4b645dc Yusuke Endoh * thread.c, thread_win32.c, vm_core.h: try to remove false positive of
mame authored
286 ubf_handle, GET_THREAD());
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
287 return ret;
288 }
ae317b5 Koichi Sasada * yarvcore.h, thread.c: fix to use pthread on cygwin.
ko1 authored
289
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
290 static void
47e3f4e Nobuyoshi Nakada * thread.c (thread_start_func_2): wake up joining threads.
nobu authored
291 native_sleep(rb_thread_t *th, struct timeval *tv)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
292 {
a146829 Nobuyoshi Nakada * thread.c (sleep_forever): wait until timed out. [ruby-core:17270]
nobu authored
293 DWORD msec;
4b02286 unak * thread_win32.c (native_sleep): fixed previous commit.
unak authored
294
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
295 if (tv) {
296 msec = tv->tv_sec * 1000 + tv->tv_usec / 1000;
297 }
298 else {
299 msec = INFINITE;
300 }
301
302 GVL_UNLOCK_BEGIN();
303 {
a146829 Nobuyoshi Nakada * thread.c (sleep_forever): wait until timed out. [ruby-core:17270]
nobu authored
304 DWORD ret;
305
8724448 unak * thread_win32.c (native_sleep): must block reentrance when accessing
unak authored
306 native_mutex_lock(&th->interrupt_lock);
1b63d7b Nobuyoshi Nakada * vm_core.h (struct rb_unblock_callback), thread.c
nobu authored
307 th->unblock.func = ubf_handle;
308 th->unblock.arg = th;
8724448 unak * thread_win32.c (native_sleep): must block reentrance when accessing
unak authored
309 native_mutex_unlock(&th->interrupt_lock);
5f0b8af Koichi Sasada * vm_core.h, thread.c, cont.c: add RUBY_VM_SET_INTERRUPT(),
ko1 authored
310
311 if (RUBY_VM_INTERRUPTED(th)) {
312 /* interrupted. return immediate */
313 }
314 else {
87e4ad0 Nobuyoshi Nakada * io.c, signal.c, thread.c, thread_win32.c, include/ruby/intern.h:
nobu authored
315 thread_debug("native_sleep start (%lu)\n", msec);
5f0b8af Koichi Sasada * vm_core.h, thread.c, cont.c: add RUBY_VM_SET_INTERRUPT(),
ko1 authored
316 ret = w32_wait_events(0, 0, msec, th);
87e4ad0 Nobuyoshi Nakada * io.c, signal.c, thread.c, thread_win32.c, include/ruby/intern.h:
nobu authored
317 thread_debug("native_sleep done (%lu)\n", ret);
5f0b8af Koichi Sasada * vm_core.h, thread.c, cont.c: add RUBY_VM_SET_INTERRUPT(),
ko1 authored
318 }
319
8724448 unak * thread_win32.c (native_sleep): must block reentrance when accessing
unak authored
320 native_mutex_lock(&th->interrupt_lock);
1b63d7b Nobuyoshi Nakada * vm_core.h (struct rb_unblock_callback), thread.c
nobu authored
321 th->unblock.func = 0;
322 th->unblock.arg = 0;
8724448 unak * thread_win32.c (native_sleep): must block reentrance when accessing
unak authored
323 native_mutex_unlock(&th->interrupt_lock);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
324 }
325 GVL_UNLOCK_END();
326 }
327
42f0b52 Koichi Sasada * thread_pthread.c, thread_pthread.h, thread_win32.c,
ko1 authored
328 static int
8ee7d07 Koichi Sasada * blockinlining.c, compile.c, compile.h, error.c, eval.c,
ko1 authored
329 native_mutex_lock(rb_thread_lock_t *lock)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
330 {
331 #if USE_WIN32_MUTEX
450463d Koichi Sasada * thread.c, vm_core.h: make gvl_acquire/release/init/destruct
ko1 authored
332 w32_mutex_lock(*lock);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
333 #else
334 EnterCriticalSection(lock);
335 return 0;
336 #endif
337 }
338
42f0b52 Koichi Sasada * thread_pthread.c, thread_pthread.h, thread_win32.c,
ko1 authored
339 static int
8ee7d07 Koichi Sasada * blockinlining.c, compile.c, compile.h, error.c, eval.c,
ko1 authored
340 native_mutex_unlock(rb_thread_lock_t *lock)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
341 {
342 #if USE_WIN32_MUTEX
343 thread_debug("release mutex: %p\n", *lock);
344 return ReleaseMutex(*lock);
345 #else
346 LeaveCriticalSection(lock);
347 return 0;
348 #endif
349 }
350
42f0b52 Koichi Sasada * thread_pthread.c, thread_pthread.h, thread_win32.c,
ko1 authored
351 static int
8ee7d07 Koichi Sasada * blockinlining.c, compile.c, compile.h, error.c, eval.c,
ko1 authored
352 native_mutex_trylock(rb_thread_lock_t *lock)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
353 {
35eb542 Nobuyoshi Nakada * thread_win32.ci: fixed typo.
nobu authored
354 #if USE_WIN32_MUTEX
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
355 int result;
356 thread_debug("native_mutex_trylock: %p\n", *lock);
bb022be unak * thread.c (rb_thread_polling): check interrupts here.
unak authored
357 result = w32_wait_events(&*lock, 1, 1, 0);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
358 thread_debug("native_mutex_trylock result: %d\n", result);
359 switch (result) {
99d65b1 Nobuyoshi Nakada * compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
nobu authored
360 case WAIT_OBJECT_0:
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
361 return 0;
99d65b1 Nobuyoshi Nakada * compile.c, dir.c, eval.c, eval_jump.h, eval_method.h, numeric.c,
nobu authored
362 case WAIT_TIMEOUT:
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
363 return EBUSY;
364 }
365 return EINVAL;
366 #else
367 return TryEnterCriticalSection(lock) == 0;
368 #endif
369 }
370
42f0b52 Koichi Sasada * thread_pthread.c, thread_pthread.h, thread_win32.c,
ko1 authored
371 static void
8ee7d07 Koichi Sasada * blockinlining.c, compile.c, compile.h, error.c, eval.c,
ko1 authored
372 native_mutex_initialize(rb_thread_lock_t *lock)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
373 {
35eb542 Nobuyoshi Nakada * thread_win32.ci: fixed typo.
nobu authored
374 #if USE_WIN32_MUTEX
450463d Koichi Sasada * thread.c, vm_core.h: make gvl_acquire/release/init/destruct
ko1 authored
375 *lock = w32_mutex_create();
205f310 Nobuyoshi Nakada * call_cfunc.ci, compile.c, compile.h, debug.h, eval.c,
nobu authored
376 /* thread_debug("initialize mutex: %p\n", *lock); */
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
377 #else
378 InitializeCriticalSection(lock);
379 #endif
380 }
381
42f0b52 Koichi Sasada * thread_pthread.c, thread_pthread.h, thread_win32.c,
ko1 authored
382 static void
a902624 Koichi Sasada * thread.c, thread_pthread.ci, thread_win32.ci (thread_start_func_1):
ko1 authored
383 native_mutex_destroy(rb_thread_lock_t *lock)
384 {
35eb542 Nobuyoshi Nakada * thread_win32.ci: fixed typo.
nobu authored
385 #if USE_WIN32_MUTEX
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
386 w32_close_handle(lock);
387 #else
388 DeleteCriticalSection(lock);
389 #endif
a902624 Koichi Sasada * thread.c, thread_pthread.ci, thread_win32.ci (thread_start_func_1):
ko1 authored
390 }
391
a73ba1d unak * thread_win32.[ch] (cond_every_entry, rb_thread_cond_struct): reverted
unak authored
392 struct cond_event_entry {
393 struct cond_event_entry* next;
394 HANDLE event;
395 };
396
42f0b52 Koichi Sasada * thread_pthread.c, thread_pthread.h, thread_win32.c,
ko1 authored
397 static void
6244e50 Koichi Sasada * thread.c: fix Mutex to be interruptable lock.
ko1 authored
398 native_cond_signal(rb_thread_cond_t *cond)
399 {
400 /* cond is guarded by mutex */
401 struct cond_event_entry *e = cond->next;
402
403 if (e) {
404 cond->next = e->next;
405 SetEvent(e->event);
406 }
407 else {
408 rb_bug("native_cond_signal: no pending threads");
409 }
410 }
411
42f0b52 Koichi Sasada * thread_pthread.c, thread_pthread.h, thread_win32.c,
ko1 authored
412 static void
6244e50 Koichi Sasada * thread.c: fix Mutex to be interruptable lock.
ko1 authored
413 native_cond_broadcast(rb_thread_cond_t *cond)
414 {
415 /* cond is guarded by mutex */
416 struct cond_event_entry *e = cond->next;
417 cond->next = 0;
418
419 while (e) {
420 SetEvent(e->event);
421 e = e->next;
422 }
423 }
424
b4c5fad kosaki * thread_win32.c (native_cond_timedwait): New. r31373 caused
kosaki authored
425
426 static int
427 __cond_timedwait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex, unsigned long msec)
6244e50 Koichi Sasada * thread.c: fix Mutex to be interruptable lock.
ko1 authored
428 {
429 DWORD r;
430 struct cond_event_entry entry;
431
432 entry.next = 0;
433 entry.event = CreateEvent(0, FALSE, FALSE, 0);
434
435 /* cond is guarded by mutex */
436 if (cond->next) {
437 cond->last->next = &entry;
438 cond->last = &entry;
439 }
440 else {
441 cond->next = &entry;
442 cond->last = &entry;
443 }
444
445 native_mutex_unlock(mutex);
446 {
b4c5fad kosaki * thread_win32.c (native_cond_timedwait): New. r31373 caused
kosaki authored
447 r = WaitForSingleObject(entry.event, msec);
448 if ((r != WAIT_OBJECT_0) && (r != WAIT_TIMEOUT)) {
87e4ad0 Nobuyoshi Nakada * io.c, signal.c, thread.c, thread_win32.c, include/ruby/intern.h:
nobu authored
449 rb_bug("native_cond_wait: WaitForSingleObject returns %lu", r);
6244e50 Koichi Sasada * thread.c: fix Mutex to be interruptable lock.
ko1 authored
450 }
451 }
452 native_mutex_lock(mutex);
453
454 w32_close_handle(entry.event);
b4c5fad kosaki * thread_win32.c (native_cond_timedwait): New. r31373 caused
kosaki authored
455 return (r == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
456 }
457
458 static int
459 native_cond_wait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex)
460 {
461 return __cond_timedwait(cond, mutex, INFINITE);
462 }
463
464 static unsigned long
465 abs_timespec_to_timeout_ms(struct timespec *ts)
466 {
467 struct timeval tv;
468 struct timeval now;
469
470 gettimeofday(&now, NULL);
471 tv.tv_sec = ts->tv_sec;
472 tv.tv_usec = ts->tv_nsec;
473
474 if (!rb_w32_time_subtract(&tv, &now))
475 return 0;
476
477 return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
478 }
479
480 static int
481 native_cond_timedwait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex, struct timespec *ts)
482 {
483 unsigned long timeout_ms;
484
485 timeout_ms = abs_timespec_to_timeout_ms(ts);
486 if (!timeout_ms)
487 return ETIMEDOUT;
488
489 return __cond_timedwait(cond, mutex, timeout_ms);
6244e50 Koichi Sasada * thread.c: fix Mutex to be interruptable lock.
ko1 authored
490 }
491
42f0b52 Koichi Sasada * thread_pthread.c, thread_pthread.h, thread_win32.c,
ko1 authored
492 static void
a1cfaf4 kosaki * thread_pthread.h (rb_thread_cond_t): add clockid field. it's
kosaki authored
493 native_cond_initialize(rb_thread_cond_t *cond, int flags)
6244e50 Koichi Sasada * thread.c: fix Mutex to be interruptable lock.
ko1 authored
494 {
495 cond->next = 0;
496 cond->last = 0;
497 }
498
42f0b52 Koichi Sasada * thread_pthread.c, thread_pthread.h, thread_win32.c,
ko1 authored
499 static void
6244e50 Koichi Sasada * thread.c: fix Mutex to be interruptable lock.
ko1 authored
500 native_cond_destroy(rb_thread_cond_t *cond)
501 {
502 /* */
503 }
a902624 Koichi Sasada * thread.c, thread_pthread.ci, thread_win32.ci (thread_start_func_1):
ko1 authored
504
fc3c60f Nobuyoshi Nakada * gc.h (STACK_UPPER): moved from gc.c
nobu authored
505 void
c7853b4 Nobuyoshi Nakada * eval.c (ruby_cleanup): the order of local variables on stack is
nobu authored
506 ruby_init_stack(volatile VALUE *addr)
fc3c60f Nobuyoshi Nakada * gc.h (STACK_UPPER): moved from gc.c
nobu authored
507 {
508 }
509
510 #define CHECK_ERR(expr) \
511 {if (!(expr)) {rb_bug("err: %lu - %s", GetLastError(), #expr);}}
512
513 static void
514 native_thread_init_stack(rb_thread_t *th)
515 {
516 MEMORY_BASIC_INFORMATION mi;
517 char *base, *end;
518 DWORD size, space;
519
520 CHECK_ERR(VirtualQuery(&mi, &mi, sizeof(mi)));
521 base = mi.AllocationBase;
522 end = mi.BaseAddress;
523 end += mi.RegionSize;
524 size = end - base;
525 space = size / 5;
526 if (space > 1024*1024) space = 1024*1024;
527 th->machine_stack_start = (VALUE *)end - 1;
528 th->machine_stack_maxsize = size - space;
529 }
530
dfc07e8 unak * thread_win32.c (InterlockedExchangePointer): old SDK support.
unak authored
531 #ifndef InterlockedExchangePointer
532 #define InterlockedExchangePointer(t, v) \
533 (void *)InterlockedExchange((long *)(t), (long)(v))
534 #endif
a902624 Koichi Sasada * thread.c, thread_pthread.ci, thread_win32.ci (thread_start_func_1):
ko1 authored
535 static void
536 native_thread_destroy(rb_thread_t *th)
537 {
9f90682 unak * thread_win32.c (native_thread_destroy): decreased the probability of
unak authored
538 HANDLE intr = InterlockedExchangePointer(&th->native_thread_data.interrupt_event, 0);
00f60d0 unak * thread_win32.ci (w32_wait_events): check whether interrupt_event is
unak authored
539 thread_debug("close handle - intr: %p, thid: %p\n", intr, th->thread_id);
540 w32_close_handle(intr);
a902624 Koichi Sasada * thread.c, thread_pthread.ci, thread_win32.ci (thread_start_func_1):
ko1 authored
541 }
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
542
2840fa6 Nobuyoshi Nakada * common.mk: inverted rules order.
nobu authored
543 static unsigned long _stdcall
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
544 thread_start_func_1(void *th_ptr)
545 {
9c57438 Koichi Sasada * blockinlining.c, error.c, eval.c, eval_error.h, eval_intern.h,
ko1 authored
546 rb_thread_t *th = th_ptr;
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
547 volatile HANDLE thread_id = th->thread_id;
548
fc3c60f Nobuyoshi Nakada * gc.h (STACK_UPPER): moved from gc.c
nobu authored
549 native_thread_init_stack(th);
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
550 th->native_thread_data.interrupt_event = CreateEvent(0, TRUE, FALSE, 0);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
551
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
552 /* run */
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
553 thread_debug("thread created (th: %p, thid: %p, event: %p)\n", th,
554 th->thread_id, th->native_thread_data.interrupt_event);
5732566 Nobuyoshi Nakada * thread.c (rb_thread_stop_timer_thread): terminates timer thread
nobu authored
555
df6ea23 Nobuyoshi Nakada * thread_win32.c (thread_start_func_1): use already gotten stack info.
nobu authored
556 thread_start_func_2(th, th->machine_stack_start, rb_ia64_bsp());
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
557
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
558 w32_close_handle(thread_id);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
559 thread_debug("thread deleted (th: %p)\n", th);
560 return 0;
561 }
562
563 static int
9c57438 Koichi Sasada * blockinlining.c, error.c, eval.c, eval_error.h, eval_intern.h,
ko1 authored
564 native_thread_create(rb_thread_t *th)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
565 {
a902624 Koichi Sasada * thread.c, thread_pthread.ci, thread_win32.ci (thread_start_func_1):
ko1 authored
566 size_t stack_size = 4 * 1024; /* 4KB */
567 th->thread_id = w32_create_thread(stack_size, thread_start_func_1, th);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
568
a902624 Koichi Sasada * thread.c, thread_pthread.ci, thread_win32.ci (thread_start_func_1):
ko1 authored
569 if ((th->thread_id) == 0) {
9e0f3e0 Nobuyoshi Nakada * thread_win32.c (thread_errno): CreateThread does not set errno.
nobu authored
570 return thread_errno;
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
571 }
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
572
573 w32_resume_thread(th->thread_id);
574
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
575 if (THREAD_DEBUG) {
576 Sleep(0);
cea3919 Nobuyoshi Nakada * configure.in (RUBY_CHECK_PRINTF_PREFIX): check for printf format
nobu authored
577 thread_debug("create: (th: %p, thid: %p, intr: %p), stack size: %"PRIdSIZE"\n",
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
578 th, th->thread_id,
579 th->native_thread_data.interrupt_event, stack_size);
580 }
581 return 0;
582 }
583
584 static void
84f8da1 Koichi Sasada * thread.c (rb_thread_stop_timer_thread(), rb_thread_reset_timer_thread(...
ko1 authored
585 native_thread_join(HANDLE th)
586 {
6198f53 unak * thread_win32.c (native_thread_join): need to wait thread, of course.
unak authored
587 w32_wait_events(&th, 1, INFINITE, 0);
84f8da1 Koichi Sasada * thread.c (rb_thread_stop_timer_thread(), rb_thread_reset_timer_thread(...
ko1 authored
588 }
589
16612b3 Koichi Sasada * thread.c, vm_core.h: add manual priority support
ko1 authored
590 #if USE_NATIVE_THREAD_PRIORITY
591
84f8da1 Koichi Sasada * thread.c (rb_thread_stop_timer_thread(), rb_thread_reset_timer_thread(...
ko1 authored
592 static void
9c57438 Koichi Sasada * blockinlining.c, error.c, eval.c, eval_error.h, eval_intern.h,
ko1 authored
593 native_thread_apply_priority(rb_thread_t *th)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
594 {
595 int priority = th->priority;
596 if (th->priority > 0) {
597 priority = THREAD_PRIORITY_ABOVE_NORMAL;
598 }
599 else if (th->priority < 0) {
600 priority = THREAD_PRIORITY_BELOW_NORMAL;
601 }
602 else {
603 priority = THREAD_PRIORITY_NORMAL;
604 }
605
606 SetThreadPriority(th->thread_id, priority);
607 }
608
16612b3 Koichi Sasada * thread.c, vm_core.h: add manual priority support
ko1 authored
609 #endif /* USE_NATIVE_THREAD_PRIORITY */
610
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
611 static void
3453b2b Koichi Sasada * gc.h, vm_core.h: decl of rb_gc_save_machine_context()
ko1 authored
612 ubf_handle(void *ptr)
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
613 {
3453b2b Koichi Sasada * gc.h, vm_core.h: decl of rb_gc_save_machine_context()
ko1 authored
614 rb_thread_t *th = (rb_thread_t *)ptr;
ae317b5 Koichi Sasada * yarvcore.h, thread.c: fix to use pthread on cygwin.
ko1 authored
615 thread_debug("ubf_handle: %p\n", th);
25498d2 unak * thread_win32.c (ubf_handle): cancel blocking IO if it can (only
unak authored
616
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
617 w32_set_event(th->native_thread_data.interrupt_event);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
618 }
619
84f8da1 Koichi Sasada * thread.c (rb_thread_stop_timer_thread(), rb_thread_reset_timer_thread(...
ko1 authored
620 static HANDLE timer_thread_id = 0;
5732566 Nobuyoshi Nakada * thread.c (rb_thread_stop_timer_thread): terminates timer thread
nobu authored
621 static HANDLE timer_thread_lock;
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
622
2840fa6 Nobuyoshi Nakada * common.mk: inverted rules order.
nobu authored
623 static unsigned long _stdcall
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
624 timer_thread_func(void *dummy)
625 {
626 thread_debug("timer_thread\n");
5732566 Nobuyoshi Nakada * thread.c (rb_thread_stop_timer_thread): terminates timer thread
nobu authored
627 while (WaitForSingleObject(timer_thread_lock, WIN32_WAIT_TIMEOUT) ==
628 WAIT_TIMEOUT) {
6bbbf98 Nobuyoshi Nakada * thread.c (thread_initialize): NUM2INT() returns int.
nobu authored
629 timer_thread_function(dummy);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
630 }
631 thread_debug("timer killed\n");
632 return 0;
633 }
634
5732566 Nobuyoshi Nakada * thread.c (rb_thread_stop_timer_thread): terminates timer thread
nobu authored
635 static void
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
636 rb_thread_create_timer_thread(void)
637 {
84f8da1 Koichi Sasada * thread.c (rb_thread_stop_timer_thread(), rb_thread_reset_timer_thread(...
ko1 authored
638 if (timer_thread_id == 0) {
5732566 Nobuyoshi Nakada * thread.c (rb_thread_stop_timer_thread): terminates timer thread
nobu authored
639 if (!timer_thread_lock) {
640 timer_thread_lock = CreateEvent(0, TRUE, FALSE, 0);
641 }
a534e39 Nobuyoshi Nakada * thread_{pthread,win32}.c (rb_thread_create_timer_thread): needs more
nobu authored
642 timer_thread_id = w32_create_thread(1024 + (THREAD_DEBUG ? BUFSIZ : 0),
5732566 Nobuyoshi Nakada * thread.c (rb_thread_stop_timer_thread): terminates timer thread
nobu authored
643 timer_thread_func, 0);
a5abb1c Koichi Sasada * thread_win32.ci (w32_show_error_message): renamed to w32_error.
ko1 authored
644 w32_resume_thread(timer_thread_id);
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
645 }
646 }
647
641f43d Nobuyoshi Nakada * thread_pthread.c (thread_timer): checks working flags again.
nobu authored
648 static int
649 native_stop_timer_thread(void)
650 {
651 int stopped = --system_working <= 0;
652 if (stopped) {
9ee5e61 unak * thread_{pthread,win32}.c (native_stop_timer_thread): join the thread
unak authored
653 SetEvent(timer_thread_lock);
654 native_thread_join(timer_thread_id);
641f43d Nobuyoshi Nakada * thread_pthread.c (thread_timer): checks working flags again.
nobu authored
655 CloseHandle(timer_thread_lock);
656 timer_thread_lock = 0;
657 }
658 return stopped;
659 }
5732566 Nobuyoshi Nakada * thread.c (rb_thread_stop_timer_thread): terminates timer thread
nobu authored
660
9ee5e61 unak * thread_{pthread,win32}.c (native_stop_timer_thread): join the thread
unak authored
661 static void
662 native_reset_timer_thread(void)
663 {
664 if (timer_thread_id) {
665 CloseHandle(timer_thread_id);
666 timer_thread_id = 0;
667 }
668 }
669
767d708 Nobuyoshi Nakada * Makefile.in (ASFLAGS): needs INCFLAGS.
nobu authored
670 #ifdef RUBY_ALLOCA_CHKSTK
671 void
672 ruby_alloca_chkstk(size_t len, void *sp)
673 {
674 if (ruby_stack_length(NULL) * sizeof(VALUE) >= len) {
675 rb_thread_t *th = GET_THREAD();
676 if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW)) {
677 rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
678 rb_exc_raise(sysstack_error);
679 }
680 }
681 }
682 #endif
a3e1b1c Koichi Sasada * Merge YARV
ko1 authored
683 #endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */
Something went wrong with that request. Please try again.