mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
matz
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1039 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
e9cf3b3bf5
commit
46620a8772
12 changed files with 510 additions and 204 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
Mon Nov 13 22:44:52 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
|
* error.c (rb_bug): print version to stderr.
|
||||||
|
|
||||||
Mon Nov 13 19:02:08 2000 WATANABE Hirofumi <eban@ruby-lang.org>
|
Mon Nov 13 19:02:08 2000 WATANABE Hirofumi <eban@ruby-lang.org>
|
||||||
|
|
||||||
* win32/win32.c, io.c, process.c: the exit status of program must be
|
* win32/win32.c, io.c, process.c: the exit status of program must be
|
||||||
|
|
|
@ -245,7 +245,7 @@ dir.@OBJEXT@: dir.c ruby.h config.h defines.h intern.h
|
||||||
dln.@OBJEXT@: dln.c config.h defines.h dln.h
|
dln.@OBJEXT@: dln.c config.h defines.h dln.h
|
||||||
dmyext.@OBJEXT@: dmyext.c
|
dmyext.@OBJEXT@: dmyext.c
|
||||||
enum.@OBJEXT@: enum.c ruby.h config.h defines.h intern.h
|
enum.@OBJEXT@: enum.c ruby.h config.h defines.h intern.h
|
||||||
error.@OBJEXT@: error.c ruby.h config.h defines.h intern.h env.h
|
error.@OBJEXT@: error.c ruby.h config.h defines.h intern.h env.h version.h
|
||||||
eval.@OBJEXT@: eval.c ruby.h config.h defines.h intern.h node.h env.h rubysig.h st.h dln.h
|
eval.@OBJEXT@: eval.c ruby.h config.h defines.h intern.h node.h env.h rubysig.h st.h dln.h
|
||||||
file.@OBJEXT@: file.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h
|
file.@OBJEXT@: file.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h
|
||||||
gc.@OBJEXT@: gc.c ruby.h config.h defines.h intern.h rubysig.h st.h node.h env.h re.h regex.h
|
gc.@OBJEXT@: gc.c ruby.h config.h defines.h intern.h rubysig.h st.h node.h env.h re.h regex.h
|
||||||
|
|
4
error.c
4
error.c
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include "ruby.h"
|
#include "ruby.h"
|
||||||
#include "env.h"
|
#include "env.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#ifdef HAVE_STDARG_PROTOTYPES
|
#ifdef HAVE_STDARG_PROTOTYPES
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -172,7 +174,7 @@ rb_bug(fmt, va_alist)
|
||||||
va_init_list(args, fmt);
|
va_init_list(args, fmt);
|
||||||
warn_print(buf, args);
|
warn_print(buf, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
ruby_show_version();
|
fprintf(stderr, "ruby %s (%s) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
47
gc.c
47
gc.c
|
@ -74,10 +74,10 @@ ruby_xmalloc(size)
|
||||||
if (malloc_memories > GC_MALLOC_LIMIT) {
|
if (malloc_memories > GC_MALLOC_LIMIT) {
|
||||||
rb_gc();
|
rb_gc();
|
||||||
}
|
}
|
||||||
mem = malloc(size);
|
RUBY_CRITICAL(mem = malloc(size));
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
rb_gc();
|
rb_gc();
|
||||||
mem = malloc(size);
|
RUBY_CRITICAL(mem = malloc(size));
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
if (size >= 10 * 1024 * 1024) {
|
if (size >= 10 * 1024 * 1024) {
|
||||||
rb_raise(rb_eNoMemError, "tried to allocate too big memory");
|
rb_raise(rb_eNoMemError, "tried to allocate too big memory");
|
||||||
|
@ -114,10 +114,10 @@ ruby_xrealloc(ptr, size)
|
||||||
if (!ptr) return xmalloc(size);
|
if (!ptr) return xmalloc(size);
|
||||||
if (size == 0) size = 1;
|
if (size == 0) size = 1;
|
||||||
malloc_memories += size;
|
malloc_memories += size;
|
||||||
mem = realloc(ptr, size);
|
RUBY_CRITICAL(mem = realloc(ptr, size));
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
rb_gc();
|
rb_gc();
|
||||||
mem = realloc(ptr, size);
|
RUBY_CRITICAL(mem = realloc(ptr, size));
|
||||||
if (!mem)
|
if (!mem)
|
||||||
if (size >= 50 * 1024 * 1024) {
|
if (size >= 50 * 1024 * 1024) {
|
||||||
rb_raise(rb_eNoMemError, "tried to re-allocate too big memory");
|
rb_raise(rb_eNoMemError, "tried to re-allocate too big memory");
|
||||||
|
@ -132,7 +132,8 @@ void
|
||||||
ruby_xfree(x)
|
ruby_xfree(x)
|
||||||
void *x;
|
void *x;
|
||||||
{
|
{
|
||||||
if (x) free(x);
|
if (x)
|
||||||
|
RUBY_CRITICAL(free(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int ruby_in_compile;
|
extern int ruby_in_compile;
|
||||||
|
@ -186,7 +187,7 @@ rb_gc_unregister_address(addr)
|
||||||
|
|
||||||
if (tmp->varptr == addr) {
|
if (tmp->varptr == addr) {
|
||||||
Global_List = tmp->next;
|
Global_List = tmp->next;
|
||||||
free(tmp);
|
RUBY_CRITICAL(free(tmp));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (tmp->next) {
|
while (tmp->next) {
|
||||||
|
@ -194,7 +195,7 @@ rb_gc_unregister_address(addr)
|
||||||
struct gc_list *t = tmp->next;
|
struct gc_list *t = tmp->next;
|
||||||
|
|
||||||
tmp->next = tmp->next->next;
|
tmp->next = tmp->next->next;
|
||||||
free(t);
|
RUBY_CRITICAL(free(t));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
|
@ -253,13 +254,13 @@ add_heap()
|
||||||
if (heaps_used == heaps_length) {
|
if (heaps_used == heaps_length) {
|
||||||
/* Realloc heaps */
|
/* Realloc heaps */
|
||||||
heaps_length += HEAPS_INCREMENT;
|
heaps_length += HEAPS_INCREMENT;
|
||||||
heaps = (heaps_used>0)?
|
RUBY_CRITICAL(heaps = (heaps_used>0)?
|
||||||
(RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE*)):
|
(RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE*)):
|
||||||
(RVALUE**)malloc(heaps_length*sizeof(RVALUE*));
|
(RVALUE**)malloc(heaps_length*sizeof(RVALUE*)));
|
||||||
if (heaps == 0) mem_error("heaps: can't alloc memory");
|
if (heaps == 0) mem_error("heaps: can't alloc memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
p = heaps[heaps_used++] = (RVALUE*)malloc(sizeof(RVALUE)*HEAP_SLOTS);
|
RUBY_CRITICAL(p = heaps[heaps_used++] = (RVALUE*)malloc(sizeof(RVALUE)*HEAP_SLOTS));
|
||||||
if (p == 0) mem_error("add_heap: can't alloc memory");
|
if (p == 0) mem_error("add_heap: can't alloc memory");
|
||||||
pend = p + HEAP_SLOTS;
|
pend = p + HEAP_SLOTS;
|
||||||
if (lomem == 0 || lomem > p) lomem = p;
|
if (lomem == 0 || lomem > p) lomem = p;
|
||||||
|
@ -754,12 +755,12 @@ obj_free(obj)
|
||||||
case T_STRING:
|
case T_STRING:
|
||||||
#define STR_NO_ORIG FL_USER2 /* copied from string.c */
|
#define STR_NO_ORIG FL_USER2 /* copied from string.c */
|
||||||
if (!RANY(obj)->as.string.orig || FL_TEST(obj, STR_NO_ORIG)) {
|
if (!RANY(obj)->as.string.orig || FL_TEST(obj, STR_NO_ORIG)) {
|
||||||
free(RANY(obj)->as.string.ptr);
|
RUBY_CRITICAL(free(RANY(obj)->as.string.ptr));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_ARRAY:
|
case T_ARRAY:
|
||||||
if (RANY(obj)->as.array.ptr) {
|
if (RANY(obj)->as.array.ptr) {
|
||||||
free(RANY(obj)->as.array.ptr);
|
RUBY_CRITICAL(free(RANY(obj)->as.array.ptr));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_HASH:
|
case T_HASH:
|
||||||
|
@ -772,13 +773,13 @@ obj_free(obj)
|
||||||
re_free_pattern(RANY(obj)->as.regexp.ptr);
|
re_free_pattern(RANY(obj)->as.regexp.ptr);
|
||||||
}
|
}
|
||||||
if (RANY(obj)->as.regexp.str) {
|
if (RANY(obj)->as.regexp.str) {
|
||||||
free(RANY(obj)->as.regexp.str);
|
RUBY_CRITICAL(free(RANY(obj)->as.regexp.str));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_DATA:
|
case T_DATA:
|
||||||
if (DATA_PTR(obj)) {
|
if (DATA_PTR(obj)) {
|
||||||
if ((long)RANY(obj)->as.data.dfree == -1) {
|
if ((long)RANY(obj)->as.data.dfree == -1) {
|
||||||
free(DATA_PTR(obj));
|
RUBY_CRITICAL(free(DATA_PTR(obj)));
|
||||||
}
|
}
|
||||||
else if (RANY(obj)->as.data.dfree) {
|
else if (RANY(obj)->as.data.dfree) {
|
||||||
(*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
|
(*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
|
||||||
|
@ -788,13 +789,13 @@ obj_free(obj)
|
||||||
case T_MATCH:
|
case T_MATCH:
|
||||||
if (RANY(obj)->as.match.regs) {
|
if (RANY(obj)->as.match.regs) {
|
||||||
re_free_registers(RANY(obj)->as.match.regs);
|
re_free_registers(RANY(obj)->as.match.regs);
|
||||||
free(RANY(obj)->as.match.regs);
|
RUBY_CRITICAL(free(RANY(obj)->as.match.regs));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_FILE:
|
case T_FILE:
|
||||||
if (RANY(obj)->as.file.fptr) {
|
if (RANY(obj)->as.file.fptr) {
|
||||||
rb_io_fptr_finalize(RANY(obj)->as.file.fptr);
|
rb_io_fptr_finalize(RANY(obj)->as.file.fptr);
|
||||||
free(RANY(obj)->as.file.fptr);
|
RUBY_CRITICAL(free(RANY(obj)->as.file.fptr));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_ICLASS:
|
case T_ICLASS:
|
||||||
|
@ -807,19 +808,19 @@ obj_free(obj)
|
||||||
|
|
||||||
case T_BIGNUM:
|
case T_BIGNUM:
|
||||||
if (RANY(obj)->as.bignum.digits) {
|
if (RANY(obj)->as.bignum.digits) {
|
||||||
free(RANY(obj)->as.bignum.digits);
|
RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_NODE:
|
case T_NODE:
|
||||||
switch (nd_type(obj)) {
|
switch (nd_type(obj)) {
|
||||||
case NODE_SCOPE:
|
case NODE_SCOPE:
|
||||||
if (RANY(obj)->as.node.u1.tbl) {
|
if (RANY(obj)->as.node.u1.tbl) {
|
||||||
free(RANY(obj)->as.node.u1.tbl);
|
RUBY_CRITICAL(free(RANY(obj)->as.node.u1.tbl));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef C_ALLOCA
|
#ifdef C_ALLOCA
|
||||||
case NODE_ALLOCA:
|
case NODE_ALLOCA:
|
||||||
free(RANY(obj)->as.node.u1.value);
|
RUBY_CRITICAL(free(RANY(obj)->as.node.u1.value));
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -830,15 +831,15 @@ obj_free(obj)
|
||||||
RANY(obj)->as.scope.flag != SCOPE_ALLOCA) {
|
RANY(obj)->as.scope.flag != SCOPE_ALLOCA) {
|
||||||
VALUE *vars = RANY(obj)->as.scope.local_vars-1;
|
VALUE *vars = RANY(obj)->as.scope.local_vars-1;
|
||||||
if (vars[0] == 0)
|
if (vars[0] == 0)
|
||||||
free(RANY(obj)->as.scope.local_tbl);
|
RUBY_CRITICAL(free(RANY(obj)->as.scope.local_tbl));
|
||||||
if (RANY(obj)->as.scope.flag&SCOPE_MALLOC)
|
if (RANY(obj)->as.scope.flag&SCOPE_MALLOC)
|
||||||
free(vars);
|
RUBY_CRITICAL(free(vars));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_STRUCT:
|
case T_STRUCT:
|
||||||
if (RANY(obj)->as.rstruct.ptr) {
|
if (RANY(obj)->as.rstruct.ptr) {
|
||||||
free(RANY(obj)->as.rstruct.ptr);
|
RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -785,7 +785,7 @@ rb_num2long(val)
|
||||||
return Qnil; /* not reached */
|
return Qnil; /* not reached */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
val = rb_Integer(val);
|
val = rb_to_int(val);
|
||||||
return NUM2LONG(val);
|
return NUM2LONG(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
5
object.c
5
object.c
|
@ -885,8 +885,8 @@ rb_to_integer(val, method)
|
||||||
val = rb_rescue2(to_type, (VALUE)&arg1, fail_to_type, (VALUE)&arg2,
|
val = rb_rescue2(to_type, (VALUE)&arg1, fail_to_type, (VALUE)&arg2,
|
||||||
rb_eStandardError, rb_eNameError, 0);
|
rb_eStandardError, rb_eNameError, 0);
|
||||||
if (!rb_obj_is_kind_of(val, rb_cInteger)) {
|
if (!rb_obj_is_kind_of(val, rb_cInteger)) {
|
||||||
rb_raise(rb_eTypeError, "%s#%s_i should return Integer",
|
rb_raise(rb_eTypeError, "%s#%s should return Integer",
|
||||||
method, rb_class2name(CLASS_OF(arg1.val)));
|
rb_class2name(CLASS_OF(arg1.val)), method);
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -1166,6 +1166,7 @@ Init_Object()
|
||||||
rb_undef_method(CLASS_OF(rb_cSymbol), "new");
|
rb_undef_method(CLASS_OF(rb_cSymbol), "new");
|
||||||
rb_define_method(rb_cSymbol, "type", sym_type, 0);
|
rb_define_method(rb_cSymbol, "type", sym_type, 0);
|
||||||
rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0);
|
rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0);
|
||||||
|
rb_define_method(rb_cSymbol, "to_int", sym_to_i, 0);
|
||||||
rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
|
rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
|
||||||
rb_define_method(rb_cSymbol, "to_s", sym_to_s, 0);
|
rb_define_method(rb_cSymbol, "to_s", sym_to_s, 0);
|
||||||
rb_define_method(rb_cSymbol, "id2name", sym_to_s, 0);
|
rb_define_method(rb_cSymbol, "id2name", sym_to_s, 0);
|
||||||
|
|
1
random.c
1
random.c
|
@ -114,6 +114,7 @@ rb_f_srand(argc, argv, obj)
|
||||||
VALUE a;
|
VALUE a;
|
||||||
unsigned int seed, old;
|
unsigned int seed, old;
|
||||||
|
|
||||||
|
rb_secure(4);
|
||||||
if (rb_scan_args(argc, argv, "01", &a) == 0) {
|
if (rb_scan_args(argc, argv, "01", &a) == 0) {
|
||||||
static int n = 0;
|
static int n = 0;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
38
rubysig.h
38
rubysig.h
|
@ -13,14 +13,40 @@
|
||||||
#ifndef SIG_H
|
#ifndef SIG_H
|
||||||
#define SIG_H
|
#define SIG_H
|
||||||
|
|
||||||
EXTERN int rb_trap_immediate;
|
|
||||||
#ifdef NT
|
#ifdef NT
|
||||||
#define TRAP_BEG (rb_trap_immediate=1, SetEvent(rb_InterruptEvent))
|
typedef LONG rb_atomic_t;
|
||||||
#define TRAP_END (rb_trap_immediate=0, ResetEvent(rb_InterruptEvent))
|
|
||||||
|
# define ATOMIC_TEST(var) InterlockedExchange(&(var), 0)
|
||||||
|
# define ATOMIC_SET(var, val) InterlockedExchange(&(var), (val))
|
||||||
|
# define ATOMIC_INC(var) InterlockedIncrement(&(var))
|
||||||
|
# define ATOMIC_DEC(var) InterlockedDecrement(&(var))
|
||||||
|
|
||||||
|
/* Windows doesn't allow interrupt while system calls */
|
||||||
|
# define TRAP_BEG win32_enter_syscall()
|
||||||
|
# define TRAP_END win32_leave_syscall()
|
||||||
|
# define RUBY_CRITICAL(statements) do {\
|
||||||
|
win32_disable_interrupt();\
|
||||||
|
statements;\
|
||||||
|
win32_enable_interrupt();\
|
||||||
|
} while (0)
|
||||||
#else
|
#else
|
||||||
#define TRAP_BEG (rb_trap_immediate=1)
|
typedef int rb_atomic_t;
|
||||||
#define TRAP_END (rb_trap_immediate=0)
|
|
||||||
|
# define ATOMIC_TEST(var) ((var) ? ((var) = 0, 1) : 0)
|
||||||
|
# define ATOMIC_SET(var, val) ((var) = (val))
|
||||||
|
# define ATOMIC_INC(var) (++(var))
|
||||||
|
# define ATOMIC_DEC(var) (--(var))
|
||||||
|
|
||||||
|
# define TRAP_BEG (rb_trap_immediate=1)
|
||||||
|
# define TRAP_END (rb_trap_immediate=0)
|
||||||
|
# define RUBY_CRITICAL(statements) do {\
|
||||||
|
int trap_immediate = rb_trap_immediate;\
|
||||||
|
rb_trap_immediate = 0;\
|
||||||
|
statements;\
|
||||||
|
rb_trap_immediate = trap_immediate;\
|
||||||
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
EXTERN rb_atomic_t rb_trap_immediate;
|
||||||
|
|
||||||
EXTERN int rb_prohibit_interrupt;
|
EXTERN int rb_prohibit_interrupt;
|
||||||
#define DEFER_INTS {rb_prohibit_interrupt++;}
|
#define DEFER_INTS {rb_prohibit_interrupt++;}
|
||||||
|
@ -29,7 +55,7 @@ EXTERN int rb_prohibit_interrupt;
|
||||||
|
|
||||||
VALUE rb_with_disable_interrupt _((VALUE(*)(),VALUE));
|
VALUE rb_with_disable_interrupt _((VALUE(*)(),VALUE));
|
||||||
|
|
||||||
EXTERN int rb_trap_pending;
|
EXTERN rb_atomic_t rb_trap_pending;
|
||||||
void rb_trap_restore_mask _((void));
|
void rb_trap_restore_mask _((void));
|
||||||
|
|
||||||
EXTERN int rb_thread_critical;
|
EXTERN int rb_thread_critical;
|
||||||
|
|
25
signal.c
25
signal.c
|
@ -260,9 +260,9 @@ rb_f_kill(argc, argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE trap_list[NSIG];
|
static VALUE trap_list[NSIG];
|
||||||
static int trap_pending_list[NSIG];
|
static rb_atomic_t trap_pending_list[NSIG];
|
||||||
int rb_trap_pending;
|
rb_atomic_t rb_trap_pending;
|
||||||
int rb_trap_immediate;
|
rb_atomic_t rb_trap_immediate;
|
||||||
int rb_prohibit_interrupt;
|
int rb_prohibit_interrupt;
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -303,6 +303,7 @@ posix_signal(signum, handler)
|
||||||
#define ruby_signal(sig,handle) signal((sig),(handle))
|
#define ruby_signal(sig,handle) signal((sig),(handle))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void signal_exec _((int sig));
|
||||||
static void
|
static void
|
||||||
signal_exec(sig)
|
signal_exec(sig)
|
||||||
int sig;
|
int sig;
|
||||||
|
@ -342,11 +343,9 @@ sighandle(sig)
|
||||||
int sig;
|
int sig;
|
||||||
{
|
{
|
||||||
#ifdef NT
|
#ifdef NT
|
||||||
#define end_interrupt() win32_thread_resume_main()
|
#define IN_MAIN_CONTEXT(f, a) (win32_main_context(a, f) ? (void)0 : f(a))
|
||||||
if (win32_main_context(sig, sighandle)) return;
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define end_interrupt() (void)0
|
#define IN_MAIN_CONTEXT(f, a) f(a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sig >= NSIG) {
|
if (sig >= NSIG) {
|
||||||
|
@ -357,16 +356,14 @@ sighandle(sig)
|
||||||
ruby_signal(sig, sighandle);
|
ruby_signal(sig, sighandle);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (rb_trap_immediate) {
|
if (ATOMIC_TEST(rb_trap_immediate)) {
|
||||||
rb_trap_immediate = 0;
|
IN_MAIN_CONTEXT(signal_exec, sig);
|
||||||
signal_exec(sig);
|
ATOMIC_SET(rb_trap_immediate, 1);
|
||||||
rb_trap_immediate = 1;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rb_trap_pending++;
|
ATOMIC_INC(rb_trap_pending);
|
||||||
trap_pending_list[sig]++;
|
ATOMIC_INC(trap_pending_list[sig]);
|
||||||
}
|
}
|
||||||
end_interrupt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SIGBUS
|
#ifdef SIGBUS
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#define RUBY_VERSION "1.6.2"
|
#define RUBY_VERSION "1.6.2"
|
||||||
#define RUBY_RELEASE_DATE "2000-11-13"
|
#define RUBY_RELEASE_DATE "2000-11-14"
|
||||||
#define RUBY_VERSION_CODE 162
|
#define RUBY_VERSION_CODE 162
|
||||||
#define RUBY_RELEASE_CODE 20001113
|
#define RUBY_RELEASE_CODE 20001114
|
||||||
|
|
556
win32/win32.c
556
win32/win32.c
|
@ -34,6 +34,32 @@
|
||||||
#define bool int
|
#define bool int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if USE_INTERRUPT_WINSOCK
|
||||||
|
|
||||||
|
# if defined(_MSC_VER) && _MSC_VER <= 1000
|
||||||
|
/* VC++4.0 doesn't have this. */
|
||||||
|
extern DWORD WSAWaitForMultipleEvents(DWORD nevent, const HANDLE *events,
|
||||||
|
BOOL waitall, DWORD timeout,
|
||||||
|
BOOL alertable);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# define WaitForMultipleEvents WSAWaitForMultipleEvents
|
||||||
|
# define CreateSignal() (HANDLE)WSACreateEvent()
|
||||||
|
# define SetSignal(ev) WSASetEvent(ev)
|
||||||
|
# define ResetSignal(ev) WSAResetEvent(ev)
|
||||||
|
#else /* USE_INTERRUPT_WINSOCK */
|
||||||
|
# define WaitForMultipleEvents WaitForMultipleObjectsEx
|
||||||
|
# define CreateSignal() CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
# define SetSignal(ev) SetEvent(ev)
|
||||||
|
# define ResetSignal(ev) (void)0
|
||||||
|
#endif /* USE_INTERRUPT_WINSOCK */
|
||||||
|
|
||||||
|
#ifdef WIN32_DEBUG
|
||||||
|
#define Debug(something) something
|
||||||
|
#else
|
||||||
|
#define Debug(something) /* nothing */
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TO_SOCKET(x) _get_osfhandle(x)
|
#define TO_SOCKET(x) _get_osfhandle(x)
|
||||||
|
|
||||||
bool NtSyncProcess = TRUE;
|
bool NtSyncProcess = TRUE;
|
||||||
|
@ -46,6 +72,7 @@ static bool NtHasRedirection (char *);
|
||||||
static int valid_filename(char *s);
|
static int valid_filename(char *s);
|
||||||
static void StartSockets ();
|
static void StartSockets ();
|
||||||
static char *str_grow(struct RString *str, size_t new_size);
|
static char *str_grow(struct RString *str, size_t new_size);
|
||||||
|
static DWORD wait_events(HANDLE event, DWORD timeout);
|
||||||
|
|
||||||
char *NTLoginName;
|
char *NTLoginName;
|
||||||
|
|
||||||
|
@ -76,17 +103,23 @@ IsWinNT(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* main thread constants */
|
/* main thread constants */
|
||||||
HANDLE rb_CurrentProcessHandle;
|
static struct {
|
||||||
HANDLE rb_MainThreadHandle;
|
HANDLE handle;
|
||||||
DWORD rb_MainThreadId;
|
DWORD id;
|
||||||
HANDLE rb_InterruptEvent;
|
} main_thread;
|
||||||
|
|
||||||
|
/* interrupt stuff */
|
||||||
|
static HANDLE interrupted_event;
|
||||||
|
|
||||||
HANDLE GetCurrentThreadHandle(void)
|
HANDLE GetCurrentThreadHandle(void)
|
||||||
{
|
{
|
||||||
|
static HANDLE current_process_handle = NULL;
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
HANDLE proc = rb_CurrentProcessHandle;
|
|
||||||
|
|
||||||
if (!DuplicateHandle(proc, GetCurrentThread(), proc, &h,
|
if (!current_process_handle)
|
||||||
|
current_process_handle = GetCurrentProcess();
|
||||||
|
if (!DuplicateHandle(current_process_handle, GetCurrentThread(),
|
||||||
|
current_process_handle, &h,
|
||||||
0, FALSE, DUPLICATE_SAME_ACCESS))
|
0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||||
return NULL;
|
return NULL;
|
||||||
return h;
|
return h;
|
||||||
|
@ -98,68 +131,78 @@ HANDLE GetCurrentThreadHandle(void)
|
||||||
#define LK_ERR(f,i) ((f) ? (i = 0) : (errno = GetLastError()))
|
#define LK_ERR(f,i) ((f) ? (i = 0) : (errno = GetLastError()))
|
||||||
#define LK_LEN 0xffff0000
|
#define LK_LEN 0xffff0000
|
||||||
|
|
||||||
int
|
static VALUE
|
||||||
flock(int fd, int oper)
|
flock_winnt(VALUE self, int argc, VALUE* argv)
|
||||||
{
|
{
|
||||||
OVERLAPPED o;
|
OVERLAPPED o;
|
||||||
int i = -1;
|
int i = -1;
|
||||||
HANDLE fh;
|
const HANDLE fh = (HANDLE)self;
|
||||||
|
const int oper = argc;
|
||||||
|
|
||||||
fh = (HANDLE)_get_osfhandle(fd);
|
|
||||||
memset(&o, 0, sizeof(o));
|
memset(&o, 0, sizeof(o));
|
||||||
|
|
||||||
if(IsWinNT()) {
|
switch(oper) {
|
||||||
switch(oper) {
|
case LOCK_SH: /* shared lock */
|
||||||
case LOCK_SH: /* shared lock */
|
LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o), i);
|
||||||
LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i);
|
break;
|
||||||
break;
|
case LOCK_EX: /* exclusive lock */
|
||||||
case LOCK_EX: /* exclusive lock */
|
LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o), i);
|
||||||
LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i);
|
break;
|
||||||
break;
|
case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
|
||||||
case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
|
LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o), i);
|
||||||
LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i);
|
break;
|
||||||
break;
|
case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
|
||||||
case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
|
LK_ERR(LockFileEx(fh,
|
||||||
LK_ERR(LockFileEx(fh,
|
LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
|
||||||
LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
|
0, LK_LEN, 0, &o), i);
|
||||||
0, LK_LEN, 0, &o),i);
|
if (errno == EDOM)
|
||||||
if(errno == EDOM) errno = EWOULDBLOCK;
|
errno = EWOULDBLOCK;
|
||||||
break;
|
break;
|
||||||
case LOCK_UN: /* unlock lock */
|
case LOCK_UN: /* unlock lock */
|
||||||
if (UnlockFileEx(fh, 0, LK_LEN, 0, &o)) {
|
if (UnlockFileEx(fh, 0, LK_LEN, 0, &o)) {
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
if (errno == EDOM)
|
||||||
else {
|
|
||||||
/* GetLastError() must returns `ERROR_NOT_LOCKED' */
|
|
||||||
errno = EWOULDBLOCK;
|
errno = EWOULDBLOCK;
|
||||||
}
|
}
|
||||||
if(errno == EDOM) errno = EWOULDBLOCK;
|
else {
|
||||||
break;
|
/* GetLastError() must returns `ERROR_NOT_LOCKED' */
|
||||||
default: /* unknown */
|
errno = EWOULDBLOCK;
|
||||||
errno = EINVAL;
|
}
|
||||||
break;
|
break;
|
||||||
}
|
default: /* unknown */
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if(IsWin95()) {
|
return i;
|
||||||
switch(oper) {
|
}
|
||||||
case LOCK_EX:
|
|
||||||
while(i == -1) {
|
static VALUE
|
||||||
LK_ERR(LockFile(fh, 0, 0, LK_LEN, 0), i);
|
flock_win95(VALUE self, int argc, VALUE* argv)
|
||||||
if(errno != EDOM && i == -1) break;
|
{
|
||||||
}
|
int i = -1;
|
||||||
break;
|
const HANDLE fh = (HANDLE)self;
|
||||||
case LOCK_EX | LOCK_NB:
|
const int oper = argc;
|
||||||
|
|
||||||
|
switch(oper) {
|
||||||
|
case LOCK_EX:
|
||||||
|
while(i == -1) {
|
||||||
LK_ERR(LockFile(fh, 0, 0, LK_LEN, 0), i);
|
LK_ERR(LockFile(fh, 0, 0, LK_LEN, 0), i);
|
||||||
if(errno == EDOM) errno = EWOULDBLOCK;
|
if (errno != EDOM && i == -1) break;
|
||||||
break;
|
}
|
||||||
case LOCK_UN:
|
break;
|
||||||
LK_ERR(UnlockFile(fh, 0, 0, LK_LEN, 0), i);
|
case LOCK_EX | LOCK_NB:
|
||||||
if(errno == EDOM) errno = EWOULDBLOCK;
|
LK_ERR(LockFile(fh, 0, 0, LK_LEN, 0), i);
|
||||||
break;
|
if (errno == EDOM)
|
||||||
default:
|
errno = EWOULDBLOCK;
|
||||||
errno = EINVAL;
|
break;
|
||||||
break;
|
case LOCK_UN:
|
||||||
}
|
LK_ERR(UnlockFile(fh, 0, 0, LK_LEN, 0), i);
|
||||||
|
if (errno == EDOM)
|
||||||
|
errno = EWOULDBLOCK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -167,6 +210,22 @@ flock(int fd, int oper)
|
||||||
#undef LK_ERR
|
#undef LK_ERR
|
||||||
#undef LK_LEN
|
#undef LK_LEN
|
||||||
|
|
||||||
|
int
|
||||||
|
flock(int fd, int oper)
|
||||||
|
{
|
||||||
|
static asynchronous_func_t locker = NULL;
|
||||||
|
|
||||||
|
if (!locker) {
|
||||||
|
if (IsWinNT())
|
||||||
|
locker = flock_winnt;
|
||||||
|
else
|
||||||
|
locker = flock_win95;
|
||||||
|
}
|
||||||
|
|
||||||
|
return win32_asynchronize(locker,
|
||||||
|
(VALUE)_get_osfhandle(fd), oper, NULL,
|
||||||
|
(DWORD)-1);
|
||||||
|
}
|
||||||
|
|
||||||
//#undef const
|
//#undef const
|
||||||
//FILE *fdopen(int, const char *);
|
//FILE *fdopen(int, const char *);
|
||||||
|
@ -1908,8 +1967,10 @@ 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;
|
||||||
|
#ifdef USE_INTERRUPT_WINSOCK
|
||||||
|
fd_set trap;
|
||||||
|
#endif /* USE_INTERRUPT_WINSOCK */
|
||||||
int file_nfds;
|
int file_nfds;
|
||||||
int trap_immediate = rb_trap_immediate;
|
|
||||||
|
|
||||||
if (!NtSocketsInitialized++) {
|
if (!NtSocketsInitialized++) {
|
||||||
StartSockets();
|
StartSockets();
|
||||||
|
@ -1928,18 +1989,26 @@ 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 (trap_immediate)
|
|
||||||
TRAP_END;
|
#if USE_INTERRUPT_WINSOCK
|
||||||
|
if (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 */
|
||||||
|
|
||||||
if ((r = select (nfds, rd, wr, ex, timeout)) == SOCKET_ERROR) {
|
if ((r = select (nfds, rd, wr, ex, timeout)) == SOCKET_ERROR) {
|
||||||
errno = WSAGetLastError();
|
errno = WSAGetLastError();
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case WSAEINTR:
|
case WSAEINTR:
|
||||||
errno = EINTR;
|
errno = EINTR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trap_immediate)
|
|
||||||
TRAP_BEG;
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1957,31 +2026,33 @@ StartSockets ()
|
||||||
//
|
//
|
||||||
version = MAKEWORD(1, 1);
|
version = MAKEWORD(1, 1);
|
||||||
if (ret = WSAStartup(version, &retdata))
|
if (ret = WSAStartup(version, &retdata))
|
||||||
rb_fatal ("Unable to locate winsock library!\n");
|
rb_fatal ("Unable to locate winsock library!\n");
|
||||||
if (LOBYTE(retdata.wVersion) != 1)
|
if (LOBYTE(retdata.wVersion) != 1)
|
||||||
rb_fatal("could not find version 1 of winsock dll\n");
|
rb_fatal("could not find version 1 of winsock dll\n");
|
||||||
|
|
||||||
if (HIBYTE(retdata.wVersion) != 1)
|
if (HIBYTE(retdata.wVersion) != 1)
|
||||||
rb_fatal("could not find version 1 of winsock dll\n");
|
rb_fatal("could not find version 1 of winsock dll\n");
|
||||||
|
|
||||||
atexit((void (*)(void)) WSACleanup);
|
atexit((void (*)(void)) WSACleanup);
|
||||||
|
|
||||||
iSockOpt = SO_SYNCHRONOUS_NONALERT;
|
iSockOpt = SO_SYNCHRONOUS_NONALERT;
|
||||||
/*
|
/*
|
||||||
* Enable the use of sockets as filehandles
|
* Enable the use of sockets as filehandles
|
||||||
*/
|
*/
|
||||||
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();
|
main_thread.handle = GetCurrentThreadHandle();
|
||||||
rb_MainThreadHandle = GetCurrentThreadHandle();
|
main_thread.id = GetCurrentThreadId();
|
||||||
rb_MainThreadId = GetCurrentThreadId();
|
|
||||||
rb_InterruptEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
|
interrupted_event = CreateSignal();
|
||||||
|
if (!interrupted_event)
|
||||||
|
rb_fatal("Unable to create interrupt event!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef accept
|
#undef accept
|
||||||
|
|
||||||
SOCKET
|
SOCKET
|
||||||
myaccept (SOCKET s, struct sockaddr *addr, int *addrlen)
|
myaccept (SOCKET s, struct sockaddr *addr, int *addrlen)
|
||||||
{
|
{
|
||||||
SOCKET r;
|
SOCKET r;
|
||||||
|
@ -1990,12 +2061,8 @@ myaccept (SOCKET s, struct sockaddr *addr, int *addrlen)
|
||||||
if (!NtSocketsInitialized++) {
|
if (!NtSocketsInitialized++) {
|
||||||
StartSockets();
|
StartSockets();
|
||||||
}
|
}
|
||||||
if (trap_immediate)
|
|
||||||
TRAP_END;
|
|
||||||
if ((r = accept (TO_SOCKET(s), addr, addrlen)) == INVALID_SOCKET)
|
if ((r = accept (TO_SOCKET(s), addr, addrlen)) == INVALID_SOCKET)
|
||||||
errno = WSAGetLastError();
|
errno = WSAGetLastError();
|
||||||
if (trap_immediate)
|
|
||||||
TRAP_BEG;
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2342,7 +2409,7 @@ waitpid (pid_t pid, int *stat_loc, int options)
|
||||||
} else {
|
} else {
|
||||||
timeout = INFINITE;
|
timeout = INFINITE;
|
||||||
}
|
}
|
||||||
if (WaitForSingleObject((HANDLE) pid, timeout) == WAIT_OBJECT_0) {
|
if (wait_events((HANDLE)pid, timeout) == WAIT_OBJECT_0) {
|
||||||
pid = _cwait(stat_loc, pid, 0);
|
pid = _cwait(stat_loc, pid, 0);
|
||||||
#if !defined __BORLANDC__
|
#if !defined __BORLANDC__
|
||||||
*stat_loc <<= 8;
|
*stat_loc <<= 8;
|
||||||
|
@ -2487,25 +2554,26 @@ myrename(const char *oldpath, const char *newpath)
|
||||||
if (!MoveFile(oldpath, newpath))
|
if (!MoveFile(oldpath, newpath))
|
||||||
res = -1;
|
res = -1;
|
||||||
|
|
||||||
if (res == 0 || (GetLastError() != ERROR_ALREADY_EXISTS
|
if (res) {
|
||||||
&& GetLastError() != ERROR_FILE_EXISTS))
|
switch (GetLastError()) {
|
||||||
goto done;
|
case ERROR_ALREADY_EXISTS:
|
||||||
|
case ERROR_FILE_EXISTS:
|
||||||
if (IsWinNT()) {
|
if (IsWinNT()) {
|
||||||
if (MoveFileEx(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
|
if (MoveFileEx(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
|
||||||
res = 0;
|
res = 0;
|
||||||
} else {
|
} else {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!DeleteFile(newpath) && GetLastError() != ERROR_FILE_NOT_FOUND)
|
if (!DeleteFile(newpath) && GetLastError() != ERROR_FILE_NOT_FOUND)
|
||||||
break;
|
break;
|
||||||
else if (MoveFile(oldpath, newpath)) {
|
else if (MoveFile(oldpath, newpath)) {
|
||||||
res = 0;
|
res = 0;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
if (res)
|
if (res)
|
||||||
errno = GetLastError();
|
errno = GetLastError();
|
||||||
else
|
else
|
||||||
|
@ -2545,88 +2613,288 @@ mytimes(struct tms *tmbuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int win32_thread_exclusive(void)
|
#undef Sleep
|
||||||
{
|
#define yield_once() Sleep(0)
|
||||||
if (GetCurrentThreadId() == rb_MainThreadId) return FALSE;
|
#define yield_until(condition) do yield_once(); while (!(condition))
|
||||||
|
|
||||||
SuspendThread(rb_MainThreadHandle);
|
static DWORD wait_events(HANDLE event, DWORD timeout)
|
||||||
return TRUE;
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void win32_thread_resume_main(void)
|
static CRITICAL_SECTION* system_state(void)
|
||||||
{
|
{
|
||||||
if (GetCurrentThreadId() != rb_MainThreadId)
|
static int initialized = 0;
|
||||||
ResumeThread(rb_MainThreadHandle);
|
static CRITICAL_SECTION syssect;
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
InitializeCriticalSection(&syssect);
|
||||||
|
initialized = 1;
|
||||||
|
}
|
||||||
|
return &syssect;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win32_suspend_self(void)
|
static LONG flag_interrupt = -1;
|
||||||
|
static volatile DWORD tlsi_interrupt = TLS_OUT_OF_INDEXES;
|
||||||
|
|
||||||
|
void win32_disable_interrupt(void)
|
||||||
{
|
{
|
||||||
SuspendThread(GetCurrentThread());
|
if (IsWinNT()) {
|
||||||
|
EnterCriticalSection(system_state());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tlsi_interrupt == TLS_OUT_OF_INDEXES) {
|
||||||
|
tlsi_interrupt = TlsAlloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
DWORD ti = (DWORD)TlsGetValue(tlsi_interrupt);
|
||||||
|
while (InterlockedIncrement(&flag_interrupt) > 0 && !ti) {
|
||||||
|
InterlockedDecrement(&flag_interrupt);
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
TlsSetValue(tlsi_interrupt, (PVOID)++ti);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win32_call_handler(int arg, void (*handler)(int), CONTEXT ctx)
|
void win32_enable_interrupt(void)
|
||||||
{
|
{
|
||||||
handler(arg);
|
if (IsWinNT()) {
|
||||||
ctx.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
|
LeaveCriticalSection(system_state());
|
||||||
SetThreadContext(rb_MainThreadHandle, &ctx);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InterlockedDecrement(&flag_interrupt);
|
||||||
|
TlsSetValue(tlsi_interrupt, (PVOID)((DWORD)TlsGetValue(tlsi_interrupt) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int catch_interrupt(unsigned long msec)
|
struct handler_arg_t {
|
||||||
|
void (*handler)(int);
|
||||||
|
int arg;
|
||||||
|
int status;
|
||||||
|
int userstate;
|
||||||
|
HANDLE handshake;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void win32_call_handler(struct handler_arg_t* h)
|
||||||
{
|
{
|
||||||
return !WaitForSingleObject(rb_InterruptEvent, msec);
|
int status;
|
||||||
|
RUBY_CRITICAL(rb_protect((VALUE (*)())h->handler, (VALUE)h->arg, &h->status);
|
||||||
|
status = h->status;
|
||||||
|
SetEvent(h->handshake));
|
||||||
|
if (status) {
|
||||||
|
rb_jump_tag(status);
|
||||||
|
}
|
||||||
|
h->userstate = 1; /* never syscall after here */
|
||||||
|
for (;;); /* wait here in user state */
|
||||||
}
|
}
|
||||||
|
|
||||||
int win32_interruptible(void)
|
static struct handler_arg_t* setup_handler(struct handler_arg_t *harg,
|
||||||
|
int arg,
|
||||||
|
void (*handler)(int),
|
||||||
|
HANDLE handshake)
|
||||||
{
|
{
|
||||||
if (catch_interrupt(0)) return TRUE;
|
harg->handler = handler;
|
||||||
SetEvent(rb_InterruptEvent);
|
harg->arg = arg;
|
||||||
return FALSE;
|
harg->status = 0;
|
||||||
|
harg->userstate = 0;
|
||||||
|
harg->handshake = handshake;
|
||||||
|
return harg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_call(CONTEXT* ctx, struct handler_arg_t *harg)
|
||||||
|
{
|
||||||
|
#ifdef _M_IX86
|
||||||
|
DWORD *esp = (DWORD *)ctx->Esp;
|
||||||
|
*--esp = (DWORD)harg;
|
||||||
|
*--esp = ctx->Eip;
|
||||||
|
ctx->Esp = (DWORD)esp;
|
||||||
|
ctx->Eip = (DWORD)win32_call_handler;
|
||||||
|
#else
|
||||||
|
#error unsupported processor
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int win32_main_context(int arg, void (*handler)(int))
|
int win32_main_context(int arg, void (*handler)(int))
|
||||||
{
|
{
|
||||||
if (!win32_thread_exclusive()) return FALSE;
|
static HANDLE interrupt_done = NULL;
|
||||||
|
struct handler_arg_t harg;
|
||||||
|
CONTEXT ctx_orig;
|
||||||
|
HANDLE current_thread = GetCurrentThread();
|
||||||
|
int old_priority = GetThreadPriority(current_thread);
|
||||||
|
|
||||||
if (!catch_interrupt(0)) {
|
if (GetCurrentThreadId() == main_thread.id) return FALSE;
|
||||||
SetEvent(rb_InterruptEvent);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
SetSignal(interrupted_event);
|
||||||
|
|
||||||
|
RUBY_CRITICAL({ /* the main thread must be in user state */
|
||||||
CONTEXT ctx;
|
CONTEXT ctx;
|
||||||
|
|
||||||
|
SuspendThread(main_thread.handle);
|
||||||
|
SetThreadPriority(current_thread, GetThreadPriority(main_thread.handle));
|
||||||
|
|
||||||
ZeroMemory(&ctx, sizeof(CONTEXT));
|
ZeroMemory(&ctx, sizeof(CONTEXT));
|
||||||
ctx.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
|
ctx.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
|
||||||
GetThreadContext(rb_MainThreadHandle, &ctx);
|
GetThreadContext(main_thread.handle, &ctx);
|
||||||
#ifdef _M_IX86
|
ctx_orig = ctx;
|
||||||
{
|
|
||||||
DWORD *esp = (DWORD *)(ctx.Esp - sizeof(CONTEXT));
|
/* handler context setup */
|
||||||
*(CONTEXT *)esp = ctx;
|
if (!interrupt_done) {
|
||||||
*--esp = (DWORD)handler;
|
interrupt_done = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
*--esp = arg;
|
/* anonymous one-shot event */
|
||||||
*--esp = ctx.Eip;
|
|
||||||
ctx.Esp = (DWORD)esp;
|
|
||||||
}
|
}
|
||||||
ctx.Eip = (DWORD)win32_call_handler;
|
else {
|
||||||
#else
|
ResetEvent(interrupt_done);
|
||||||
#error
|
}
|
||||||
#endif
|
setup_call(&ctx, setup_handler(&harg, arg, handler, interrupt_done));
|
||||||
|
|
||||||
ctx.ContextFlags = CONTEXT_CONTROL;
|
ctx.ContextFlags = CONTEXT_CONTROL;
|
||||||
SetThreadContext(rb_MainThreadHandle, &ctx);
|
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.userstate);
|
||||||
|
|
||||||
|
SuspendThread(main_thread.handle);
|
||||||
|
ctx_orig.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
|
||||||
|
SetThreadContext(main_thread.handle, &ctx_orig);
|
||||||
|
ResumeThread(main_thread.handle);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
ResumeThread(rb_MainThreadHandle);
|
/* otherwise leave the main thread raised */
|
||||||
|
|
||||||
|
SetThreadPriority(current_thread, old_priority);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void win32_sleep(unsigned long msec)
|
int win32_sleep(unsigned long msec)
|
||||||
{
|
{
|
||||||
int trap_immediate = rb_trap_immediate;
|
return wait_events(NULL, msec) != WAIT_TIMEOUT;
|
||||||
|
}
|
||||||
if (trap_immediate)
|
|
||||||
TRAP_END;
|
static void catch_interrupt(void)
|
||||||
catch_interrupt(msec);
|
{
|
||||||
if (trap_immediate)
|
yield_once();
|
||||||
TRAP_BEG;
|
win32_sleep(0);
|
||||||
|
CHECK_INTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void win32_enter_syscall(void)
|
||||||
|
{
|
||||||
|
InterlockedExchange(&rb_trap_immediate, 1);
|
||||||
|
catch_interrupt();
|
||||||
|
win32_disable_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void win32_leave_syscall(void)
|
||||||
|
{
|
||||||
|
win32_enable_interrupt();
|
||||||
|
catch_interrupt();
|
||||||
|
InterlockedExchange(&rb_trap_immediate, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct asynchronous_arg_t {
|
||||||
|
/* output field */
|
||||||
|
void* stackaddr;
|
||||||
|
|
||||||
|
/* input field */
|
||||||
|
VALUE (*func)(VALUE self, int argc, VALUE* argv);
|
||||||
|
VALUE self;
|
||||||
|
int argc;
|
||||||
|
VALUE* argv;
|
||||||
|
};
|
||||||
|
|
||||||
|
static DWORD WINAPI
|
||||||
|
call_asynchronous(PVOID argp)
|
||||||
|
{
|
||||||
|
struct asynchronous_arg_t *arg = argp;
|
||||||
|
arg->stackaddr = &argp;
|
||||||
|
return (DWORD)arg->func(arg->self, arg->argc, arg->argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE win32_asynchronize(asynchronous_func_t func,
|
||||||
|
VALUE self, int argc, VALUE* argv, VALUE intrval)
|
||||||
|
{
|
||||||
|
DWORD val;
|
||||||
|
BOOL interrupted = FALSE;
|
||||||
|
HANDLE thr;
|
||||||
|
|
||||||
|
RUBY_CRITICAL({
|
||||||
|
struct asynchronous_arg_t arg;
|
||||||
|
|
||||||
|
arg.stackaddr = NULL;
|
||||||
|
arg.func = func;
|
||||||
|
arg.self = self;
|
||||||
|
arg.argc = argc;
|
||||||
|
arg.argv = argv;
|
||||||
|
|
||||||
|
thr = CreateThread(NULL, 0, call_asynchronous, &arg, 0, &val);
|
||||||
|
|
||||||
|
if (thr) {
|
||||||
|
yield_until(arg.stackaddr);
|
||||||
|
|
||||||
|
if (wait_events(thr, INFINITE) != WAIT_OBJECT_0) {
|
||||||
|
interrupted = TRUE;
|
||||||
|
|
||||||
|
if (TerminateThread(thr, intrval)) {
|
||||||
|
yield_once();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GetExitCodeThread(thr, &val);
|
||||||
|
CloseHandle(thr);
|
||||||
|
|
||||||
|
if (interrupted) {
|
||||||
|
/* must release stack of killed thread, why doesn't Windows? */
|
||||||
|
MEMORY_BASIC_INFORMATION m;
|
||||||
|
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
|
if (!VirtualQuery(arg.stackaddr, &m, sizeof(m))) {
|
||||||
|
Debug(fprintf(stderr, "couldn't get stack base:%p:%d\n",
|
||||||
|
arg.stackaddr, GetLastError()));
|
||||||
|
}
|
||||||
|
else if (!VirtualFree(m.AllocationBase, 0, MEM_RELEASE)) {
|
||||||
|
Debug(fprintf(stderr, "couldn't release stack:%p:%d\n",
|
||||||
|
m.AllocationBase, GetLastError()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!thr) {
|
||||||
|
rb_fatal("failed to launch waiter thread:%d", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interrupted) {
|
||||||
|
errno = EINTR;
|
||||||
|
CHECK_INTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
|
@ -427,17 +427,23 @@ struct tms {
|
||||||
#define times mytimes
|
#define times mytimes
|
||||||
|
|
||||||
/* thread stuff */
|
/* thread stuff */
|
||||||
/* initialized by NtInitialize() */
|
|
||||||
HANDLE rb_CurrentProcessHandle;
|
|
||||||
HANDLE rb_MainThreadHandle;
|
|
||||||
HANDLE rb_InterruptEvent;
|
|
||||||
DWORD rb_MainThreadId;
|
|
||||||
|
|
||||||
HANDLE GetCurrentThreadHandle(void);
|
HANDLE GetCurrentThreadHandle(void);
|
||||||
int win32_main_context(int arg, void (*handler)(int));
|
int win32_main_context(int arg, void (*handler)(int));
|
||||||
int win32_interruptible(void);
|
int win32_sleep(unsigned long msec);
|
||||||
void win32_thread_resume_main(void);
|
void win32_enter_syscall(void);
|
||||||
void win32_sleep(unsigned long msec);
|
void win32_leave_syscall(void);
|
||||||
#define Sleep(msec) win32_sleep(msec)
|
void win32_disable_interrupt(void);
|
||||||
|
void win32_enable_interrupt(void);
|
||||||
|
#define Sleep(msec) (void)win32_sleep(msec)
|
||||||
|
|
||||||
|
/*
|
||||||
|
== ***CAUTION***
|
||||||
|
Since this function is very dangerous, ((*NEVER*))
|
||||||
|
* lock any HANDLEs(i.e. Mutex, Semaphore, CriticalSection and so on) or,
|
||||||
|
* use anything like TRAP_BEG...TRAP_END block structure,
|
||||||
|
in asynchronous_func_t.
|
||||||
|
*/
|
||||||
|
typedef DWORD (*asynchronous_func_t)(DWORD self, int argc, DWORD* argv);
|
||||||
|
DWORD win32_asynchronize(asynchronous_func_t func, DWORD self, int argc, DWORD* argv, DWORD intrval);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue