matz
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@981 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
25aa3816b1
commit
6f36fedaa4
@ -14,8 +14,13 @@
|
|||||||
#define SIG_H
|
#define SIG_H
|
||||||
|
|
||||||
EXTERN int rb_trap_immediate;
|
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_BEG (rb_trap_immediate=1)
|
||||||
#define TRAP_END (rb_trap_immediate=0)
|
#define TRAP_END (rb_trap_immediate=0)
|
||||||
|
#endif
|
||||||
|
|
||||||
EXTERN int rb_prohibit_interrupt;
|
EXTERN int rb_prohibit_interrupt;
|
||||||
#define DEFER_INTS {rb_prohibit_interrupt++;}
|
#define DEFER_INTS {rb_prohibit_interrupt++;}
|
||||||
|
@ -46,8 +46,8 @@ def philosopher(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i in 0..N-1
|
for n in 0..N-1
|
||||||
Thread.start{philosopher(i)}
|
Thread.start(n){|i| philosopher(i)}
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
9
signal.c
9
signal.c
@ -341,6 +341,14 @@ static RETSIGTYPE
|
|||||||
sighandle(sig)
|
sighandle(sig)
|
||||||
int 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) {
|
if (sig >= NSIG) {
|
||||||
rb_bug("trap_handler: Bad signal %d", sig);
|
rb_bug("trap_handler: Bad signal %d", sig);
|
||||||
}
|
}
|
||||||
@ -358,6 +366,7 @@ sighandle(sig)
|
|||||||
rb_trap_pending++;
|
rb_trap_pending++;
|
||||||
trap_pending_list[sig]++;
|
trap_pending_list[sig]++;
|
||||||
}
|
}
|
||||||
|
end_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SIGBUS
|
#ifdef SIGBUS
|
||||||
|
126
win32/win32.c
126
win32/win32.c
@ -75,6 +75,22 @@ IsWinNT(void) {
|
|||||||
return (IdOS() == VER_PLATFORM_WIN32_NT);
|
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 */
|
/* simulate flock by locking a range on the file */
|
||||||
|
|
||||||
@ -160,7 +176,8 @@ flock(int fd, int oper)
|
|||||||
// Initialization stuff
|
// Initialization stuff
|
||||||
//
|
//
|
||||||
void
|
void
|
||||||
NtInitialize(int *argc, char ***argv) {
|
NtInitialize(int *argc, char ***argv)
|
||||||
|
{
|
||||||
|
|
||||||
WORD version;
|
WORD version;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1215,7 +1232,7 @@ NtMakeCmdVector (char *cmdline, char ***vec, int InputCmd)
|
|||||||
//
|
//
|
||||||
|
|
||||||
DIR *
|
DIR *
|
||||||
opendir(const char *filename)
|
opendir(char *filename)
|
||||||
{
|
{
|
||||||
DIR *p;
|
DIR *p;
|
||||||
long len;
|
long len;
|
||||||
@ -1887,6 +1904,7 @@ myselect (int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
|
|||||||
long r;
|
long r;
|
||||||
fd_set file_rd;
|
fd_set file_rd;
|
||||||
fd_set file_wr;
|
fd_set file_wr;
|
||||||
|
fd_set trap;
|
||||||
int file_nfds;
|
int file_nfds;
|
||||||
int trap_immediate = rb_trap_immediate;
|
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;
|
if (wr) *wr = file_wr;
|
||||||
return file_nfds;
|
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)
|
if (trap_immediate)
|
||||||
TRAP_END;
|
TRAP_END;
|
||||||
if ((r = select (nfds, rd, wr, ex, timeout)) == SOCKET_ERROR) {
|
if ((r = select (nfds, rd, wr, &trap, timeout)) == SOCKET_ERROR) {
|
||||||
errno = WSAGetLastError();
|
errno = WSAGetLastError();
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case WSAEINTR:
|
case WSAEINTR:
|
||||||
@ -1923,7 +1948,8 @@ myselect (int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
StartSockets () {
|
StartSockets ()
|
||||||
|
{
|
||||||
WORD version;
|
WORD version;
|
||||||
WSADATA retdata;
|
WSADATA retdata;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1950,6 +1976,11 @@ StartSockets () {
|
|||||||
*/
|
*/
|
||||||
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
|
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
|
||||||
(char *)&iSockOpt, sizeof(iSockOpt));
|
(char *)&iSockOpt, sizeof(iSockOpt));
|
||||||
|
|
||||||
|
rb_CurrentProcessHandle = GetCurrentProcess();
|
||||||
|
rb_MainThreadHandle = GetCurrentThreadHandle();
|
||||||
|
rb_MainThreadId = GetCurrentThreadId();
|
||||||
|
rb_InterruptEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef accept
|
#undef accept
|
||||||
@ -2513,3 +2544,90 @@ mytimes(struct tms *tmbuf)
|
|||||||
}
|
}
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
@ -143,7 +143,7 @@ extern "C++" {
|
|||||||
#define execvp _execvp
|
#define execvp _execvp
|
||||||
#define execvpe _execvpe
|
#define execvpe _execvpe
|
||||||
#define getpid _getpid
|
#define getpid _getpid
|
||||||
#define sleep(x) Sleep((x)*1000)
|
#define sleep(x) win32_sleep((x)*1000)
|
||||||
#define spawnl _spawnl
|
#define spawnl _spawnl
|
||||||
#define spawnle _spawnle
|
#define spawnle _spawnle
|
||||||
#define spawnlp _spawnlp
|
#define spawnlp _spawnlp
|
||||||
@ -426,4 +426,18 @@ struct tms {
|
|||||||
#endif
|
#endif
|
||||||
#define times mytimes
|
#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
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user