Skip to content

HTTPS clone URL

Subversion checkout URL

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