diff --git a/src/mred/mredmsw.cxx b/src/mred/mredmsw.cxx index 7c283d29c6..90b2c213c0 100644 --- a/src/mred/mredmsw.cxx +++ b/src/mred/mredmsw.cxx @@ -42,7 +42,6 @@ extern long last_msg_time; extern "C" { struct Scheme_Thread_Memory *scheme_remember_thread(void *); void scheme_forget_thread(struct Scheme_Thread_Memory *); - void scheme_interrupt_win32_thread(HANDLE th); }; static int found_nothing; @@ -846,28 +845,8 @@ int MrEdCheckForBreak(void) } } -#ifdef MZ_PRECISE_GC -START_XFORM_SKIP; -#endif - -static long signal_fddone(void *fds) -{ - win_extended_fd_set *r = (win_extended_fd_set *)fds; - win_extended_fd_set *w = ((win_extended_fd_set *)fds) + 1; - win_extended_fd_set *e = ((win_extended_fd_set *)fds) + 2; - - select(0, &r->set, &w->set, &e->set, 0); - - return 0; -} - -#ifdef MZ_PRECISE_GC -END_XFORM_SKIP; -#endif - void MrEdMSWSleep(float secs, void *fds) { - win_extended_fd_set *r, *w, *e; DWORD msecs; if (fds && ((win_extended_fd_set *)fds)->no_sleep) @@ -930,72 +909,28 @@ void MrEdMSWSleep(float secs, void *fds) } if (fds) { + win_extended_fd_set *r; + int num_handles, num_rhandles, *rps, result; + HANDLE *handles; + + scheme_collapse_win_fd(fds); /* merges */ + r = (win_extended_fd_set *)fds; - w = ((win_extended_fd_set *)fds) + 1; - e = ((win_extended_fd_set *)fds) + 2; - } else - r = w = e = NULL; - - /* Block: use different stratgey if there are handles or fds to watch: */ - if (fds && ((r->added || w->added || e->added) - || r->num_handles)) { - - int num_handles = r->num_handles, *rps, two_rps[2]; - HANDLE *handles, two_handles[2]; - SOCKET fake; - HANDLE th2; - DWORD result; - DWORD id; - struct Scheme_Thread_Memory *thread_memory; - - if (num_handles) { - /* handles has been set up with an extra couple of slots: */ - handles = r->handles; - rps = r->repost_sema; - } else { - handles = two_handles; - rps = two_rps; - } - - if (r->set.fd_count || w->set.fd_count || e->set.fd_count) { - fake = socket(PF_INET, SOCK_STREAM, 0); - FD_SET(fake, e); - FD_SET(fake, r); - - th2 = CreateThread(NULL, 4096, - (LPTHREAD_START_ROUTINE)signal_fddone, - fds, 0, &id); - /* Not actually necessary, since GC can't occur during the - thread's life, but better safe than sorry if we change the - code later. */ - thread_memory = scheme_remember_thread((void *)th2); - - rps[num_handles] = 0; - handles[num_handles++] = th2; - } else - th2 = NULL; + + num_rhandles = SCHEME_INT_VAL(((win_extended_fd_set *)fds)->num_handles); + num_handles = SCHEME_INT_VAL(((win_extended_fd_set *)fds)->combined_len); + handles = ((win_extended_fd_set *)fds)->combined_wait_array; + rps = ((win_extended_fd_set *)fds)->repost_sema; result = MsgWaitForMultipleObjects(num_handles, handles, FALSE, secs ? msecs : INFINITE, QS_ALLINPUT); - if ((result >= WAIT_OBJECT_0) && (result < WAIT_OBJECT_0 + num_handles)) { + if ((result >= WAIT_OBJECT_0) && (result < WAIT_OBJECT_0 + num_rhandles)) { result -= WAIT_OBJECT_0; if (rps[result]) ReleaseSemaphore(handles[result], 1, NULL); } - - if (th2) { - while (closesocket(fake)) { - /* I don't think WSAEINPROGRESS should happen, but just in case... */ - if (WSAGetLastError() != WSAEINPROGRESS) - break; - } - scheme_interrupt_win32_thread(th2); - WaitForSingleObject(th2, INFINITE); - scheme_forget_thread(thread_memory); - CloseHandle(th2); - } } else if (wxTheApp->keep_going) { MsgWaitForMultipleObjects(0, NULL, FALSE, secs ? msecs : INFINITE, diff --git a/src/mzscheme/src/mzmark.c b/src/mzscheme/src/mzmark.c index 36ae988ed3..64c2337deb 100644 --- a/src/mzscheme/src/mzmark.c +++ b/src/mzscheme/src/mzmark.c @@ -3519,27 +3519,6 @@ static int mark_input_file_FIXUP(void *p) { #define mark_input_file_IS_CONST_SIZE 1 -#if defined(WIN32_FD_HANDLES) -static int mark_tcp_select_info_SIZE(void *p) { - return - gcBYTES_TO_WORDS(sizeof(Tcp_Select_Info)); -} - -static int mark_tcp_select_info_MARK(void *p) { - return - gcBYTES_TO_WORDS(sizeof(Tcp_Select_Info)); -} - -static int mark_tcp_select_info_FIXUP(void *p) { - return - gcBYTES_TO_WORDS(sizeof(Tcp_Select_Info)); -} - -#define mark_tcp_select_info_IS_ATOMIC 1 -#define mark_tcp_select_info_IS_CONST_SIZE 1 - -#endif - static int mark_output_file_SIZE(void *p) { return gcBYTES_TO_WORDS(sizeof(Scheme_Output_File)); diff --git a/src/mzscheme/src/mzmarksrc.c b/src/mzscheme/src/mzmarksrc.c index 4ac017da7b..a49b33ab01 100644 --- a/src/mzscheme/src/mzmarksrc.c +++ b/src/mzscheme/src/mzmarksrc.c @@ -1431,14 +1431,6 @@ mark_input_file { gcBYTES_TO_WORDS(sizeof(Scheme_Input_File)); } -#if defined(WIN32_FD_HANDLES) -mark_tcp_select_info { - mark: - size: - gcBYTES_TO_WORDS(sizeof(Tcp_Select_Info)); -} -#endif - mark_output_file { mark: Scheme_Output_File *o = (Scheme_Output_File *)p; diff --git a/src/mzscheme/src/network.c b/src/mzscheme/src/network.c index f06f596f1e..8d02421c51 100644 --- a/src/mzscheme/src/network.c +++ b/src/mzscheme/src/network.c @@ -155,6 +155,21 @@ typedef struct Scheme_UDP { #endif /* USE_TCP */ +#if defined(WINDOWS_PROCESSES) || defined(WINDOWS_FILE_HANDLES) +# define DECL_OS_FDSET(n) fd_set n[1] +# define INIT_DECL_OS_FDSET(n) /* empty */ +# define MZ_OS_FD_ZERO(p) FD_ZERO(p) +# define MZ_OS_FD_SET(n, p) FD_SET(n, p) +# define MZ_OS_FD_CLR(n, p) FD_CLR(n, p) +#else +# define DECL_OS_FDSET(n) DECL_FDSET(n, 1) +# define INIT_DECL_OS_FDSET(n) INIT_DECL_FDSET(n, 1) +# define MZ_OS_FD_ZERO(p) MZ_FD_ZERO(p) +# define MZ_OS_FD_SET(n, p) MZ_FD_SET(n, p) +# define MZ_OS_FD_CLR(n, p) MZ_FD_CLR(n, p) +#endif +#define MZ_OS_FD_ISSET(n, p) FD_ISSET(n, p) + static Scheme_Object *tcp_connect(int argc, Scheme_Object *argv[]); static Scheme_Object *tcp_connect_break(int argc, Scheme_Object *argv[]); static Scheme_Object *tcp_listen(int argc, Scheme_Object *argv[]); @@ -937,25 +952,25 @@ static int tcp_check_accept(Scheme_Object *_listener) #ifdef USE_SOCKETS_TCP tcp_t s, mx; listener_t *listener = (listener_t *)_listener; - DECL_FDSET(readfds, 1); - DECL_FDSET(exnfds, 1); + DECL_OS_FDSET(readfds); + DECL_OS_FDSET(exnfds); struct timeval time = {0, 0}; int sr, i; - INIT_DECL_FDSET(readfds, 1); - INIT_DECL_FDSET(exnfds, 1); + INIT_DECL_OS_FDSET(readfds); + INIT_DECL_OS_FDSET(exnfds); if (LISTENER_WAS_CLOSED(listener)) return 1; - MZ_FD_ZERO(readfds); - MZ_FD_ZERO(exnfds); + MZ_OS_FD_ZERO(readfds); + MZ_OS_FD_ZERO(exnfds); mx = 0; for (i = 0; i < listener->count; i++) { s = listener->s[i]; - MZ_FD_SET(s, readfds); - MZ_FD_SET(s, exnfds); + MZ_OS_FD_SET(s, readfds); + MZ_OS_FD_SET(s, exnfds); if (s > mx) mx = s; } @@ -967,8 +982,8 @@ static int tcp_check_accept(Scheme_Object *_listener) if (sr) { for (i = 0; i < listener->count; i++) { s = listener->s[i]; - if (FD_ISSET(s, readfds) - || FD_ISSET(s, exnfds)) + if (MZ_OS_FD_ISSET(s, readfds) + || MZ_OS_FD_ISSET(s, exnfds)) return i + 1; } } @@ -1001,21 +1016,21 @@ static int tcp_check_connect(Scheme_Object *connector_p) { #ifdef USE_SOCKETS_TCP tcp_t s; - DECL_FDSET(writefds, 1); - DECL_FDSET(exnfds, 1); + DECL_OS_FDSET(writefds); + DECL_OS_FDSET(exnfds); struct timeval time = {0, 0}; int sr; - INIT_DECL_FDSET(writefds, 1); - INIT_DECL_FDSET(exnfds, 1); + INIT_DECL_OS_FDSET(writefds); + INIT_DECL_OS_FDSET(exnfds); s = *(tcp_t *)connector_p; - MZ_FD_ZERO(writefds); - MZ_FD_ZERO(exnfds); + MZ_OS_FD_ZERO(writefds); + MZ_OS_FD_ZERO(exnfds); - MZ_FD_SET(s, writefds); - MZ_FD_SET(s, exnfds); + MZ_OS_FD_SET(s, writefds); + MZ_OS_FD_SET(s, exnfds); do { sr = select(s + 1, NULL, writefds, exnfds, &time); @@ -1056,20 +1071,20 @@ static int tcp_check_write(Scheme_Object *port) #ifdef USE_SOCKETS_TCP { tcp_t s; - DECL_FDSET(writefds, 1); - DECL_FDSET(exnfds, 1); + DECL_OS_FDSET(writefds); + DECL_OS_FDSET(exnfds); struct timeval time = {0, 0}; int sr; - INIT_DECL_FDSET(writefds, 1); - INIT_DECL_FDSET(exnfds, 1); + INIT_DECL_OS_FDSET(writefds); + INIT_DECL_OS_FDSET(exnfds); s = data->tcp; - MZ_FD_ZERO(writefds); - MZ_FD_SET(s, writefds); - MZ_FD_ZERO(exnfds); - MZ_FD_SET(s, exnfds); + MZ_OS_FD_ZERO(writefds); + MZ_OS_FD_SET(s, writefds); + MZ_OS_FD_ZERO(exnfds); + MZ_OS_FD_SET(s, exnfds); do { sr = select(s + 1, NULL, writefds, exnfds, &time); @@ -1156,12 +1171,12 @@ static int tcp_byte_ready (Scheme_Input_Port *port) Scheme_Tcp *data; #ifdef USE_SOCKETS_TCP int sr; - DECL_FDSET(readfds, 1); - DECL_FDSET(exfds, 1); + DECL_OS_FDSET(readfds); + DECL_OS_FDSET(exfds); struct timeval time = {0, 0}; - INIT_DECL_FDSET(readfds, 1); - INIT_DECL_FDSET(exfds, 1); + INIT_DECL_OS_FDSET(readfds); + INIT_DECL_OS_FDSET(exfds); #endif if (port->closed) @@ -1175,10 +1190,10 @@ static int tcp_byte_ready (Scheme_Input_Port *port) return 1; #ifdef USE_SOCKETS_TCP - MZ_FD_ZERO(readfds); - MZ_FD_ZERO(exfds); - MZ_FD_SET(data->tcp, readfds); - MZ_FD_SET(data->tcp, exfds); + MZ_OS_FD_ZERO(readfds); + MZ_OS_FD_ZERO(exfds); + MZ_OS_FD_SET(data->tcp, readfds); + MZ_OS_FD_SET(data->tcp, exfds); do { sr = select(data->tcp + 1, readfds, NULL, exfds, &time); @@ -2880,18 +2895,18 @@ static int udp_check_send(Scheme_Object *_udp) return 1; { - DECL_FDSET(writefds, 1); - DECL_FDSET(exnfds, 1); + DECL_OS_FDSET(writefds); + DECL_OS_FDSET(exnfds); struct timeval time = {0, 0}; int sr; - INIT_DECL_FDSET(writefds, 1); - INIT_DECL_FDSET(exnfds, 1); + INIT_DECL_OS_FDSET(writefds); + INIT_DECL_OS_FDSET(exnfds); - MZ_FD_ZERO(writefds); - MZ_FD_SET(udp->s, writefds); - MZ_FD_ZERO(exnfds); - MZ_FD_SET(udp->s, exnfds); + MZ_OS_FD_ZERO(writefds); + MZ_OS_FD_SET(udp->s, writefds); + MZ_OS_FD_ZERO(exnfds); + MZ_OS_FD_SET(udp->s, exnfds); do { sr = select(udp->s + 1, NULL, writefds, exnfds, &time); @@ -3112,18 +3127,18 @@ static int udp_check_recv(Scheme_Object *_udp) return 1; { - DECL_FDSET(readfds, 1); - DECL_FDSET(exnfds, 1); + DECL_OS_FDSET(readfds); + DECL_OS_FDSET(exnfds); struct timeval time = {0, 0}; int sr; - INIT_DECL_FDSET(readfds, 1); - INIT_DECL_FDSET(exnfds, 1); + INIT_DECL_OS_FDSET(readfds); + INIT_DECL_OS_FDSET(exnfds); - MZ_FD_ZERO(readfds); - MZ_FD_SET(udp->s, readfds); - MZ_FD_ZERO(exnfds); - MZ_FD_SET(udp->s, exnfds); + MZ_OS_FD_ZERO(readfds); + MZ_OS_FD_SET(udp->s, readfds); + MZ_OS_FD_ZERO(exnfds); + MZ_OS_FD_SET(udp->s, exnfds); do { sr = select(udp->s + 1, readfds, NULL, exnfds, &time); diff --git a/src/mzscheme/src/port.c b/src/mzscheme/src/port.c index f10ffc67a6..d83c121f12 100644 --- a/src/mzscheme/src/port.c +++ b/src/mzscheme/src/port.c @@ -104,6 +104,7 @@ typedef struct { static void init_thread_memory(); # define WIN32_FD_HANDLES +# include # include # include # include @@ -739,17 +740,20 @@ void *scheme_alloc_fdset_array(int count, int permanent) { #if defined(FILES_HAVE_FDS) || defined(USE_SOCKETS_TCP) || defined(WIN32_FD_HANDLES) void *fdarray; +# if defined(WIN32_FD_HANDLES) + if (count) { + fdarray = scheme_malloc_allow_interior(count * sizeof(fdset_type)); + if (permanent) + scheme_dont_gc_ptr(fdarray); + + scheme_init_fdset_array(fdarray, count); + } else + fdarray = NULL; +# else if (permanent) fdarray = scheme_malloc_eternal(count * sizeof(fdset_type)); else fdarray = scheme_malloc_atomic(count * sizeof(fdset_type)); -# if defined(WIN32_FD_HANDLES) - if (count) { - ((win_extended_fd_set *)fdarray)->added = 0; - ((win_extended_fd_set *)fdarray)->num_handles = 0; - ((win_extended_fd_set *)fdarray)->no_sleep = 0; - ((win_extended_fd_set *)fdarray)->wait_event_mask = 0; - } # endif return fdarray; #else @@ -757,13 +761,37 @@ void *scheme_alloc_fdset_array(int count, int permanent) #endif } +#if defined(WIN32_FD_HANDLES) +static void reset_wait_array(win_extended_fd_set *efd) +{ + /* Allocate an array that may be big enough to hold all events + when we eventually call WaitForMultipleObjects. One of the three + arrays will be big enough. */ + int sz = (3 * (SCHEME_INT_VAL(efd->alloc) + SCHEME_INT_VAL(efd->num_handles))) + 2; + HANDLE *wa; + wa = MALLOC_N_ATOMIC(HANDLE, sz); + efd->wait_array = wa; +} +#endif + void *scheme_init_fdset_array(void *fdarray, int count) { #if defined(WIN32_FD_HANDLES) if (count) { - ((win_extended_fd_set *)fdarray)->added = 0; - ((win_extended_fd_set *)fdarray)->num_handles = 0; - ((win_extended_fd_set *)fdarray)->wait_event_mask = 0; + int i; + win_extended_fd_set *fd; + for (i = 0; i < count; i++) { + fd = (win_extended_fd_set *)scheme_get_fdset(fdarray, i); + fd->sockets = NULL; + fd->added = scheme_make_integer(0); + fd->alloc = scheme_make_integer(0); + fd->handles = NULL; + fd->num_handles = scheme_make_integer(0); + fd->no_sleep = NULL; + fd->wait_event_mask = scheme_make_integer(0); + fd->wait_array = NULL; + reset_wait_array(fdarray); + } } #endif return fdarray; @@ -780,11 +808,12 @@ void *scheme_get_fdset(void *fdarray, int pos) void scheme_fdzero(void *fd) { -#if defined(FILES_HAVE_FDS) || defined(USE_SOCKETS_TCP) - FD_ZERO((fd_set *)fd); -#endif #if defined(WIN32_FD_HANDLES) - ((win_extended_fd_set *)fd)->added = 0; + scheme_init_fdset_array(fd, 1); +#else +# if defined(FILES_HAVE_FDS) || defined(USE_SOCKETS_TCP) + FD_ZERO((fd_set *)fd); +# endif #endif } @@ -793,37 +822,64 @@ void scheme_fdzero(void *fd) void scheme_fdclr(void *fd, int n) { #if defined(WIN32_FD_HANDLES) - if (FD_ISSET(n, ((fd_set *)fd))) - --((win_extended_fd_set *)fd)->added; -#endif -#if defined(FILES_HAVE_FDS) || defined(USE_SOCKETS_TCP) + win_extended_fd_set *efd = (win_extended_fd_set *)fd; + int i; + for (i = SCHEME_INT_VAL(efd->added); i--; ) { + if (efd->sockets[i] == n) + efd->sockets[i] = INVALID_SOCKET; + } +#else +# if defined(FILES_HAVE_FDS) || defined(USE_SOCKETS_TCP) FD_CLR((unsigned)n, ((fd_set *)fd)); +# endif #endif } void scheme_fdset(void *fd, int n) { #if defined(WIN32_FD_HANDLES) - if (!FD_ISSET(n, ((fd_set *)fd))) - ((win_extended_fd_set *)fd)->added++; -#endif -#if defined(FILES_HAVE_FDS) || defined(USE_SOCKETS_TCP) -# ifdef STORED_ACTUAL_FDSET_LIMIT + win_extended_fd_set *efd = (win_extended_fd_set *)fd; + if (SCHEME_INT_VAL(efd->added) >= SCHEME_INT_VAL(efd->alloc)) { + SOCKET *naya; + int na; + na = (SCHEME_INT_VAL(efd->alloc) * 2) + 10; + naya = (SOCKET *)scheme_malloc_atomic(na * sizeof(SOCKET)); + memcpy(naya, efd->sockets, SCHEME_INT_VAL(efd->alloc) * sizeof(SOCKET)); + efd->sockets = naya; + efd->alloc = scheme_make_integer(na); + reset_wait_array(efd); + } + efd->sockets[SCHEME_INT_VAL(efd->added)] = n; + efd->added = scheme_make_integer(1 + SCHEME_INT_VAL(efd->added)); +#else +# if defined(FILES_HAVE_FDS) || defined(USE_SOCKETS_TCP) +# ifdef STORED_ACTUAL_FDSET_LIMIT int mx; mx = FDSET_LIMIT(fd); if (n > mx) FDSET_LIMIT(fd) = n; -# endif +# endif FD_SET(n, ((fd_set *)fd)); +# endif #endif } int scheme_fdisset(void *fd, int n) { -#if defined(FILES_HAVE_FDS) || defined(USE_SOCKETS_TCP) - return FD_ISSET(n, ((fd_set *)fd)); -#else +#if defined(WIN32_FD_HANDLES) + win_extended_fd_set *efd = (win_extended_fd_set *)fd; + int i; + for (i = SCHEME_INT_VAL(efd->added); i--; ) { + if (efd->sockets[i] == n) + return 1; + } return 0; +#else +# if defined(FILES_HAVE_FDS) || defined(USE_SOCKETS_TCP) + return FD_ISSET(n, ((fd_set *)fd)); +# else + return 0; +# endif #endif } @@ -834,19 +890,19 @@ void scheme_add_fd_handle(void *h, void *fds, int repost) OS_SEMAPHORE_TYPE *hs; int i, *rps; - i = efd->num_handles; - hs = MALLOC_N_ATOMIC(OS_SEMAPHORE_TYPE, i + 3); - /* Leave room for two more -^ */ - rps = MALLOC_N_ATOMIC(int, i + 3); + i = SCHEME_INT_VAL(efd->num_handles); + hs = MALLOC_N_ATOMIC(OS_SEMAPHORE_TYPE, i + 1); + rps = MALLOC_N_ATOMIC(int, i + 1); hs[i] = (OS_SEMAPHORE_TYPE)h; rps[i] = repost; while (i--) { hs[i] = efd->handles[i]; rps[i] = efd->repost_sema[i]; } - efd->num_handles++; - efd->handles= hs; + efd->num_handles = scheme_make_integer(1 + SCHEME_INT_VAL(efd->num_handles)); + efd->handles = hs; efd->repost_sema = rps; + reset_wait_array(efd); #else /* Do nothing. */ #endif @@ -856,7 +912,7 @@ void scheme_add_fd_nosleep(void *fds) { #if defined(WIN32_FD_HANDLES) win_extended_fd_set *efd = (win_extended_fd_set *)fds; - efd->no_sleep = 1; + efd->no_sleep = scheme_true; #else #endif } @@ -864,12 +920,147 @@ void scheme_add_fd_nosleep(void *fds) void scheme_add_fd_eventmask(void *fds, int mask) { #if defined(WIN32_FD_HANDLES) - ((win_extended_fd_set *)fds)->wait_event_mask |= mask; + win_extended_fd_set *efd = (win_extended_fd_set *)fds; + efd->wait_event_mask = scheme_make_integer(mask | SCHEME_INT_VAL(efd->wait_event_mask)); #endif } void scheme_collapse_win_fd(void *fds) { +#if defined(WIN32_FD_HANDLES) + win_extended_fd_set *rfd, *wfd, *efd; + HANDLE *wa, e; + int i, p = 0, mask, j; + SOCKET s; + + rfd = (win_extended_fd_set *)fds; + wfd = (win_extended_fd_set *)scheme_get_fdset(fds, 1); + efd = (win_extended_fd_set *)scheme_get_fdset(fds, 2); + + if (rfd->combined_wait_array) { + /* clean up */ + for (i = SCHEME_INT_VAL(rfd->added); i--; ) { + if (rfd->sockets[i] != INVALID_SOCKET) + WSAEventSelect(rfd->sockets[i], NULL, 0); + } + for (i = SCHEME_INT_VAL(wfd->added); i--; ) { + if (wfd->sockets[i] != INVALID_SOCKET) + WSAEventSelect(wfd->sockets[i], NULL, 0); + } + for (i = SCHEME_INT_VAL(efd->added); i--; ) { + if (efd->sockets[i] != INVALID_SOCKET) + WSAEventSelect(efd->sockets[i], NULL, 0); + } + p = SCHEME_INT_VAL(rfd->num_handles); + for (i = SCHEME_INT_VAL(rfd->combined_len); i-- > p; ) { + WSACloseEvent(rfd->combined_wait_array[i]); + } + rfd->combined_wait_array = NULL; + } else { + /* merge */ + if (SCHEME_INT_VAL(rfd->alloc) < SCHEME_INT_VAL(wfd->alloc)) { + if (SCHEME_INT_VAL(wfd->alloc) < SCHEME_INT_VAL(efd->alloc)) + wa = efd->wait_array; + else + wa = wfd->wait_array; + } else { + if (SCHEME_INT_VAL(rfd->alloc) < SCHEME_INT_VAL(efd->alloc)) + wa = efd->wait_array; + else + wa = rfd->wait_array; + } + + rfd->combined_wait_array = wa; + + p = SCHEME_INT_VAL(rfd->num_handles); + for (i = 0; i < p; i++) { + wa[i] = rfd->handles[i]; + } + + for (i = SCHEME_INT_VAL(rfd->added); i--; ) { + s = rfd->sockets[i]; + if (s != INVALID_SOCKET) { + mask = FD_READ | FD_ACCEPT | FD_CONNECT | FD_CLOSE; + + for (j = SCHEME_INT_VAL(wfd->added); j--; ) { + if (wfd->sockets[j] == s) { + mask |= FD_WRITE; + break; + } + } + + for (j = SCHEME_INT_VAL(efd->added); j--; ) { + if (efd->sockets[j] == s) { + mask |= FD_OOB; + break; + } + } + + e = WSACreateEvent(); + wa[p++] = e; + WSAEventSelect(s, e, mask); + } + } + + for (i = SCHEME_INT_VAL(wfd->added); i--; ) { + s = wfd->sockets[i]; + if (s != INVALID_SOCKET) { + mask = FD_WRITE | FD_CONNECT | FD_CLOSE; + + for (j = SCHEME_INT_VAL(rfd->added); j--; ) { + if (rfd->sockets[j] == s) { + mask = 0; + break; + } + } + + if (mask) { + for (j = SCHEME_INT_VAL(efd->added); j--; ) { + if (efd->sockets[j] == s) { + mask |= FD_OOB; + break; + } + } + + e = WSACreateEvent(); + wa[p++] = e; + WSAEventSelect(s, e, mask); + } + } + } + + for (i = SCHEME_INT_VAL(efd->added); i--; ) { + s = efd->sockets[i]; + if (s != INVALID_SOCKET) { + mask = FD_OOB | FD_CLOSE; + + for (j = SCHEME_INT_VAL(rfd->added); j--; ) { + if (rfd->sockets[j] == s) { + mask = 0; + break; + } + } + + if (mask) { + for (j = SCHEME_INT_VAL(wfd->added); j--; ) { + if (wfd->sockets[j] == s) { + mask = 0; + break; + } + } + + if (mask) { + e = WSACreateEvent(); + wa[p++] = e; + WSAEventSelect(s, e, mask); + } + } + } + } + + rfd->combined_len = scheme_make_integer(p); + } +#endif } /*========================================================================*/ @@ -4612,15 +4803,6 @@ static CSI_proc get_csi(void) return csi; } -MZ_EXTERN void scheme_interrupt_win32_thread(HANDLE th); -void scheme_interrupt_win32_thread(HANDLE th) -{ - CSI_proc csi; - csi = get_csi(); - if (csi) - csi(th); -} - # endif /* forward decl: */ @@ -7827,49 +8009,7 @@ void scheme_release_file_descriptor(void) /* This code is used to implement sleeping when MzScheme is completely blocked on external objects, such as ports. For Unix, sleeping is - essentially just a select(). For Windows, we essentially have to - implement select() ourselves, so that it works with both TCP - connections and stream ports all at once. */ - -/********************* Windows TCP watcher *****************/ - -#if defined(WIN32_FD_HANDLES) -typedef struct -{ - MZTAG_IF_REQUIRED - fd_set *rd, *wr, *ex; -} Tcp_Select_Info; - -#ifdef MZ_XFORM -START_XFORM_SKIP; -#endif - -static long select_for_tcp(void *data) -{ - /* Precise GC: we rely on the fact that a GC can't occur - during this thread's lifetime. */ - Tcp_Select_Info *info = (Tcp_Select_Info *)data; - - select(0, info->rd, info->wr, info->ex, NULL); - - return 0; -} - -#ifdef MZ_XFORM -END_XFORM_SKIP; -#endif - -# ifdef USE_WINSOCK_TCP -# define TCP_T SOCKET -# else -# define TCP_T int -# endif - -# ifndef MZ_PF_INET -# define MZ_PF_INET PF_INET -# endif - -#endif + essentially just a select(). */ /****************** Windows cleanup *****************/ @@ -8017,121 +8157,47 @@ static void default_sleep(float v, void *fds) { long result; OS_SEMAPHORE_TYPE *array, just_two_array[2], break_sema; - int count, *rps, just_two_rps[2]; - int fd_added; + int count, rcount, *rps; if (((win_extended_fd_set *)rd)->no_sleep) return; - fd_added = (((win_extended_fd_set *)rd)->added - || ((win_extended_fd_set *)wr)->added - || ((win_extended_fd_set *)ex)->added); - count = ((win_extended_fd_set *)fds)->num_handles; - array = ((win_extended_fd_set *)fds)->handles; + scheme_collapse_win_fd(fds); /* merges */ + + rcount = SCHEME_INT_VAL(((win_extended_fd_set *)fds)->num_handles); + count = SCHEME_INT_VAL(((win_extended_fd_set *)fds)->combined_len); + array = ((win_extended_fd_set *)fds)->combined_wait_array; rps = ((win_extended_fd_set *)fds)->repost_sema; /* add break semaphore: */ if (!count) { array = just_two_array; - rps = just_two_rps; } - rps[count] = 0; break_sema = scheme_break_semaphore; array[count++] = break_sema; - if (count && !fd_added) { - /* Simple: just wait for HANDLE-based input: */ - /* Extensions may handle events */ - if (((win_extended_fd_set *)fds)->wait_event_mask - && GetQueueStatus(((win_extended_fd_set *)fds)->wait_event_mask)) - result = WAIT_TIMEOUT; /* doesn't matter... */ - else { - DWORD msec; - if (v) { - if (v > 100000) - msec = 100000000; - else - msec = (DWORD)(v * 1000); - } else { - msec = INFINITE; - } - result = MsgWaitForMultipleObjects(count, array, FALSE, msec, - ((win_extended_fd_set *)fds)->wait_event_mask); + /* Wait for HANDLE-based input: */ + /* Extensions may handle events */ + if (SCHEME_INT_VAL(((win_extended_fd_set *)fds)->wait_event_mask) + && GetQueueStatus(SCHEME_INT_VAL(((win_extended_fd_set *)fds)->wait_event_mask))) + result = WAIT_TIMEOUT; /* doesn't matter... */ + else { + DWORD msec; + if (v) { + if (v > 100000) + msec = 100000000; + else + msec = (DWORD)(v * 1000); + } else { + msec = INFINITE; } - clean_up_wait(result, array, rps, count); - return; - } else if (count) { - /* What a mess! We must wait for either HANDLE-based input or TCP - status. Use a thread to select() for TCP status, and then - hit a semaphore if the status changes. Meanwhile, in this - thread, wait on both the console input and the semaphore. - When either happens, kill the thread. */ - OS_THREAD_TYPE th; - Tcp_Select_Info *info; - TCP_T fake; - struct Scheme_Thread_Memory *thread_memory; - - info = MALLOC_ONE_RT(Tcp_Select_Info); -#ifdef MZTAG_REQUIRED - info->type = scheme_rt_tcp_select_info; -#endif - - fake = socket(MZ_PF_INET, SOCK_STREAM, 0); - FD_SET(fake, ex); - FD_SET(fake, rd); - - info->rd = rd; - info->wr = wr; - info->ex = ex; - - { - DWORD id; - th = CreateThread(NULL, 4096, - (LPTHREAD_START_ROUTINE)select_for_tcp, - info, 0, &id); - /* Not actually necessary, since GC can't occur during the - thread's life, but better safe than sorry if we change the - code later. */ - thread_memory = scheme_remember_thread((void *)th, 0); - } - - rps[count] = 0; - array[count++] = th; - - if (((win_extended_fd_set *)fds)->wait_event_mask - && GetQueueStatus(((win_extended_fd_set *)fds)->wait_event_mask)) - result = WAIT_TIMEOUT; /* doesn't matter... */ - else { - DWORD msec; - if (v) { - if (v > 100000) - msec = 100000000; - else - msec = (DWORD)(v * 1000); - } else { - msec = INFINITE; - } - result = MsgWaitForMultipleObjects(count, array, FALSE, - v ? (DWORD)(v * 1000) : INFINITE, - ((win_extended_fd_set *)fds)->wait_event_mask); - } - clean_up_wait(result, array, rps, count); - - /* cause selector thread to end: */ - while (closesocket(fake)) { - /* I don't think WSAEINPROGRESS should happen, but just in case... */ - if (WSAGetLastError() != WSAEINPROGRESS) - break; - } - - scheme_interrupt_win32_thread(th); - - WaitForSingleObject(th, INFINITE); - scheme_forget_thread(thread_memory); - CloseHandle(th); - - return; + result = MsgWaitForMultipleObjects(count, array, FALSE, msec, + SCHEME_INT_VAL(((win_extended_fd_set *)fds)->wait_event_mask)); } + clean_up_wait(result, array, rps, rcount); + scheme_collapse_win_fd(fds); /* cleans up */ + + return; } #endif @@ -8523,9 +8589,6 @@ static void register_traversers(void) GC_REG_TRAV(scheme_rt_thread_memory, mark_thread_memory); #endif GC_REG_TRAV(scheme_rt_input_file, mark_input_file); -#if defined(WIN32_FD_HANDLES) - GC_REG_TRAV(scheme_rt_tcp_select_info, mark_tcp_select_info); -#endif GC_REG_TRAV(scheme_rt_output_file, mark_output_file); #ifdef MZ_FDS diff --git a/src/mzscheme/src/schwinfd.h b/src/mzscheme/src/schwinfd.h index adbfb790c4..49eb39fe56 100644 --- a/src/mzscheme/src/schwinfd.h +++ b/src/mzscheme/src/schwinfd.h @@ -2,18 +2,26 @@ #if defined(WINDOWS_PROCESSES) || defined(DETECT_WIN32_CONSOLE_STDIN) || defined(USE_BEOS_PORT_THREADS) # ifndef NO_STDIO_THREADS typedef struct { - fd_set set; + /* All fields must be pointers */ - int added; + SOCKET *sockets; - int num_handles; + Scheme_Object *added; /* fixnum */ + Scheme_Object *alloc; /* fixnum */ + + Scheme_Object *num_handles; /* fixnum */ OS_SEMAPHORE_TYPE *handles; int *repost_sema; - int no_sleep; + Scheme_Object *no_sleep; /* boolean */ - int wait_event_mask; + Scheme_Object *wait_event_mask; /* fixnum */ + + HANDLE *wait_array; + + HANDLE *combined_wait_array; + Scheme_Object *combined_len; /* fixnum */ } win_extended_fd_set; # endif #endif diff --git a/src/worksp/gc2/make.ss b/src/worksp/gc2/make.ss index edf7fd12eb..f7c8abe7e3 100644 --- a/src/worksp/gc2/make.ss +++ b/src/worksp/gc2/make.ss @@ -233,7 +233,7 @@ (define dll "../../../lib/libmzsch3mxxxxxxx.dll") (define exe "../../../MzScheme.exe") -(define libs "kernel32.lib user32.lib wsock32.lib shell32.lib advapi32.lib") +(define libs "kernel32.lib user32.lib ws2_32.lib shell32.lib advapi32.lib") (define (link-dll objs delayloads sys-libs dll link-options exe?) (let ([ms (if (file-exists? dll) diff --git a/src/worksp/libmred/libmred.vcproj b/src/worksp/libmred/libmred.vcproj index 8b3a373ec5..8911952070 100644 --- a/src/worksp/libmred/libmred.vcproj +++ b/src/worksp/libmred/libmred.vcproj @@ -65,7 +65,7 @@