|
|
1.1 root 1: /***********************************************************
2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4:
5: All Rights Reserved
6:
7: Permission to use, copy, modify, and distribute this software and its
8: documentation for any purpose and without fee is hereby granted,
9: provided that the above copyright notice appear in all copies and that
10: both that copyright notice and this permission notice appear in
11: supporting documentation, and that the names of Digital or MIT not be
12: used in advertising or publicity pertaining to distribution of the
13: software without specific, written prior permission.
14:
15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21: SOFTWARE.
22:
23: ******************************************************************/
24:
25: /*****************************************************************
26: * OS Depedent input routines:
27: *
28: * WaitForSomething, GetEvent
29: *
30: *****************************************************************/
31:
32: #include "Xos.h" /* for strings, fcntl, time */
33:
34: #include <errno.h>
35: #include <stdio.h>
36: #include "X.h"
37: #include "misc.h"
38:
39: #include <sys/param.h>
40: #include <signal.h>
41: #include "osdep.h"
42: #include "dixstruct.h"
43:
44:
45: extern long AllSockets[];
46: extern long AllClients[];
47: extern long LastSelectMask[];
48: extern long WellKnownConnections;
49: extern long EnabledDevices;
50: extern long ClientsWithInput[];
51: extern long ClientsWriteBlocked[];
52: extern long OutputPending[];
53:
54: extern long ScreenSaverTime; /* milliseconds */
55: extern long ScreenSaverInterval; /* milliseconds */
56: extern ClientPtr ConnectionTranslation[];
57:
58: extern Bool clientsDoomed;
59: extern Bool NewOutputPending;
60: extern Bool AnyClientsWriteBlocked;
61:
62: extern void CheckConnections();
63: extern void EstablishNewConnections();
64:
65: extern int errno;
66:
67: int isItTimeToYield = 1;
68:
69: #ifdef MULTI_X_HACK
70: extern int XMulti;
71: extern int sigwindow_handler();
72: #endif MULTI_X_HACK
73:
74: #ifdef XTESTEXT1
75: /*
76: * defined in xtestext1dd.c
77: */
78: extern int playback_on;
79: #endif /* XTESTEXT1 */
80:
81: /*****************
82: * WaitForSomething:
83: * Make the server suspend until there is
84: * 1. data from clients or
85: * 2. input events available or
86: * 3. ddx notices something of interest (graphics
87: * queue ready, etc.) or
88: * 4. clients that have buffered replies/events are ready
89: *
90: * If the time between INPUT events is
91: * greater than ScreenSaverTime, the display is turned off (or
92: * saved, depending on the hardware). So, WaitForSomething()
93: * has to handle this also (that's why the select() has a timeout.
94: * For more info on ClientsWithInput, see ReadRequestFromClient().
95: * pClientsReady is a mask, the bits set are
96: * indices into the o.s. depedent table of available clients.
97: * (In this case, there is no table -- the index is the socket
98: * file descriptor.)
99: *****************/
100:
101: #ifdef ISOCONN
102: /*
103: * cannot use select in TSAP stuff, so...see TNetAccept
104: * (which calls xselect, which calls select...)
105: */
106:
107: #include <isode/tsap.h>
108: #endif /* ISOCONN */
109:
110: static long timeTilFrob = 0; /* while screen saving */
111:
112: #if (mskcnt>4)
113: /*
114: * This is a macro if mskcnt <= 4
115: */
116: ANYSET(src)
117: long *src;
118: {
119: int i;
120:
121: for (i=0; i<mskcnt; i++)
122: if (src[ i ])
123: return (TRUE);
124: return (FALSE);
125: }
126: #endif
127:
128: WaitForSomething(pClientsReady, nready, pNewClients, nnew)
129: ClientPtr *pClientsReady;
130: int *nready;
131: ClientPtr *pNewClients;
132: int *nnew;
133: {
134: int i;
135: struct timeval waittime, *wt;
136: long timeout;
137: long clientsReadable[mskcnt];
138: long clientsWritable[mskcnt];
139: long curclient;
140: int selecterr;
141: #ifdef ISOCONN
142: int vecp;
143: char *vec[4];
144: struct TSAPdisconnect tds;
145: struct TSAPdisconnect *td = &tds;
146: #endif /* ISOCONN */
147:
148: #ifdef hpux
149: long ready_inputs; /* to tell HIL drivers about input */
150: #endif hpux
151:
152: *nready = 0;
153: *nnew = 0;
154: CLEARBITS(clientsReadable);
155: if (! (ANYSET(ClientsWithInput)))
156: {
157: /* We need a while loop here to handle
158: crashed connections and the screen saver timeout */
159: while (1)
160: {
161: if (ScreenSaverTime)
162: {
163: timeout = ScreenSaverTime - TimeSinceLastInputEvent();
164: if (timeout <= 0) /* may be forced by AutoResetServer() */
165: {
166: long timeSinceSave;
167:
168: if (clientsDoomed)
169: {
170: *nnew = *nready = 0;
171: break;
172: }
173:
174: timeSinceSave = -timeout;
175: if ((timeSinceSave >= timeTilFrob) && (timeTilFrob >= 0))
176: {
177: SaveScreens(SCREEN_SAVER_ON, ScreenSaverActive);
178: if (ScreenSaverInterval)
179: /* round up to the next ScreenSaverInterval */
180: timeTilFrob = ScreenSaverInterval *
181: ((timeSinceSave + ScreenSaverInterval) /
182: ScreenSaverInterval);
183: else
184: timeTilFrob = -1;
185: }
186: timeout = timeTilFrob - timeSinceSave;
187: }
188: else
189: {
190: if (timeout > ScreenSaverTime)
191: timeout = ScreenSaverTime;
192: timeTilFrob = 0;
193: }
194: if (timeTilFrob >= 0)
195: {
196: waittime.tv_sec = timeout / MILLI_PER_SECOND;
197: waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
198: (1000000 / MILLI_PER_SECOND);
199: wt = &waittime;
200: }
201: else
202: {
203: wt = NULL;
204: }
205: }
206: else
207: wt = NULL;
208: #ifdef MULTI_X_HACK
209: if (XMulti) {
210: ipc_block_handler();
211: signal(SIGWINDOW,sigwindow_handler);
212: }
213: #endif MULTI_X_HACK
214: COPYBITS(AllSockets, LastSelectMask);
215: BlockHandler(&wt, LastSelectMask);
216: if (NewOutputPending)
217: FlushAllOutput();
218: #ifdef XTESTEXT1
219: /* XXX how does this interact with new write block handling? */
220: if (playback_on) {
221: wt = &waittime;
222: XTestComputeWaitTime (&waittime);
223: }
224: #endif /* XTESTEXT1 */
225:
226: #ifndef ISOCONN
227: if (AnyClientsWriteBlocked)
228: {
229: COPYBITS(ClientsWriteBlocked, clientsWritable);
230: i = select (MAXSOCKS, LastSelectMask, clientsWritable,
231: (int *) NULL, wt);
232: }
233: else
234: {
235: i = select (MAXSOCKS, LastSelectMask,
236: (int *) NULL, (int *) NULL, wt);
237: }
238: selecterr = errno;
239: #else /* IS ISOCONN */
240: if (AnyClientsWriteBlocked)
241: {
242: int secs = wt->tv_sec;
243: if (secs == 0 && wt->tv_usec != 0)
244: secs = 1;
245: COPYBITS(ClientsWriteBlocked, clientsWritable);
246: i = TNetAccept(&vecp, vec, MAXSOCKS, LastSelectMask,
247: clientsWritable, (int *)NULL, wt->tv_sec, td);
248: }
249: else
250: {
251: int secs = wt->tv_sec;
252: if (secs == 0 && wt->tv_usec != 0)
253: secs = 1;
254: i = TNetAccept(&vecp, vec, MAXSOCKS, LastSelectMask,
255: (int *)NULL, (int *)NULL, secs, td);
256: }
257: /* map errors */
258: if (i < 0) {
259: if (!DR_FATAL(td->td_reason))
260: errno = EWOULDBLOCK;
261: }
262: selecterr = errno;
263: #endif /* ISOCONN */
264: WakeupHandler(i, LastSelectMask);
265: #ifdef XTESTEXT1
266: if (playback_on) {
267: i = XTestProcessInputAction (i, &waittime);
268: }
269: #endif /* XTESTEXT1 */
270: if (i <= 0) /* An error or timeout occurred */
271: {
272: #ifdef ISODEBUG
273: if (isodexbug)
274: fprintf(stderr, "WF: TO or ERR %d\n", i);
275: #endif
276: CLEARBITS(clientsWritable);
277: if (i < 0)
278: if (selecterr == EBADF) /* Some client disconnected */
279: {
280: CheckConnections ();
281: if (! ANYSET (AllClients))
282: return;
283: }
284: else if (selecterr != EINTR)
285: ErrorF("WaitForSomething(): select: errno=%d\n",
286: selecterr);
287: }
288: else
289: {
290: if (AnyClientsWriteBlocked && ANYSET (clientsWritable))
291: {
292: #ifdef ISODEBUG
293: if (isodexbug)
294: fprintf(stderr, "WF: write\n");
295: #endif
296: NewOutputPending = TRUE;
297: ORBITS(OutputPending, clientsWritable, OutputPending);
298: UNSETBITS(ClientsWriteBlocked, clientsWritable);
299: if (! ANYSET(ClientsWriteBlocked))
300: AnyClientsWriteBlocked = FALSE;
301: }
302:
303: #ifdef hpux
304: ready_inputs = (LastSelectMask[0] & EnabledDevices);
305:
306: if (ready_inputs > 0) store_inputs (ready_inputs);
307: /* call the HIL driver to gather inputs. */
308: #endif hpux
309:
310: MASKANDSETBITS(clientsReadable, LastSelectMask, AllClients);
311: #ifdef ISOCONN
312: /*
313: * ISODE version says new connections pending accept if vecp > 0 !!
314: */
315: if (vecp > 0) {
316: #ifdef ISODEBUG
317: if (isodexbug)
318: fprintf(stderr, "WF: CX pending\n");
319: #endif
320: EstablishNewConnections(pNewClients, nnew, vecp, vec);
321: }
322: #else /* ISOCONN */
323: if (LastSelectMask[0] & WellKnownConnections)
324: EstablishNewConnections(pNewClients, nnew);
325: #endif /* ISOCONN */
326: if (*nnew || (LastSelectMask[0] & EnabledDevices)
327: || (ANYSET (clientsReadable)))
328: break;
329: }
330: }
331: }
332: else
333: {
334: COPYBITS(ClientsWithInput, clientsReadable);
335: }
336:
337: if (ANYSET(clientsReadable))
338: {
339: #ifdef ISODEBUG
340: if (isodexbug)
341: fprintf(stderr, "WF: readable\n");
342: #endif
343: for (i=0; i<mskcnt; i++)
344: {
345: while (clientsReadable[i])
346: {
347: curclient = ffs (clientsReadable[i]) - 1;
348: pClientsReady[(*nready)++] =
349: ConnectionTranslation[curclient + (32 * i)];
350: clientsReadable[i] &= ~(1 << curclient);
351: }
352: }
353: }
354: }
355:
356:
357:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.