windows socket-wait rewrite

svn: r14060
This commit is contained in:
Matthew Flatt 2009-03-11 22:08:32 +00:00
parent 356c01884f
commit 83034ae9d6
10 changed files with 350 additions and 358 deletions

View File

@ -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,

View File

@ -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));

View File

@ -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;

View File

@ -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);

View File

@ -104,6 +104,7 @@ typedef struct {
static void init_thread_memory();
# define WIN32_FD_HANDLES
# include <winsock2.h>
# include <windows.h>
# include <process.h>
# include <signal.h>
@ -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

View File

@ -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

View File

@ -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)

View File

@ -65,7 +65,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="ComCtl32.lib Glu32.lib OpenGL32.lib Unicows.lib WinMM.lib WSock32.lib User32.lib Gdi32.lib Shell32.lib Comdlg32.lib Advapi32.lib Ole32.lib"
AdditionalDependencies="ComCtl32.lib Glu32.lib OpenGL32.lib Unicows.lib WinMM.lib WS2_32.lib User32.lib Gdi32.lib Shell32.lib Comdlg32.lib Advapi32.lib Ole32.lib"
OutputFile="..\..\..\lib\$(ProjectName)xxxxxxx.dll"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
@ -152,7 +152,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="ComCtl32.lib Glu32.lib OpenGL32.lib Unicows.lib WinMM.lib WSock32.lib User32.lib Gdi32.lib Shell32.lib Comdlg32.lib Advapi32.lib Ole32.lib"
AdditionalDependencies="ComCtl32.lib Glu32.lib OpenGL32.lib Unicows.lib WinMM.lib WS2_32.lib User32.lib Gdi32.lib Shell32.lib Comdlg32.lib Advapi32.lib Ole32.lib"
OutputFile="..\..\..\lib\$(ProjectName)xxxxxxx.dll"
SuppressStartupBanner="true"
GenerateDebugInformation="true"

View File

@ -66,7 +66,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="Unicows.lib WSock32.lib Shell32.lib User32.lib"
AdditionalDependencies="Unicows.lib WS2_32.lib Shell32.lib User32.lib"
OutputFile="..\..\..\lib\$(ProjectName)xxxxxxx.dll"
SuppressStartupBanner="true"
GenerateDebugInformation="true"
@ -154,7 +154,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="Unicows.lib WSock32.lib Shell32.lib User32.lib"
AdditionalDependencies="Unicows.lib WS2_32.lib Shell32.lib User32.lib"
OutputFile="..\..\..\lib\$(ProjectName)xxxxxxx.dll"
SuppressStartupBanner="true"
GenerateDebugInformation="true"

View File

@ -69,7 +69,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386 /DELAYLOAD:libmzschxxxxxxx.dll /DELAYLOAD:libmzgcxxxxxxx.dll /DELAYLOAD:libmredxxxxxxx.dll"
AdditionalDependencies="Unicows.lib WSock32.lib User32.lib Advapi32.lib delayimp.lib"
AdditionalDependencies="Unicows.lib WS2_32.lib User32.lib Advapi32.lib delayimp.lib"
OutputFile="..\..\..\$(ProjectName)CGC.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -155,7 +155,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386 /DELAYLOAD:libmzschxxxxxxx.dll /DELAYLOAD:libmzgcxxxxxxx.dll /DELAYLOAD:libmredxxxxxxx.dll"
AdditionalDependencies="Unicows.lib WSock32.lib User32.lib Advapi32.lib delayimp.lib"
AdditionalDependencies="Unicows.lib WS2_32.lib User32.lib Advapi32.lib delayimp.lib"
OutputFile="..\..\..\$(ProjectName)CGC.exe"
SuppressStartupBanner="true"
IgnoreDefaultLibraryNames="libcd.lib"