From: nobu.nakada@... Date: 2001-02-17T10:19:08+09:00 Subject: [ruby-dev:12254] Re: lazy mswin32/mingw32(Re: データベース ) なかだです。 At Wed, 14 Feb 2001 13:07:48 +0900, matz@zetabits.com (Yukihiro Matsumoto) wrote: > |実は僕は1.7に入れちゃっていいかな、と考えてました。 > > 私もいいんじゃないかなって思ってます。責任はとれませんけど。 じゃそうしてもらえますか。だいたい四月以降 Windows を使えるか どうかも不明なので、このまま握ってるのはまずそうな。 一応気づいた限りの部分は対処してみました。win32_getc()/putc() は性能面との妥協です。うーん、あとあるとすれば read()/write()? Index: rubysig.h =================================================================== RCS file: /home/cvs/ruby/src/ruby/rubysig.h,v retrieving revision 1.7 diff -u -2 -p -r1.7 rubysig.h --- rubysig.h 2001/02/14 05:51:58 1.7 +++ rubysig.h 2001/02/16 09:46:37 @@ -23,10 +23,12 @@ typedef LONG rb_atomic_t; /* Windows doesn't allow interrupt while system calls */ -# define TRAP_BEG win32_enter_syscall() -# define TRAP_END win32_leave_syscall() +# define TRAP_BEG do {\ + rb_atomic_t trap_immediate = ATOMIC_SET(rb_trap_immediate, 1); +# define TRAP_END ATOMIC_SET(rb_trap_immediate, trap_immediate);\ +} while (0) # define RUBY_CRITICAL(statements) do {\ - win32_disable_interrupt();\ + win32_enter_critical();\ statements;\ - win32_enable_interrupt();\ + win32_leave_critical();\ } while (0) #else Index: win32/win32.c =================================================================== RCS file: /home/cvs/ruby/src/ruby/win32/win32.c,v retrieving revision 1.34 diff -u -2 -p -r1.34 win32.c --- win32/win32.c 2001/02/09 15:02:14 1.34 +++ win32/win32.c 2001/02/16 09:39:29 @@ -36,13 +36,15 @@ #endif -#if USE_INTERRUPT_WINSOCK +#ifdef _M_IX86 +# define WIN95 1 +#else +# undef WIN95 +#endif -# 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 +#if HAVE_WSAWAITFORMULTIPLEEVENTS +# define USE_INTERRUPT_WINSOCK +#endif +#if USE_INTERRUPT_WINSOCK # define WaitForMultipleEvents WSAWaitForMultipleEvents # define CreateSignal() (HANDLE)WSACreateEvent() @@ -78,4 +80,5 @@ static DWORD wait_events(HANDLE event, D char *NTLoginName; +#ifdef WIN95 DWORD Win32System = (DWORD)-1; @@ -103,4 +106,8 @@ IsWinNT(void) { return (IdOS() == VER_PLATFORM_WIN32_NT); } +#else +# define IsWinNT() TRUE +# define IsWin95() FALSE +#endif /* main thread constants */ @@ -178,4 +185,5 @@ flock_winnt(VALUE self, int argc, VALUE* } +#ifdef WIN95 static VALUE flock_win95(VALUE self, int argc, VALUE* argv) @@ -208,4 +216,5 @@ flock_win95(VALUE self, int argc, VALUE* return i; } +#endif #undef LK_ERR @@ -215,4 +224,5 @@ int flock(int fd, int oper) { +#ifdef WIN95 static asynchronous_func_t locker = NULL; @@ -223,4 +233,7 @@ flock(int fd, int oper) locker = flock_win95; } +#else + const asynchronous_func_t locker = flock_winnt; +#endif return win32_asynchronize(locker, @@ -1672,4 +1685,11 @@ EXTERN_C void __cdecl _unlock(int); #define MSVCRT_THREADS #endif +#ifdef MSVCRT_THREADS +# define MTHREAD_ONLY(x) x +# define STHREAD_ONLY(x) +#else +# define MTHREAD_ONLY(x) +# define STHREAD_ONLY(x) x +#endif typedef struct { @@ -1706,18 +1726,4 @@ EXTERN_C _CRTIMP ioinfo * __pioinfo[]; static int -_alloc_osfhnd(void) -{ - HANDLE hF = CreateFile("NUL", 0, 0, NULL, OPEN_ALWAYS, 0, NULL); - int fh = _open_osfhandle((long)hF, 0); - CloseHandle(hF); - if (fh == -1) - return fh; -#ifdef MSVCRT_THREADS - EnterCriticalSection(&(_pioinfo(fh)->lock)); -#endif - return fh; -} - -static int my_open_osfhandle(long osfhandle, int flags) { @@ -1737,20 +1743,25 @@ my_open_osfhandle(long osfhandle, int fl fileflags |= FNOINHERIT; - /* attempt to allocate a C Runtime file handle */ - if ((fh = _alloc_osfhnd()) == -1) { - errno = EMFILE; /* too many open files */ - _doserrno = 0L; /* not an OS error */ - return -1; /* return error to caller */ - } + RUBY_CRITICAL({ + /* attempt to allocate a C Runtime file handle */ + HANDLE hF = CreateFile("NUL", 0, 0, NULL, OPEN_ALWAYS, 0, NULL); + fh = _open_osfhandle((long)hF, 0); + CloseHandle(hF); + if (fh == -1) { + errno = EMFILE; /* too many open files */ + _doserrno = 0L; /* not an OS error */ + } + else { - /* the file is open. now, set the info in _osfhnd array */ - _set_osfhnd(fh, osfhandle); + MTHREAD_ONLY(EnterCriticalSection(&(_pioinfo(fh)->lock))); + /* the file is open. now, set the info in _osfhnd array */ + _set_osfhnd(fh, osfhandle); - fileflags |= FOPEN; /* mark as open */ + fileflags |= FOPEN; /* mark as open */ - _osfile(fh) = fileflags; /* set osfile entry */ -#ifdef MSVCRT_THREADS - LeaveCriticalSection(&_pioinfo(fh)->lock); -#endif + _osfile(fh) = fileflags; /* set osfile entry */ + MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fh)->lock)); + } + }); return fh; /* return handle */ @@ -1798,8 +1809,8 @@ void myfdclose(FILE *fp) { -#if !defined MSVCRT_THREADS - _free_osfhnd(fileno(fp)); -#endif - fclose(fp); + RUBY_CRITICAL({ + STHREAD_ONLY(_free_osfhnd(fileno(fp))); + fclose(fp); + }); } @@ -2036,5 +2047,6 @@ myselect (int nfds, fd_set *rd, fd_set * #endif /* USE_INTERRUPT_WINSOCK */ - if ((r = select (nfds, rd, wr, ex, timeout)) == SOCKET_ERROR) { + RUBY_CRITICAL(r = select (nfds, rd, wr, ex, timeout)); + if (r == SOCKET_ERROR) { errno = WSAGetLastError(); switch (errno) { @@ -2083,4 +2095,7 @@ StartSockets () if (!interrupted_event) rb_fatal("Unable to create interrupt event!\n"); + interrupted_event = CreateSignal(); + if (!interrupted_event) + rb_fatal("Unable to create interrupt event!\n"); } @@ -2095,5 +2110,6 @@ myaccept (SOCKET s, struct sockaddr *add StartSockets(); } - if ((r = accept (TO_SOCKET(s), addr, addrlen)) == INVALID_SOCKET) + RUBY_CRITICAL(r = accept (TO_SOCKET(s), addr, addrlen)); + if (r == INVALID_SOCKET) errno = WSAGetLastError(); return my_open_osfhandle(r, O_RDWR|O_BINARY); @@ -2110,5 +2126,6 @@ mybind (SOCKET s, struct sockaddr *addr, StartSockets(); } - if ((r = bind (TO_SOCKET(s), addr, addrlen)) == SOCKET_ERROR) + RUBY_CRITICAL(r = bind (TO_SOCKET(s), addr, addrlen)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2124,5 +2141,6 @@ myconnect (SOCKET s, struct sockaddr *ad StartSockets(); } - if ((r = connect (TO_SOCKET(s), addr, addrlen)) == SOCKET_ERROR) + RUBY_CRITICAL(r = connect (TO_SOCKET(s), addr, addrlen)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2139,5 +2157,6 @@ mygetpeername (SOCKET s, struct sockaddr StartSockets(); } - if ((r = getpeername (TO_SOCKET(s), addr, addrlen)) == SOCKET_ERROR) + RUBY_CRITICAL(r = getpeername (TO_SOCKET(s), addr, addrlen)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2153,5 +2172,6 @@ mygetsockname (SOCKET s, struct sockaddr StartSockets(); } - if ((r = getsockname (TO_SOCKET(s), addr, addrlen)) == SOCKET_ERROR) + RUBY_CRITICAL(r = getsockname (TO_SOCKET(s), addr, addrlen)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2165,5 +2185,6 @@ mygetsockopt (SOCKET s, int level, int o StartSockets(); } - if ((r = getsockopt (TO_SOCKET(s), level, optname, optval, optlen)) == SOCKET_ERROR) + RUBY_CRITICAL(r = getsockopt (TO_SOCKET(s), level, optname, optval, optlen)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2179,5 +2200,6 @@ myioctlsocket (SOCKET s, long cmd, u_lon StartSockets(); } - if ((r = ioctlsocket (TO_SOCKET(s), cmd, argp)) == SOCKET_ERROR) + RUBY_CRITICAL(r = ioctlsocket (TO_SOCKET(s), cmd, argp)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2193,5 +2215,6 @@ mylisten (SOCKET s, int backlog) StartSockets(); } - if ((r = listen (TO_SOCKET(s), backlog)) == SOCKET_ERROR) + RUBY_CRITICAL(r = listen (TO_SOCKET(s), backlog)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2207,5 +2230,6 @@ myrecv (SOCKET s, char *buf, int len, in StartSockets(); } - if ((r = recv (TO_SOCKET(s), buf, len, flags)) == SOCKET_ERROR) + RUBY_CRITICAL(r = recv (TO_SOCKET(s), buf, len, flags)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2222,5 +2246,6 @@ myrecvfrom (SOCKET s, char *buf, int len StartSockets(); } - if ((r = recvfrom (TO_SOCKET(s), buf, len, flags, from, fromlen)) == SOCKET_ERROR) + RUBY_CRITICAL(r = recvfrom (TO_SOCKET(s), buf, len, flags, from, fromlen)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2236,5 +2261,6 @@ mysend (SOCKET s, char *buf, int len, in StartSockets(); } - if ((r = send (TO_SOCKET(s), buf, len, flags)) == SOCKET_ERROR) + RUBY_CRITICAL(r = send (TO_SOCKET(s), buf, len, flags)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2251,5 +2277,6 @@ mysendto (SOCKET s, char *buf, int len, StartSockets(); } - if ((r = sendto (TO_SOCKET(s), buf, len, flags, to, tolen)) == SOCKET_ERROR) + RUBY_CRITICAL(r = sendto (TO_SOCKET(s), buf, len, flags, to, tolen)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2265,6 +2292,6 @@ mysetsockopt (SOCKET s, int level, int o StartSockets(); } - if ((r = setsockopt (TO_SOCKET(s), level, optname, optval, optlen)) - == SOCKET_ERROR) + RUBY_CRITICAL(r = setsockopt (TO_SOCKET(s), level, optname, optval, optlen)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2280,5 +2307,6 @@ myshutdown (SOCKET s, int how) StartSockets(); } - if ((r = shutdown (TO_SOCKET(s), how)) == SOCKET_ERROR) + RUBY_CRITICAL(r = shutdown (TO_SOCKET(s), how)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2294,5 +2322,6 @@ mysocket (int af, int type, int protocol StartSockets(); } - if ((s = socket (af, type, protocol)) == INVALID_SOCKET) { + RUBY_CRITICAL(s = socket (af, type, protocol)); + if (s == INVALID_SOCKET) { errno = WSAGetLastError(); //fprintf(stderr, "socket fail (%d)", WSAGetLastError()); @@ -2310,5 +2339,6 @@ mygethostbyaddr (char *addr, int len, in StartSockets(); } - if ((r = gethostbyaddr (addr, len, type)) == NULL) + RUBY_CRITICAL(r = gethostbyaddr (addr, len, type)); + if (r == NULL) errno = WSAGetLastError(); return r; @@ -2324,5 +2354,6 @@ mygethostbyname (char *name) StartSockets(); } - if ((r = gethostbyname (name)) == NULL) + RUBY_CRITICAL(r = gethostbyname (name)); + if (r == NULL) errno = WSAGetLastError(); return r; @@ -2338,5 +2369,6 @@ mygethostname (char *name, int len) StartSockets(); } - if ((r = gethostname (name, len)) == SOCKET_ERROR) + RUBY_CRITICAL(r = gethostname (name, len)); + if (r == SOCKET_ERROR) errno = WSAGetLastError(); return r; @@ -2352,5 +2384,6 @@ mygetprotobyname (char *name) StartSockets(); } - if ((r = getprotobyname (name)) == NULL) + RUBY_CRITICAL(r = getprotobyname (name)); + if (r == NULL) errno = WSAGetLastError(); return r; @@ -2366,5 +2399,6 @@ mygetprotobynumber (int num) StartSockets(); } - if ((r = getprotobynumber (num)) == NULL) + RUBY_CRITICAL(r = getprotobynumber (num)); + if (r == NULL) errno = WSAGetLastError(); return r; @@ -2380,5 +2414,6 @@ mygetservbyname (char *name, char *proto StartSockets(); } - if ((r = getservbyname (name, proto)) == NULL) + RUBY_CRITICAL(r = getservbyname (name, proto)); + if (r == NULL) errno = WSAGetLastError(); return r; @@ -2394,5 +2429,6 @@ mygetservbyport (int port, char *proto) StartSockets(); } - if ((r = getservbyport (port, proto)) == NULL) + RUBY_CRITICAL(r = getservbyport (port, proto)); + if (r == NULL) errno = WSAGetLastError(); return r; @@ -2441,12 +2477,16 @@ waitpid (pid_t pid, int *stat_loc, int o timeout = INFINITE; } - if (wait_events((HANDLE)pid, timeout) == WAIT_OBJECT_0) { - pid = _cwait(stat_loc, pid, 0); + RUBY_CRITICAL({ + if (wait_events((HANDLE)pid, timeout) == WAIT_OBJECT_0) { + pid = _cwait(stat_loc, pid, 0); + } + else { + pid = 0; + } + }); #if !defined __BORLANDC__ - *stat_loc <<= 8; + if (pid) *stat_loc <<= 8; #endif - return pid; - } - return 0; + return pid; } @@ -2579,35 +2619,37 @@ myrename(const char *oldpath, const char return -1; } - - if (newatts != -1 && newatts & FILE_ATTRIBUTE_READONLY) - SetFileAttributesA(newpath, newatts & ~ FILE_ATTRIBUTE_READONLY); - if (!MoveFile(oldpath, newpath)) - res = -1; - - if (res) { - switch (GetLastError()) { - case ERROR_ALREADY_EXISTS: - case ERROR_FILE_EXISTS: - if (IsWinNT()) { - if (MoveFileEx(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) - res = 0; - } else { - for (;;) { - if (!DeleteFile(newpath) && GetLastError() != ERROR_FILE_NOT_FOUND) - break; - else if (MoveFile(oldpath, newpath)) { + RUBY_CRITICAL({ + if (newatts != -1 && newatts & FILE_ATTRIBUTE_READONLY) + SetFileAttributesA(newpath, newatts & ~ FILE_ATTRIBUTE_READONLY); + + if (!MoveFile(oldpath, newpath)) + res = -1; + + if (res) { + switch (GetLastError()) { + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + if (IsWinNT()) { + if (MoveFileEx(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) res = 0; - break; + } else { + for (;;) { + if (!DeleteFile(newpath) && GetLastError() != ERROR_FILE_NOT_FOUND) + break; + else if (MoveFile(oldpath, newpath)) { + res = 0; + break; + } } } } } - } - if (res) - errno = GetLastError(); - else - SetFileAttributes(newpath, oldatts); + if (res) + errno = GetLastError(); + else + SetFileAttributes(newpath, oldatts); + }); return res; @@ -2618,4 +2660,5 @@ win32_stat(const char *path, struct stat { const char *p = path; + int ret; if ((isdirsep(*p) && (p++, TRUE)) || /* absolute path or UNC */ @@ -2631,5 +2674,6 @@ win32_stat(const char *path, struct stat path = s; } - return stat(path, st); + RUBY_CRITICAL(ret = stat(path, st)); + return ret; } @@ -2705,5 +2749,5 @@ static LONG flag_interrupt = -1; static volatile DWORD tlsi_interrupt = TLS_OUT_OF_INDEXES; -void win32_disable_interrupt(void) +void win32_enter_critical(void) { if (IsWinNT()) { @@ -2726,5 +2770,5 @@ void win32_disable_interrupt(void) } -void win32_enable_interrupt(void) +void win32_leave_critical(void) { if (IsWinNT()) { @@ -2741,5 +2785,5 @@ struct handler_arg_t { int arg; int status; - int userstate; + int finished; HANDLE handshake; }; @@ -2754,6 +2798,6 @@ static void win32_call_handler(struct ha rb_jump_tag(status); } - h->userstate = 1; /* never syscall after here */ - for (;;); /* wait here in user state */ + h->finished = 1; + Sleep(INFINITE); /* safe on Win95? */ } @@ -2766,5 +2810,5 @@ static struct handler_arg_t* setup_handl harg->arg = arg; harg->status = 0; - harg->userstate = 0; + harg->finished = 0; harg->handshake = handshake; return harg; @@ -2830,5 +2874,5 @@ int win32_main_context(int arg, void (*h RUBY_CRITICAL({ /* ensure the main thread is in user state. */ - yield_until(harg.userstate); + yield_until(harg.finished); SuspendThread(main_thread.handle); @@ -2847,5 +2891,9 @@ int win32_main_context(int arg, void (*h int win32_sleep(unsigned long msec) { - return wait_events(NULL, msec) != WAIT_TIMEOUT; + DWORD ret; + RUBY_CRITICAL(ret = wait_events(NULL, msec)); + yield_once(); + CHECK_INTS; + return ret != WAIT_TIMEOUT; } @@ -2853,20 +2901,38 @@ static void catch_interrupt(void) { yield_once(); - win32_sleep(0); + RUBY_CRITICAL(wait_events(NULL, 0)); CHECK_INTS; } -void win32_enter_syscall(void) +#undef fgetc +int win32_getc(FILE* stream) { - InterlockedExchange(&rb_trap_immediate, 1); - catch_interrupt(); - win32_disable_interrupt(); + int c, trap_immediate = rb_trap_immediate; + if (--stream->_cnt >= 0) { + c = (unsigned char)*stream->_ptr++; + rb_trap_immediate = trap_immediate; + } + else { + c = _filbuf(stream); + rb_trap_immediate = trap_immediate; + catch_interrupt(); + } + return c; } -void win32_leave_syscall(void) +#undef fputc +int win32_putc(int c, FILE* stream) { - win32_enable_interrupt(); - catch_interrupt(); - InterlockedExchange(&rb_trap_immediate, 0); + int trap_immediate = rb_trap_immediate; + if (--stream->_cnt >= 0) { + c = (unsigned char)(*stream->_ptr++ = (char)c); + rb_trap_immediate = trap_immediate; + } + else { + c = _flsbuf(c, stream); + rb_trap_immediate = trap_immediate; + catch_interrupt(); + } + return c; } Index: win32/win32.h =================================================================== RCS file: /home/cvs/ruby/src/ruby/win32/win32.h,v retrieving revision 1.15 diff -u -2 -p -r1.15 win32.h --- win32/win32.h 2001/02/09 15:02:14 1.15 +++ win32/win32.h 2001/02/13 09:30:57 @@ -113,4 +113,21 @@ extern "C++" { #define WNOHANG -1 +#undef getc +#undef putc +#undef fgetc +#undef fputc +#undef getchar +#undef putchar +#undef fgetchar +#undef fputchar +#define getc(_stream) win32_getc(_stream) +#define putc(_c, _stream) win32_putc(_c, _stream) +#define fgetc(_stream) getc(_stream) +#define fputc(_c, _stream) putc(_c, _stream) +#define getchar() win32_getc(stdin) +#define putchar(_c) win32_putc(_c, stdout) +#define fgetchar(_stream) getchar() +#define fputchar(_c, _stream) putchar(_c) + #define access _access #define chmod _chmod @@ -428,8 +445,8 @@ HANDLE GetCurrentThreadHandle(void); int win32_main_context(int arg, void (*handler)(int)); int win32_sleep(unsigned long msec); -void win32_enter_syscall(void); -void win32_leave_syscall(void); -void win32_disable_interrupt(void); -void win32_enable_interrupt(void); +void win32_enter_critical(void); +void win32_leave_critical(void); +int win32_putc(int, FILE*); +int win32_getc(FILE*); #define Sleep(msec) (void)win32_sleep(msec) -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦