From f4092abdf94af6a99aff944d6264bc1284e8bdd4 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 10 Oct 2011 17:43:39 +0200 Subject: Imported nx-X11-3.1.0-1.tar.gz Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository --- .../Xserver/hw/xfree86/os-support/os2/os2_select.c | 497 +++++++++++++++++++++ 1 file changed, 497 insertions(+) create mode 100644 nx-X11/programs/Xserver/hw/xfree86/os-support/os2/os2_select.c (limited to 'nx-X11/programs/Xserver/hw/xfree86/os-support/os2/os2_select.c') diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/os2/os2_select.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/os2/os2_select.c new file mode 100644 index 000000000..395104242 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/os2/os2_select.c @@ -0,0 +1,497 @@ +/* $XConsortium: os2_select.c /main/6 1996/10/27 11:48:55 kaleb $ */ + + + + +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/os2/os2_select.c,v 3.9 2003/03/25 04:18:24 dawes Exp $ */ + +/* + * (c) Copyright 1996 by Sebastien Marineau + * + * Modified 1999 by Holger.Veit@gmd.de + * Modified 2004 by Frank Giessler + * + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * HOLGER VEIT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Sebastien Marineau shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Sebastien Marineau. + * + */ + +/* os2_select.c: reimplementation of the xserver select(), optimized for speed */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#define I_NEED_OS2_H +#define INCL_DOSSEMAPHORES +#define INCL_DOSPROFILE +#define INCL_DOSPROCESS +#define INCL_DOSFILEMGR +#define INCL_DOSMISC +#define INCL_DOSMODULEMGR + + +#include +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +#include "os2_select.h" + +int os2MouseQueueQuery(); +int os2KbdQueueQuery(); +void os2RecoverFromPopup(); +void os2CheckPopupPending(); +void os2SocketMonitorThread(); +extern BOOL os2PopupErrorPending; + +extern HEV hKbdSem; +extern HEV hMouseSem; +extern HEV hevServerHasFocus; +HEV hPipeSem; +HEV hSocketSem; +HEV hActivateSocketSem; +HEV hSwitchToSem; +static HMUX hSelectWait; +SEMRECORD SelectMuxRecord[5]; +HMODULE hmod_so32dll; +static struct select_data sd; + +static int (*os2_tcp_select)(int *,int,int,int,long); +static int (*os2_so_cancel)(int); +static int (*os2_sock_errno)(); +int os2_set_error(ULONG); +extern int _files[]; + + + +/* This is a new implementation of select, for improved efficiency */ +/* This function performs select() on sockets */ +/* but uses OS/2 internal fncts to check mouse */ +/* and keyboard. S. Marineau, 27/4/96 */ + +/* This is still VERY messy */ + +/* A few note on optimizations: this select has been tuned for maximum +* performance, and thus has a different approach than a general-purpose +* select. It should not be used in another app without modifications. Further, +* it may need modifications if the Xserver os code is modified +* Assumptions: this is never called with anything in exceptfds. This is +* silently ignored. Further, if any pipes are specified in the write mask, it is +* because they have just been stuffed full by the xserver. There is not much +* in immediately returning with those bits set. Instead, we block on the +* semaphore for at least one tick, which will let the client at least start +* to flush the pipe. */ + +int os2PseudoSelect(nfds,readfds,writefds,exceptfds,timeout) + int nfds; + fd_set *readfds,*writefds,*exceptfds; + struct timeval *timeout; +{ + + static BOOL FirstTime=TRUE; + + int n,ns,np; + int ready_handles; + ULONG timeout_ms; + BOOL any_ready; + ULONG semKey,postCount; + APIRET rc; + char faildata[16]; + static int Socket_Tid; + + 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; + + /* Stuff we have to do the first time this is called to set up various parameters */ + + 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) { + FatalError("Could not load module so32dll.dll, rc = %d. Error note %s\n",rc,faildata); + } + if ((rc = DosQueryProcAddr(hmod_so32dll, 0, "SELECT", (PPFN)&os2_tcp_select))!=0) { + FatalError("Could not query address of SELECT, rc = %d.\n",rc); + } + if ((rc = DosQueryProcAddr(hmod_so32dll, 0, "SO_CANCEL", (PPFN)&os2_so_cancel))!=0) { + FatalError("Could not query address of SO_CANCEL, rc = %d.\n",rc); + } + if ((rc = DosQueryProcAddr(hmod_so32dll, 0, "SOCK_ERRNO", (PPFN)&os2_sock_errno))!=0) { + FatalError("Could not query address of SOCK_ERRNO, rc = %d.\n",rc); + } + + /* Call these a first time to set the semaphore */ + xf86OsMouseEvents(); + xf86KbdEvents(); + + DosCreateEventSem(NULL, &hSocketSem,DC_SEM_SHARED,FALSE); + DosResetEventSem(hSocketSem,&postCount); + + DosCreateEventSem(NULL, &hActivateSocketSem, DC_SEM_SHARED, FALSE); + DosResetEventSem(hActivateSocketSem, &postCount); + + DosCreateEventSem(NULL, &hSwitchToSem, DC_SEM_SHARED, FALSE); + DosResetEventSem(hSwitchToSem, &postCount); + + Socket_Tid = _beginthread(os2SocketMonitorThread, NULL, 0x2000,(void *) NULL); + xf86Msg(X_INFO, + "Started Socket monitor thread, TID=%d\n",Socket_Tid); + + SelectMuxRecord[0].hsemCur = (HSEM)hMouseSem; + SelectMuxRecord[0].ulUser = MOUSE_SEM_KEY; + SelectMuxRecord[1].hsemCur = (HSEM)hKbdSem; + SelectMuxRecord[1].ulUser = KBD_SEM_KEY; + SelectMuxRecord[2].hsemCur = (HSEM)hPipeSem; + SelectMuxRecord[2].ulUser = PIPE_SEM_KEY; + SelectMuxRecord[3].hsemCur = (HSEM)hSocketSem; + SelectMuxRecord[3].ulUser = SOCKET_SEM_KEY; + SelectMuxRecord[4].hsemCur = (HSEM)hSwitchToSem; + SelectMuxRecord[4].ulUser = SWITCHTO_SEM_KEY; + + rc = DosCreateMuxWaitSem(NULL, &hSelectWait, 5, SelectMuxRecord, + DC_SEM_SHARED | DCMW_WAIT_ANY); + if (rc) { + xf86Msg(X_ERROR,"Could not create MuxWait semaphore, rc=%d\n",rc); + } + FirstTime = FALSE; + } + + rc = DosResetEventSem(hActivateSocketSem, &postCount); + /* 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... */ + } + + /* Zero our local fd_masks */ + {FD_ZERO(&sd.read_copy);} + {FD_ZERO(&sd.write_copy);} + + /* Copy the masks for later use */ + 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); + + /* Now check if we have sockets ready! */ + + if (sd.socket_ntotal > 0) { + ns = os2_poll_sockets(&sd,readfds,writefds); + if (ns>0) { + ready_handles+=ns; + any_ready = TRUE; + } else if (ns == -1) { + return(-1); + } + } + + /* And pipes */ + + if (sd.pipe_ntotal > 0) { + np = os2_check_pipes(&sd,readfds,writefds); + if (np > 0) { + ready_handles+=np; + any_ready = TRUE; + } else if (np == -1) { + return(-1); + } + } + + /* And finally poll input devices */ + if(!os2MouseQueueQuery() || !os2KbdQueueQuery() ) any_ready = TRUE; + + if (xf86Info.vtRequestsPending) any_ready=TRUE; + + if (os2PopupErrorPending) + os2RecoverFromPopup(); + + if (!any_ready && timeout_ms) { + DosResetEventSem(hSocketSem,&postCount); + + /* Activate the socket thread */ + if (sd.socket_ntotal>0) { + rc = DosPostEventSem(hActivateSocketSem); + } + + rc = DosWaitMuxWaitSem(hSelectWait, timeout_ms, &semKey); + + /* If our socket monitor thread is still blocked in os2_tcp_select() + * we have to wake it up by calling os2_so_cancel(). + * After that, call os2_tcp_select() once more to get rid of + * error SOCEINTR (10004) + */ + if (sd.socket_ntotal>0) { + rc = DosQueryEventSem(hSocketSem, &postCount); + + if (postCount == 0) { /* os2_select still blocked */ + int i,f,g; + struct select_data *sd_ptr=&sd; + + if (sd.socket_nread > 0) { + for (i=0; itcp_select_mask[i]; + os2_so_cancel(f); + os2_tcp_select(&g, 1, 0, 0, 0); /* get rid of error 10004 */ + } + } + if (sd.socket_nwrite > 0) { + for (i=sd.socket_nread; + itcp_select_mask[i]; + os2_so_cancel(f); + os2_tcp_select(&g, 0, 1, 0, 0); /* get rid of error 10004 */ + } + } + } else { /* not blocked, something must be ready -> get it */ + ns = os2_poll_sockets(&sd,readfds,writefds); + if (ns>0) { + ready_handles+=ns; + } else if (ns == -1) { + return(-1); + } + } + } + if (sd.pipe_ntotal > 0) { + rc = DosQueryEventSem(hPipeSem,&postCount); + if (postCount > 0) { + np = os2_check_pipes(&sd,readfds,writefds); + if (np > 0) { + ready_handles+=np; + } else if (np == -1) { + return(-1); + } + } + } + } + /* The polling of sockets/pipe automatically set the proper bits */ + return (ready_handles); +} + + +int os2_parse_select(sd,nfds) + struct select_data *sd; + int nfds; +{ + int i; + /* First we determine up to which descriptor we need to check. */ + /* No need to check up to 256 if we don't have to (and usually we dont...)*/ + /* Note: stuff here is hardcoded for fd_sets which are int[8] as in EMX!!! */ + + if (nfds > sd->max_fds) { + for (i=0;i<((FD_SETSIZE+31)/32);i++) { + if (sd->read_copy.fds_bits[i] || + sd->write_copy.fds_bits[i]) + sd->max_fds=(i*32) +32; + } + } else { sd->max_fds = nfds; } + + /* Check if this is greater than specified in select() call */ + if(sd->max_fds > nfds) sd->max_fds = nfds; + + if (sd->have_read) { + for (i = 0; i < sd->max_fds; ++i) { + if (FD_ISSET (i, &sd->read_copy)) { + if(_files[i] & F_SOCKET) { + sd->tcp_select_mask[sd->socket_ntotal]=_getsockhandle(i); + sd->tcp_emx_handles[sd->socket_ntotal]=i; + sd->socket_ntotal++; sd->socket_nread++; + } else if (_files[i] & F_PIPE) { + sd -> pipe_ntotal++; + } + } + } + } + if (sd->have_write) { + for (i = 0; i < sd->max_fds; ++i) { + if (FD_ISSET (i, &sd->write_copy)) { + if (_files[i] & F_SOCKET) { + sd->tcp_select_mask[sd->socket_ntotal]=_getsockhandle(i); + sd->tcp_emx_handles[sd->socket_ntotal]=i; + sd->socket_ntotal++; sd->socket_nwrite++; + } else if (_files[i] & F_PIPE) { + sd -> pipe_ntotal++; + sd -> pipe_have_write=TRUE; + } + } + } + } + return(sd->socket_ntotal); +} + + +int os2_poll_sockets(sd,readfds,writefds) + struct select_data *sd; + fd_set *readfds,*writefds; +{ + int e,i; + int j,n; + + memcpy(sd->tcp_select_copy,sd->tcp_select_mask, + sd->socket_ntotal*sizeof(int)); + + e = os2_tcp_select(sd->tcp_select_copy,sd->socket_nread, + sd->socket_nwrite, 0, 0); + + if (e == 0) return(e); + + /* We have something ready? */ + if (e>0) { + j = 0; n = 0; + for (i = 0; i < sd->socket_nread; ++i, ++j) + if (sd->tcp_select_copy[j] != -1) { + FD_SET (sd->tcp_emx_handles[j], readfds); + n ++; + } + for (i = 0; i < sd->socket_nwrite; ++i, ++j) + if (sd->tcp_select_copy[j] != -1) { + FD_SET (sd->tcp_emx_handles[j], writefds); + n ++; + } + errno = 0; + + return n; + } + if (e<0) { + /*Error -- TODO */ + xf86Msg(X_ERROR,"Error in server select! sock_errno = %d\n",os2_sock_errno()); + errno = EBADF; + return (-1); + } +} + +/* Check to see if anything is ready on pipes */ + +int os2_check_pipes(sd,readfds,writefds) + struct select_data *sd; + fd_set *readfds,*writefds; +{ + int i,e; + ULONG ulPostCount; + PIPESEMSTATE pipeSemState[128]; + APIRET rc; + + e = 0; + rc = DosResetEventSem(hPipeSem,&ulPostCount); + rc = DosQueryNPipeSemState((HSEM) hPipeSem, (PPIPESEMSTATE)&pipeSemState, + sizeof(pipeSemState)); + if(rc) xf86Msg(X_ERROR,"SELECT: rc from QueryNPipeSem: %d\n",rc); + i=0; + while (pipeSemState[i].fStatus != 0) { +/* xf86Msg(X_INFO,"SELECT: sem entry, stat=%d, flag=%d, key=%d,avail=%d\n", + pipeSemState[i].fStatus,pipeSemState[i].fFlag,pipeSemState[i].usKey, + pipeSemState[i].usAvail); */ + if ((pipeSemState[i].fStatus == 1) && + (FD_ISSET(pipeSemState[i].usKey,&sd->read_copy))) { + FD_SET(pipeSemState[i].usKey,readfds); + e++; + } else if ((pipeSemState[i].fStatus == 2) && + (FD_ISSET(pipeSemState[i].usKey,&sd->write_copy))) { + FD_SET(pipeSemState[i].usKey,writefds); + e++; + } else if ((pipeSemState[i].fStatus == 3) && + ((FD_ISSET(pipeSemState[i].usKey,&sd->read_copy)) || + (FD_ISSET(pipeSemState[i].usKey,&sd->write_copy)) )) { + errno = EBADF; + /* xf86Msg(X_ERROR,"Pipe has closed down, fd=%d\n",pipeSemState[i].usKey); */ + return (-1); + } + i++; + } /* endwhile */ + + errno = 0; + return(e); +} + + +void os2SocketMonitorThread(void *arg) +{ + struct select_data *sd_ptr = &sd; + ULONG ulPostCount; + int e,rc; + + /* Make thread time critical */ + DosSetPriority(2L,3L,0L,0L); + + while (1) { + rc = DosWaitEventSem(hActivateSocketSem, SEM_INDEFINITE_WAIT); + if (rc != 0 ) + xf86Msg(X_ERROR,"Socket monitor: DosWaitEventSem(hActivateSocketSem..) returned %d\n",rc); + + rc = DosResetEventSem(hActivateSocketSem,&ulPostCount); + if (rc != 0 ) + xf86Msg(X_ERROR,"Socket monitor: DosResetEventSem(&hActivateSocketSem..) returned %d\n",rc); + + /* fg300104: + * The next line shouldn't be here, but the DosPostEventSem() + * below will return 299 from time to time under heavy load + */ +/* DosResetEventSem(hSocketSem,&ulPostCount);*/ + + memcpy(sd_ptr->tcp_select_monitor,sd_ptr->tcp_select_mask, + sd_ptr->socket_ntotal*sizeof(int)); + + /* call os2_select(), return only if either something is ready or + * os2_so_cancel() was called + */ + e = os2_tcp_select(sd_ptr->tcp_select_monitor, sd_ptr->socket_nread, + sd_ptr->socket_nwrite, 0, -1); + + if (e>0) { + rc = DosPostEventSem(hSocketSem); + if (rc != 0 ) + xf86Msg(X_ERROR,"Socket monitor: DosPostEventSem(hSocketSem..) returned %d\n",rc); + } else if (e<0) { + rc = os2_sock_errno(); + if (rc != 10004) + xf86Msg(X_ERROR,"Socket monitor: os2_select: sock_errno = %d\n",rc); + } + + rc = DosQueryEventSem(hevServerHasFocus, &ulPostCount); + + /* no need to rush while switched away */ + if ((rc==0) && (ulPostCount==0)) + rc == DosWaitEventSem(hevServerHasFocus,31L); + } +} + -- cgit v1.2.3