mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* thread.c (rb_thread_polling): check interrupts here.
* thread_win32.ci (w32_wait_events): rename from w32_wait_event(), and now receive multiple event handles. * win32/win32.c (wait_events, rb_w32_main_context): removed. * thread_win32.ci (rb_w32_wait_events): new function. * thread_win32.ci, win32/win32.c (rb_w32_sleep, rb_w32_Sleep): move from win32/win32.c to thread_win32.ci, and use w32_wait_events(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11832 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
bcd3345136
commit
bb022bed3a
5 changed files with 61 additions and 136 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
Fri Feb 23 18:27:17 2007 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* thread.c (rb_thread_polling): check interrupts here.
|
||||
|
||||
* thread_win32.ci (w32_wait_events): rename from w32_wait_event(), and
|
||||
now receive multiple event handles.
|
||||
|
||||
* win32/win32.c (wait_events, rb_w32_main_context): removed.
|
||||
|
||||
* thread_win32.ci (rb_w32_wait_events): new function.
|
||||
|
||||
* thread_win32.ci, win32/win32.c (rb_w32_sleep, rb_w32_Sleep): move
|
||||
from win32/win32.c to thread_win32.ci, and use w32_wait_events().
|
||||
|
||||
Fri Feb 23 18:13:22 2007 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* test/ruby/test_optimization.rb: new test (merges test_opts.rb).
|
||||
|
|
1
thread.c
1
thread.c
|
@ -546,6 +546,7 @@ rb_thread_wait_for(struct timeval time)
|
|||
void
|
||||
rb_thread_polling(void)
|
||||
{
|
||||
RUBY_VM_CHECK_INTS();
|
||||
if (!rb_thread_alone()) {
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
sleep_for_polling(th);
|
||||
|
|
|
@ -67,17 +67,13 @@ w32_reset_event(HANDLE handle)
|
|||
}
|
||||
|
||||
static int
|
||||
w32_wait_event(HANDLE event, DWORD timeout, rb_thread_t *th)
|
||||
w32_wait_events(HANDLE *events, int count, DWORD timeout, rb_thread_t *th)
|
||||
{
|
||||
HANDLE events[2];
|
||||
int count = 0;
|
||||
HANDLE *targets = events;
|
||||
DWORD ret;
|
||||
|
||||
if (event) {
|
||||
events[count++] = event;
|
||||
thread_debug(" * handle: %p (count: %d)\n", event, count);
|
||||
}
|
||||
|
||||
thread_debug(" w32_wait_events events:%p, count:%d, timeout:%ld, th:%p\n",
|
||||
events, count, timeout, th);
|
||||
if (th) {
|
||||
HANDLE intr = th->native_thread_data.interrupt_event;
|
||||
w32_reset_event(intr);
|
||||
|
@ -85,12 +81,15 @@ w32_wait_event(HANDLE event, DWORD timeout, rb_thread_t *th)
|
|||
w32_set_event(intr);
|
||||
}
|
||||
|
||||
events[count++] = intr;
|
||||
targets = ALLOCA_N(HANDLE, count + 1);
|
||||
memcpy(targets, events, sizeof(HANDLE) * count);
|
||||
|
||||
targets[count++] = intr;
|
||||
thread_debug(" * handle: %p (count: %d, intr)\n", intr, count);
|
||||
}
|
||||
|
||||
thread_debug(" WaitForMultipleObjects start (count: %d)\n", count);
|
||||
ret = WaitForMultipleObjects(count, events, FALSE, timeout);
|
||||
ret = WaitForMultipleObjects(count, targets, FALSE, timeout);
|
||||
thread_debug(" WaitForMultipleObjects end (ret: %d)\n", ret);
|
||||
|
||||
if (ret == WAIT_OBJECT_0 + count - 1 && th) {
|
||||
|
@ -101,12 +100,24 @@ w32_wait_event(HANDLE event, DWORD timeout, rb_thread_t *th)
|
|||
DWORD dmy;
|
||||
for (i = 0; i < count; i++) {
|
||||
thread_debug(" * error handle %d - %s\n", i,
|
||||
GetHandleInformation(events[i], &dmy) ? "OK" : "NG");
|
||||
GetHandleInformation(targets[i], &dmy) ? "OK" : "NG");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ubf_handle(rb_thread_t *th);
|
||||
#define ubf_select ubf_handle
|
||||
|
||||
int
|
||||
rb_w32_wait_events(HANDLE *events, int num, DWORD timeout)
|
||||
{
|
||||
int ret;
|
||||
|
||||
BLOCKING_REGION(ret = w32_wait_events(events, num, timeout, GET_THREAD()), ubf_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
w32_close_handle(HANDLE handle)
|
||||
{
|
||||
|
@ -129,8 +140,20 @@ w32_create_thread(DWORD stack_size, void *func, void *val)
|
|||
return (HANDLE)_beginthreadex(0, stack_size, func, val, CREATE_SUSPENDED, 0);
|
||||
}
|
||||
|
||||
static void ubf_handle(rb_thread_t *th);
|
||||
#define ubf_select ubf_handle
|
||||
int
|
||||
rb_w32_sleep(unsigned long msec)
|
||||
{
|
||||
return w32_wait_events(0, 0, msec, GET_THREAD());
|
||||
}
|
||||
|
||||
int WINAPI
|
||||
rb_w32_Sleep(unsigned long msec)
|
||||
{
|
||||
int ret;
|
||||
|
||||
BLOCKING_REGION(ret = rb_w32_sleep(msec), ubf_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
native_sleep(rb_thread_t *th, struct timeval *tv)
|
||||
|
@ -150,7 +173,7 @@ native_sleep(rb_thread_t *th, struct timeval *tv)
|
|||
th->status = THREAD_STOPPED;
|
||||
th->unblock_function = ubf_handle;
|
||||
thread_debug("native_sleep start (%d)\n", (int)msec);
|
||||
ret = w32_wait_event(0, msec, th);
|
||||
ret = w32_wait_events(0, 0, msec, th);
|
||||
thread_debug("native_sleep done (%d)\n", ret);
|
||||
th->unblock_function = 0;
|
||||
th->status = status;
|
||||
|
@ -165,7 +188,7 @@ native_mutex_lock(rb_thread_lock_t *lock)
|
|||
DWORD result;
|
||||
while (1) {
|
||||
thread_debug("native_mutex_lock: %p\n", *lock);
|
||||
result = w32_wait_event(*lock, INFINITE, 0);
|
||||
result = w32_wait_events(&*lock, 1, INFINITE, 0);
|
||||
switch (result) {
|
||||
case WAIT_OBJECT_0:
|
||||
/* get mutex object */
|
||||
|
@ -212,7 +235,7 @@ native_mutex_trylock(rb_thread_lock_t *lock)
|
|||
#if USE_WIN32MUTEX
|
||||
int result;
|
||||
thread_debug("native_mutex_trylock: %p\n", *lock);
|
||||
result = w32_wait_event(*lock, 1, 0);
|
||||
result = w32_wait_events(&*lock, 1, 1, 0);
|
||||
thread_debug("native_mutex_trylock result: %d\n", result);
|
||||
switch (result) {
|
||||
case WAIT_OBJECT_0:
|
||||
|
@ -306,7 +329,7 @@ native_thread_create(rb_thread_t *th)
|
|||
static void
|
||||
native_thread_join(HANDLE th)
|
||||
{
|
||||
w32_wait_event(th, 0, 0);
|
||||
w32_wait_events(&th, 1, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
124
win32/win32.c
124
win32/win32.c
|
@ -82,7 +82,7 @@
|
|||
static struct ChildRecord *CreateChild(const char *, const char *, SECURITY_ATTRIBUTES *, HANDLE, HANDLE, HANDLE);
|
||||
static int has_redirection(const char *);
|
||||
static void StartSockets(void);
|
||||
static DWORD wait_events(HANDLE event, DWORD timeout);
|
||||
int rb_w32_wait_events(HANDLE *events, int num, DWORD timeout);
|
||||
#if !defined(_WIN32_WCE)
|
||||
static int rb_w32_open_osfhandle(long osfhandle, int flags);
|
||||
#else
|
||||
|
@ -231,9 +231,6 @@ static struct {
|
|||
DWORD id;
|
||||
} main_thread;
|
||||
|
||||
/* interrupt stuff */
|
||||
static HANDLE interrupted_event;
|
||||
|
||||
HANDLE
|
||||
GetCurrentThreadHandle(void)
|
||||
{
|
||||
|
@ -2208,9 +2205,6 @@ rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
|
|||
trap = *ex;
|
||||
else
|
||||
trap.fd_count = 0;
|
||||
if (trap.fd_count < FD_SETSIZE)
|
||||
trap.fd_array[trap.fd_count++] = (SOCKET)interrupted_event;
|
||||
// else unable to catch interrupt.
|
||||
ex = &trap;
|
||||
#endif /* USE_INTERRUPT_WINSOCK */
|
||||
|
||||
|
@ -2253,7 +2247,6 @@ rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
|
|||
r = do_select(nfds, rd, wr, ex, timeout);
|
||||
|
||||
#if USE_INTERRUPT_WINSOCK
|
||||
RUBY_CRITICAL(ret = __WSAFDIsSet((SOCKET)interrupted_event, ex));
|
||||
if (ret) {
|
||||
// In this case, we must restore all FDs. But this is only a test
|
||||
// code, so we think about that later.
|
||||
|
@ -2286,9 +2279,6 @@ StartSockets(void)
|
|||
main_thread.handle = GetCurrentThreadHandle();
|
||||
main_thread.id = GetCurrentThreadId();
|
||||
|
||||
interrupted_event = CreateSignal();
|
||||
if (!interrupted_event)
|
||||
rb_fatal("Unable to create interrupt event!\n");
|
||||
NtSocketsInitialized = 1;
|
||||
}
|
||||
|
||||
|
@ -2943,7 +2933,7 @@ waitpid(rb_pid_t pid, int *stat_loc, int options)
|
|||
if (pid == -1) {
|
||||
int count = 0;
|
||||
DWORD ret;
|
||||
HANDLE events[MAXCHILDNUM + 1];
|
||||
HANDLE events[MAXCHILDNUM];
|
||||
|
||||
FOREACH_CHILD(child) {
|
||||
if (!child->pid || child->pid < 0) continue;
|
||||
|
@ -2954,13 +2944,10 @@ waitpid(rb_pid_t pid, int *stat_loc, int options)
|
|||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
events[count] = interrupted_event;
|
||||
|
||||
ret = WaitForMultipleEvents(count + 1, events, FALSE, timeout, TRUE);
|
||||
ret = rb_w32_wait_events(events, count, timeout);
|
||||
if (ret == WAIT_TIMEOUT) return 0;
|
||||
if ((ret -= WAIT_OBJECT_0) == count) {
|
||||
ResetSignal(interrupted_event);
|
||||
errno = EINTR;
|
||||
return -1;
|
||||
}
|
||||
if (ret > count) {
|
||||
|
@ -2979,7 +2966,7 @@ waitpid(rb_pid_t pid, int *stat_loc, int options)
|
|||
|
||||
while (!(pid = poll_child_status(child, stat_loc))) {
|
||||
/* wait... */
|
||||
if (wait_events(child->hProcess, timeout) != WAIT_OBJECT_0) {
|
||||
if (rb_w32_wait_events(&child->hProcess, 1, timeout) != WAIT_OBJECT_0) {
|
||||
/* still active */
|
||||
pid = 0;
|
||||
break;
|
||||
|
@ -3658,28 +3645,6 @@ rb_w32_times(struct tms *tmbuf)
|
|||
#define yield_once() Sleep(0)
|
||||
#define yield_until(condition) do yield_once(); while (!(condition))
|
||||
|
||||
static DWORD
|
||||
wait_events(HANDLE event, DWORD timeout)
|
||||
{
|
||||
HANDLE events[2];
|
||||
int count = 0;
|
||||
DWORD ret;
|
||||
|
||||
if (event) {
|
||||
events[count++] = event;
|
||||
}
|
||||
events[count++] = interrupted_event;
|
||||
|
||||
ret = WaitForMultipleEvents(count, events, FALSE, timeout, TRUE);
|
||||
|
||||
if (ret == WAIT_OBJECT_0 + count - 1) {
|
||||
ResetSignal(interrupted_event);
|
||||
errno = EINTR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static CRITICAL_SECTION *
|
||||
system_state(void)
|
||||
{
|
||||
|
@ -3780,88 +3745,11 @@ setup_call(CONTEXT* ctx, struct handler_arg_t *harg)
|
|||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
rb_w32_main_context(int arg, void (*handler)(int))
|
||||
{
|
||||
static HANDLE interrupt_done = NULL;
|
||||
struct handler_arg_t harg;
|
||||
CONTEXT ctx_orig;
|
||||
HANDLE current_thread = GetCurrentThread();
|
||||
int old_priority = GetThreadPriority(current_thread);
|
||||
|
||||
if (GetCurrentThreadId() == main_thread.id) return FALSE;
|
||||
|
||||
SetSignal(interrupted_event);
|
||||
|
||||
RUBY_CRITICAL({ /* the main thread must be in user state */
|
||||
CONTEXT ctx;
|
||||
|
||||
SuspendThread(main_thread.handle);
|
||||
SetThreadPriority(current_thread, GetThreadPriority(main_thread.handle));
|
||||
|
||||
ZeroMemory(&ctx, sizeof(CONTEXT));
|
||||
ctx.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
|
||||
GetThreadContext(main_thread.handle, &ctx);
|
||||
ctx_orig = ctx;
|
||||
|
||||
/* handler context setup */
|
||||
if (!interrupt_done) {
|
||||
interrupt_done = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
/* anonymous one-shot event */
|
||||
}
|
||||
else {
|
||||
ResetEvent(interrupt_done);
|
||||
}
|
||||
setup_call(&ctx, setup_handler(&harg, arg, handler, interrupt_done));
|
||||
|
||||
ctx.ContextFlags = CONTEXT_CONTROL;
|
||||
SetThreadContext(main_thread.handle, &ctx);
|
||||
ResumeThread(main_thread.handle);
|
||||
});
|
||||
|
||||
/* give a chance to the main thread */
|
||||
yield_once();
|
||||
WaitForSingleObject(interrupt_done, INFINITE); /* handshaking */
|
||||
|
||||
if (!harg.status) {
|
||||
/* no exceptions raised, restore old context. */
|
||||
RUBY_CRITICAL({
|
||||
/* ensure the main thread is in user state. */
|
||||
yield_until(harg.finished);
|
||||
|
||||
SuspendThread(main_thread.handle);
|
||||
ctx_orig.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
|
||||
SetThreadContext(main_thread.handle, &ctx_orig);
|
||||
ResumeThread(main_thread.handle);
|
||||
});
|
||||
}
|
||||
/* otherwise leave the main thread raised */
|
||||
|
||||
SetThreadPriority(current_thread, old_priority);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
rb_w32_sleep(unsigned long msec)
|
||||
{
|
||||
return rb_w32_Sleep(msec);
|
||||
}
|
||||
|
||||
int WINAPI
|
||||
rb_w32_Sleep(unsigned long msec)
|
||||
{
|
||||
DWORD ret;
|
||||
RUBY_CRITICAL(ret = wait_events(NULL, msec));
|
||||
yield_once();
|
||||
return ret != WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
static void
|
||||
catch_interrupt(void)
|
||||
{
|
||||
yield_once();
|
||||
RUBY_CRITICAL(wait_events(NULL, 0));
|
||||
RUBY_CRITICAL(rb_w32_wait_events(NULL, 0, 0));
|
||||
}
|
||||
|
||||
#if defined __BORLANDC__ || defined _WIN32_WCE
|
||||
|
@ -3972,7 +3860,7 @@ rb_w32_asynchronize(asynchronous_func_t func, VALUE self,
|
|||
if (thr) {
|
||||
yield_until(arg.stackaddr);
|
||||
|
||||
if (wait_events(thr, INFINITE) != WAIT_OBJECT_0) {
|
||||
if (rb_w32_wait_events(&thr, 1, INFINITE) != WAIT_OBJECT_0) {
|
||||
interrupted = TRUE;
|
||||
|
||||
if (TerminateThread(thr, intrval)) {
|
||||
|
|
|
@ -510,7 +510,6 @@ int rb_w32_times(struct tms *);
|
|||
|
||||
/* thread stuff */
|
||||
HANDLE GetCurrentThreadHandle(void);
|
||||
int rb_w32_main_context(int arg, void (*handler)(int));
|
||||
int rb_w32_sleep(unsigned long msec);
|
||||
void rb_w32_enter_critical(void);
|
||||
void rb_w32_leave_critical(void);
|
||||
|
|
Loading…
Reference in a new issue