From 6f36fedaa4788cfa956764d5b7e63fc67b444400 Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 27 Sep 2000 09:11:13 +0000 Subject: matz git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@981 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- rubysig.h | 5 +++ sample/philos.rb | 4 +- signal.c | 9 ++++ win32/win32.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- win32/win32.h | 16 ++++++- 5 files changed, 153 insertions(+), 7 deletions(-) diff --git a/rubysig.h b/rubysig.h index dec1fa1842..a837c017b2 100644 --- a/rubysig.h +++ b/rubysig.h @@ -14,8 +14,13 @@ #define SIG_H EXTERN int rb_trap_immediate; +#ifdef NT +#define TRAP_BEG (rb_trap_immediate=1, SetEvent(rb_InterruptEvent)) +#define TRAP_END (rb_trap_immediate=0, ResetEvent(rb_InterruptEvent)) +#else #define TRAP_BEG (rb_trap_immediate=1) #define TRAP_END (rb_trap_immediate=0) +#endif EXTERN int rb_prohibit_interrupt; #define DEFER_INTS {rb_prohibit_interrupt++;} diff --git a/sample/philos.rb b/sample/philos.rb index 3ccb052532..119e7c36b9 100644 --- a/sample/philos.rb +++ b/sample/philos.rb @@ -46,8 +46,8 @@ def philosopher(n) end end -for i in 0..N-1 - Thread.start{philosopher(i)} +for n in 0..N-1 + Thread.start(n){|i| philosopher(i)} sleep 0.1 end diff --git a/signal.c b/signal.c index f98a0b3d79..b5ed58ec75 100644 --- a/signal.c +++ b/signal.c @@ -341,6 +341,14 @@ static RETSIGTYPE sighandle(sig) int sig; { +#ifdef NT +#define end_interrupt() win32_thread_resume_main() + if (win32_main_context(sig, sighandle)) return; + +#else +#define end_interrupt() (void)0 +#endif + if (sig >= NSIG) { rb_bug("trap_handler: Bad signal %d", sig); } @@ -358,6 +366,7 @@ sighandle(sig) rb_trap_pending++; trap_pending_list[sig]++; } + end_interrupt(); } #ifdef SIGBUS diff --git a/win32/win32.c b/win32/win32.c index 1311b7e198..49b781f677 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -75,6 +75,22 @@ IsWinNT(void) { return (IdOS() == VER_PLATFORM_WIN32_NT); } +/* main thread constants */ +HANDLE rb_CurrentProcessHandle; +HANDLE rb_MainThreadHandle; +DWORD rb_MainThreadId; +HANDLE rb_InterruptEvent; + +HANDLE GetCurrentThreadHandle(void) +{ + HANDLE h; + HANDLE proc = rb_CurrentProcessHandle; + + if (!DuplicateHandle(proc, GetCurrentThread(), proc, &h, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + return NULL; + return h; +} /* simulate flock by locking a range on the file */ @@ -160,7 +176,8 @@ flock(int fd, int oper) // Initialization stuff // void -NtInitialize(int *argc, char ***argv) { +NtInitialize(int *argc, char ***argv) +{ WORD version; int ret; @@ -1215,7 +1232,7 @@ NtMakeCmdVector (char *cmdline, char ***vec, int InputCmd) // DIR * -opendir(const char *filename) +opendir(char *filename) { DIR *p; long len; @@ -1887,6 +1904,7 @@ myselect (int nfds, fd_set *rd, fd_set *wr, fd_set *ex, long r; fd_set file_rd; fd_set file_wr; + fd_set trap; int file_nfds; int trap_immediate = rb_trap_immediate; @@ -1907,9 +1925,16 @@ myselect (int nfds, fd_set *rd, fd_set *wr, fd_set *ex, if (wr) *wr = file_wr; return file_nfds; } + if (ex) + trap = *ex; + else + trap.fd_count = 0; + if (trap.fd_count < FD_SETSIZE) + trap.fd_array[trap.fd_count++] = rb_InterruptEvent; + // else unable to catch interrupt. if (trap_immediate) TRAP_END; - if ((r = select (nfds, rd, wr, ex, timeout)) == SOCKET_ERROR) { + if ((r = select (nfds, rd, wr, &trap, timeout)) == SOCKET_ERROR) { errno = WSAGetLastError(); switch (errno) { case WSAEINTR: @@ -1923,7 +1948,8 @@ myselect (int nfds, fd_set *rd, fd_set *wr, fd_set *ex, } static void -StartSockets () { +StartSockets () +{ WORD version; WSADATA retdata; int ret; @@ -1950,6 +1976,11 @@ StartSockets () { */ setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&iSockOpt, sizeof(iSockOpt)); + + rb_CurrentProcessHandle = GetCurrentProcess(); + rb_MainThreadHandle = GetCurrentThreadHandle(); + rb_MainThreadId = GetCurrentThreadId(); + rb_InterruptEvent = CreateEvent(NULL, FALSE, TRUE, NULL); } #undef accept @@ -2513,3 +2544,90 @@ mytimes(struct tms *tmbuf) } return 0; } + + +static int win32_thread_exclusive(void) +{ + if (GetCurrentThreadId() == rb_MainThreadId) return FALSE; + + SuspendThread(rb_MainThreadHandle); + return TRUE; +} + +void win32_thread_resume_main(void) +{ + if (GetCurrentThreadId() != rb_MainThreadId) + ResumeThread(rb_MainThreadHandle); +} + +static void win32_suspend_self(void) +{ + SuspendThread(GetCurrentThread()); +} + +static void win32_call_handler(int arg, void (*handler)(int), CONTEXT ctx) +{ + handler(arg); + ctx.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT; + SetThreadContext(rb_MainThreadHandle, &ctx); +} + +static int catch_interrupt(unsigned long msec) +{ + return !WaitForSingleObject(rb_InterruptEvent, msec); +} + +int win32_interruptible(void) +{ + if (catch_interrupt(0)) return TRUE; + SetEvent(rb_InterruptEvent); + return FALSE; +} + +int win32_main_context(int arg, void (*handler)(int)) +{ + if (!win32_thread_exclusive()) return FALSE; + + if (!catch_interrupt(0)) { + SetEvent(rb_InterruptEvent); + return FALSE; + } + + { + CONTEXT ctx; + + ZeroMemory(&ctx, sizeof(CONTEXT)); + ctx.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT; + GetThreadContext(rb_MainThreadHandle, &ctx); +#ifdef _M_IX86 + { + DWORD *esp = (DWORD *)(ctx.Esp - sizeof(CONTEXT)); + *(CONTEXT *)esp = ctx; + *--esp = (DWORD)handler; + *--esp = arg; + *--esp = ctx.Eip; + ctx.Esp = (DWORD)esp; + } + ctx.Eip = (DWORD)win32_call_handler; +#else +#error +#endif + + ctx.ContextFlags = CONTEXT_CONTROL; + SetThreadContext(rb_MainThreadHandle, &ctx); + } + ResumeThread(rb_MainThreadHandle); + + return TRUE; +} + +void win32_sleep(unsigned long msec) +{ + int trap_immediate = rb_trap_immediate; + + if (trap_immediate) + TRAP_END; + catch_interrupt(msec); + if (trap_immediate) + TRAP_BEG; +} diff --git a/win32/win32.h b/win32/win32.h index 0435e0cb97..d0e18152e5 100644 --- a/win32/win32.h +++ b/win32/win32.h @@ -143,7 +143,7 @@ extern "C++" { #define execvp _execvp #define execvpe _execvpe #define getpid _getpid -#define sleep(x) Sleep((x)*1000) +#define sleep(x) win32_sleep((x)*1000) #define spawnl _spawnl #define spawnle _spawnle #define spawnlp _spawnlp @@ -426,4 +426,18 @@ struct tms { #endif #define times mytimes +/* thread stuff */ +/* initialized by NtInitialize() */ +HANDLE rb_CurrentProcessHandle; +HANDLE rb_MainThreadHandle; +HANDLE rb_InterruptEvent; +DWORD rb_MainThreadId; + +HANDLE GetCurrentThreadHandle(void); +int win32_main_context(int arg, void (*handler)(int)); +int win32_interruptible(void); +void win32_thread_resume_main(void); +void win32_sleep(unsigned long msec); +#define Sleep(msec) win32_sleep(msec) + #endif -- cgit v1.2.3