int os2ClientSelect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { static BOOL FirstTime=TRUE; static haveTCPIP=TRUE; ULONG timeout_ms; ULONG postCount, start_millis,now_millis; char faildata[16]; struct select_data sd; BOOL any_ready; int np,ns, i,ready_handles,n; APIRET rc; sd.have_read=FALSE; sd.have_write=FALSE; sd.socket_nread=0; sd.socket_nwrite=0; sd.socket_ntotal=0; sd.max_fds=31; ready_handles=0; any_ready=FALSE; sd.pipe_ntotal=0; sd.pipe_have_write=FALSE; if(FirstTime){ /* First load the so32dll.dll module and get a pointer to the SELECT fn */ if((rc=DosLoadModule(faildata,sizeof(faildata),"SO32DLL",&hmod_so32dll))!=0){ fprintf(stderr, "Could not load module so32dll.dll, rc = %d. Error note %s\n",rc,faildata); haveTCPIP=FALSE; } if((rc = DosQueryProcAddr(hmod_so32dll, 0, "SELECT", (PPFN)&os2_tcp_select))!=0){ fprintf(stderr, "Could not query address of SELECT, rc = %d.\n",rc); haveTCPIP=FALSE; } /* Call these a first time to set the semaphore */ rc = DosCreateEventSem(NULL, &hPipeSem, DC_SEM_SHARED, FALSE); if(rc) { fprintf(stderr, "Could not create event semaphore, rc=%d\n",rc); return(-1); } rc = DosResetEventSem(hPipeSem, &postCount); FirstTime = FALSE; } /* Set up the time delay structs */ if(timeout!=NULL) { timeout_ms=timeout->tv_sec*1000+timeout->tv_usec/1000; } else { timeout_ms=1000000; } /* This should be large enough... */ if(timeout_ms>0) start_millis=os2_get_sys_millis(); /* Copy the masks */ {FD_ZERO(&sd.read_copy);} {FD_ZERO(&sd.write_copy);} if(readfds!=NULL){ XFD_COPYSET(readfds,&sd.read_copy); sd.have_read=TRUE;} if(writefds!=NULL) {XFD_COPYSET(writefds,&sd.write_copy);sd.have_write=TRUE;} /* And zero the original masks */ if(sd.have_read){ FD_ZERO(readfds);} if(sd.have_write) {FD_ZERO(writefds);} if(exceptfds != NULL) {FD_ZERO(exceptfds);} /* Now we parse the fd_sets passed to select and separate pipe/sockets */ n = os2_parse_select(&sd,nfds); if(n == -1) { errno = EBADF; return (-1); } /* Now we have three cases: either we have sockets, pipes, or both */ /* We handle all three cases differently to optimize things */ /* Case 1: only pipes! */ if((sd.pipe_ntotal >0) && (!sd.socket_ntotal)){ np = os2_check_pipes(&sd,readfds,writefds); if(np > 0){ return (np); } else if (np == -1) { return(-1); } while(!any_ready){ rc = DosWaitEventSem(hPipeSem, timeout_ms); if(rc == 640) { return(0); } if((rc != 0) && (rc != 95)) {errno= EBADF; return(-1);} np = os2_check_pipes(&sd,readfds,writefds); if (np > 0){ return(np); } else if (np < 0){ return(-1); } } } /* Case 2: only sockets. Just let the os/2 tcp select do the work */ if((sd.socket_ntotal > 0) && (!sd.pipe_ntotal)){ ns = os2_check_sockets(&sd, readfds, writefds, timeout_ms); return (ns); } /* Case 3: combination of both */ if((sd.socket_ntotal > 0) && (sd.pipe_ntotal)){ np = os2_check_pipes(&sd,readfds,writefds); if(np > 0){ any_ready=TRUE; ready_handles += np; } else if (np == -1) { return(-1); } ns = os2_check_sockets(&sd,readfds,writefds, 0); if(ns>0){ ready_handles+=ns; any_ready = TRUE; } else if (ns == -1) {return(-1);} while (!any_ready && timeout_ms){ rc = DosWaitEventSem(hPipeSem, 10L); if(rc == 0){ np = os2_check_pipes(&sd,readfds,writefds); if(np > 0){ ready_handles+=np; any_ready = TRUE; } else if (np == -1) { return(-1); } } ns = os2_check_sockets(&sd,readfds,writefds,exceptfds, 0); if(ns>0){ ready_handles+=ns; any_ready = TRUE; } else if (ns == -1) {return(-1);} if (i%8 == 0) { now_millis = os2_get_sys_millis(); if((now_millis-start_millis) > timeout_ms) timeout_ms = 0; } i++; } } return(ready_handles); }
void FlushAllOutput(void) { register int index, base; register fd_mask mask; /* raphael */ OsCommPtr oc; register ClientPtr client; Bool newoutput = NewOutputPending; #if defined(WIN32) fd_set newOutputPending; #endif if (FlushCallback) CallCallbacks(&FlushCallback, NULL); if (!newoutput) return; /* * It may be that some client still has critical output pending, * but he is not yet ready to receive it anyway, so we will * simply wait for the select to tell us when he's ready to receive. */ CriticalOutputPending = FALSE; NewOutputPending = FALSE; #ifndef WIN32 for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++) { mask = OutputPending.fds_bits[base]; OutputPending.fds_bits[base] = 0; while (mask) { index = ffs(mask) - 1; mask &= ~lowbit(mask); if ((index = ConnectionTranslation[(base * (sizeof(fd_mask) * 8)) + index]) == 0) continue; client = clients[index]; if (client->clientGone) continue; oc = (OsCommPtr) client->osPrivate; if (FD_ISSET(oc->fd, &ClientsWithInput)) { FD_SET(oc->fd, &OutputPending); /* set the bit again */ NewOutputPending = TRUE; } else (void) FlushClient(client, oc, (char *) NULL, 0); } } #else /* WIN32 */ FD_ZERO(&newOutputPending); for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++) { index = XFD_FD(&OutputPending, base); if ((index = GetConnectionTranslation(index)) == 0) continue; client = clients[index]; if (client->clientGone) continue; oc = (OsCommPtr) client->osPrivate; if (FD_ISSET(oc->fd, &ClientsWithInput)) { FD_SET(oc->fd, &newOutputPending); /* set the bit again */ NewOutputPending = TRUE; } else (void) FlushClient(client, oc, (char *) NULL, 0); } XFD_COPYSET(&newOutputPending, &OutputPending); #endif /* WIN32 */ }