123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671 |
- /***********************************************************
- Copyright 1987, 1998 The Open Group
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- 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 THE
- OPEN GROUP 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 The Open Group shall not be
- used in advertising or otherwise to promote the sale, use or other dealings
- in this Software without prior written authorization from The Open Group.
- Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
- All Rights Reserved
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of Digital not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
- DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- SOFTWARE.
- ******************************************************************/
- /*****************************************************************
- * OS Dependent input routines:
- *
- * WaitForSomething
- * TimerForce, TimerSet, TimerFree
- *
- *****************************************************************/
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include <X11/Xos.h> /* for strings, fcntl, time */
- #include <errno.h>
- #include <stdio.h>
- #include <X11/X.h>
- #include "misc.h"
- #include "osdep.h"
- #include <X11/Xpoll.h>
- #include "dixstruct.h"
- #include "opaque.h"
- #ifdef DPMSExtension
- #include "dpmsproc.h"
- #endif
- /* This is just a fallback to errno to hide the differences between unix and
- Windows in the code */
- #define GetErrno() errno
- /* modifications by raphael */
- int
- mffs(fd_mask mask)
- {
- int i;
- if (!mask) return 0;
- i = 1;
- while (!(mask & 1))
- {
- i++;
- mask >>= 1;
- }
- return i;
- }
- #ifdef DPMSExtension
- #define DPMS_SERVER
- #include <X11/extensions/dpms.h>
- #endif
- struct _OsTimerRec {
- OsTimerPtr next;
- CARD32 expires;
- CARD32 delta;
- OsTimerCallback callback;
- pointer arg;
- };
- static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
- static void CheckAllTimers(CARD32 now);
- static OsTimerPtr timers = NULL;
- /*****************
- * WaitForSomething:
- * Make the server suspend until there is
- * 1. data from clients or
- * 2. input events available or
- * 3. ddx notices something of interest (graphics
- * queue ready, etc.) or
- * 4. clients that have buffered replies/events are ready
- *
- * If the time between INPUT events is
- * greater than ScreenSaverTime, the display is turned off (or
- * saved, depending on the hardware). So, WaitForSomething()
- * has to handle this also (that's why the select() has a timeout.
- * For more info on ClientsWithInput, see ReadRequestFromClient().
- * pClientsReady is an array to store ready client->index values into.
- *****************/
- int
- WaitForSomething(int *pClientsReady)
- {
- int i;
- struct timeval waittime, *wt;
- INT32 timeout = 0;
- fd_set clientsReadable;
- fd_set clientsWritable;
- int curclient;
- int selecterr;
- int nready;
- fd_set devicesReadable;
- CARD32 now = 0;
- #ifdef SMART_SCHEDULE
- Bool someReady = FALSE;
- #endif
- FD_ZERO(&clientsReadable);
- /* We need a while loop here to handle
- crashed connections and the screen saver timeout */
- while (1)
- {
- /* deal with any blocked jobs */
- if (workQueue)
- ProcessWorkQueue();
- if (XFD_ANYSET (&ClientsWithInput))
- {
- #ifdef SMART_SCHEDULE
- if (!SmartScheduleDisable)
- {
- someReady = TRUE;
- waittime.tv_sec = 0;
- waittime.tv_usec = 0;
- wt = &waittime;
- }
- else
- #endif
- {
- XFD_COPYSET (&ClientsWithInput, &clientsReadable);
- break;
- }
- }
- #ifdef SMART_SCHEDULE
- if (someReady)
- {
- XFD_COPYSET(&AllSockets, &LastSelectMask);
- XFD_UNSET(&LastSelectMask, &ClientsWithInput);
- }
- else
- {
- #endif
- wt = NULL;
- if (timers)
- {
- now = GetTimeInMillis();
- timeout = timers->expires - now;
- if (timeout > 0 && timeout > timers->delta + 250) {
- /* time has rewound. reset the timers. */
- CheckAllTimers(now);
- }
- if (timers) {
- timeout = timers->expires - now;
- if (timeout < 0)
- timeout = 0;
- waittime.tv_sec = timeout / MILLI_PER_SECOND;
- waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
- (1000000 / MILLI_PER_SECOND);
- wt = &waittime;
- }
- }
- XFD_COPYSET(&AllSockets, &LastSelectMask);
- #ifdef SMART_SCHEDULE
- }
- SmartScheduleIdle = TRUE;
- #endif
- BlockHandler((pointer)&wt, (pointer)&LastSelectMask);
- if (NewOutputPending)
- FlushAllOutput();
- /* keep this check close to select() call to minimize race */
- if (dispatchException)
- i = -1;
- else if (AnyClientsWriteBlocked)
- {
- XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable);
- i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
- }
- else
- {
- i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt);
- }
- selecterr = GetErrno();
- WakeupHandler(i, (pointer)&LastSelectMask);
- #ifdef SMART_SCHEDULE
- if (i >= 0)
- {
- SmartScheduleIdle = FALSE;
- SmartScheduleIdleCount = 0;
- if (SmartScheduleTimerStopped)
- (void) SmartScheduleStartTimer ();
- }
- #endif
- if (i <= 0) /* An error or timeout occurred */
- {
- if (dispatchException)
- return 0;
- if (i < 0)
- {
- if (selecterr == EBADF) /* Some client disconnected */
- {
- CheckConnections ();
- if (! XFD_ANYSET (&AllClients))
- return 0;
- }
- else if (selecterr == EINVAL)
- {
- FatalError("WaitForSomething(): select: errno=%d\n",
- selecterr);
- }
- else if (selecterr != EINTR)
- {
- ErrorF("WaitForSomething(): select: errno=%d\n",
- selecterr);
- }
- }
- #ifdef SMART_SCHEDULE
- else if (someReady)
- {
- /*
- * If no-one else is home, bail quickly
- */
- XFD_COPYSET(&ClientsWithInput, &LastSelectMask);
- XFD_COPYSET(&ClientsWithInput, &clientsReadable);
- break;
- }
- #endif
- if (*checkForInput[0] != *checkForInput[1])
- return 0;
- if (timers)
- {
- int expired = 0;
- now = GetTimeInMillis();
- if ((int) (timers->expires - now) <= 0)
- expired = 1;
- while (timers && (int) (timers->expires - now) <= 0)
- DoTimer(timers, now, &timers);
- if (expired)
- return 0;
- }
- }
- else
- {
- fd_set tmp_set;
- if (*checkForInput[0] == *checkForInput[1]) {
- if (timers)
- {
- int expired = 0;
- now = GetTimeInMillis();
- if ((int) (timers->expires - now) <= 0)
- expired = 1;
- while (timers && (int) (timers->expires - now) <= 0)
- DoTimer(timers, now, &timers);
- if (expired)
- return 0;
- }
- }
- #ifdef SMART_SCHEDULE
- if (someReady)
- XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask);
- #endif
- if (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable))
- {
- NewOutputPending = TRUE;
- XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
- XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
- if (! XFD_ANYSET(&ClientsWriteBlocked))
- AnyClientsWriteBlocked = FALSE;
- }
- XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices);
- XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
- XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections);
- if (XFD_ANYSET(&tmp_set))
- QueueWorkProc(EstablishNewConnections, NULL,
- (pointer)&LastSelectMask);
- #ifdef DPMSExtension
- if (XFD_ANYSET (&devicesReadable) && (DPMSPowerLevel != DPMSModeOn))
- DPMSSet(DPMSModeOn);
- #endif
- if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable))
- break;
- }
- }
- nready = 0;
- if (XFD_ANYSET (&clientsReadable))
- {
- for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
- {
- int highest_priority = 0;
- while (clientsReadable.fds_bits[i])
- {
- int client_priority, client_index;
- curclient = ffs (clientsReadable.fds_bits[i]) - 1;
- client_index = /* raphael: modified */
- ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))];
- /* We implement "strict" priorities.
- * Only the highest priority client is returned to
- * dix. If multiple clients at the same priority are
- * ready, they are all returned. This means that an
- * aggressive client could take over the server.
- * This was not considered a big problem because
- * aggressive clients can hose the server in so many
- * other ways :)
- */
- client_priority = clients[client_index]->priority;
- if (nready == 0 || client_priority > highest_priority)
- {
- /* Either we found the first client, or we found
- * a client whose priority is greater than all others
- * that have been found so far. Either way, we want
- * to initialize the list of clients to contain just
- * this client.
- */
- pClientsReady[0] = client_index;
- highest_priority = client_priority;
- nready = 1;
- }
- /* the following if makes sure that multiple same-priority
- * clients get batched together
- */
- else if (client_priority == highest_priority)
- {
- pClientsReady[nready++] = client_index;
- }
- clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient);
- }
- }
- }
- return nready;
- }
- #if 0
- /*
- * This is not always a macro.
- */
- ANYSET(FdMask *src)
- {
- int i;
- for (i=0; i<mskcnt; i++)
- if (src[ i ])
- return (TRUE);
- return (FALSE);
- }
- #endif
- /* If time has rewound, re-run every affected timer.
- * Timers might drop out of the list, so we have to restart every time. */
- static void
- CheckAllTimers(CARD32 now)
- {
- OsTimerPtr timer;
- start:
- for (timer = timers; timer; timer = timer->next) {
- if (timer->expires - now > timer->delta + 250) {
- TimerForce(timer);
- goto start;
- }
- }
- }
- static void
- DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev)
- {
- CARD32 newTime;
- *prev = timer->next;
- timer->next = NULL;
- newTime = (*timer->callback)(timer, now, timer->arg);
- if (newTime)
- TimerSet(timer, 0, newTime, timer->callback, timer->arg);
- }
- _X_EXPORT OsTimerPtr
- TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
- OsTimerCallback func, pointer arg)
- {
- OsTimerPtr *prev;
- CARD32 now = GetTimeInMillis();
- if (!timer)
- {
- timer = (OsTimerPtr)malloc(sizeof(struct _OsTimerRec));
- if (!timer)
- return NULL;
- }
- else
- {
- for (prev = &timers; *prev; prev = &(*prev)->next)
- {
- if (*prev == timer)
- {
- *prev = timer->next;
- if (flags & TimerForceOld)
- (void)(*timer->callback)(timer, now, timer->arg);
- break;
- }
- }
- }
- if (!millis)
- return timer;
- if (flags & TimerAbsolute) {
- timer->delta = millis - now;
- }
- else {
- timer->delta = millis;
- millis += now;
- }
- timer->expires = millis;
- timer->callback = func;
- timer->arg = arg;
- if ((int) (millis - now) <= 0)
- {
- timer->next = NULL;
- millis = (*timer->callback)(timer, now, timer->arg);
- if (!millis)
- return timer;
- }
- for (prev = &timers;
- *prev && (int) ((*prev)->expires - millis) <= 0;
- prev = &(*prev)->next)
- ;
- timer->next = *prev;
- *prev = timer;
- return timer;
- }
- Bool
- TimerForce(OsTimerPtr timer)
- {
- OsTimerPtr *prev;
- for (prev = &timers; *prev; prev = &(*prev)->next)
- {
- if (*prev == timer)
- {
- DoTimer(timer, GetTimeInMillis(), prev);
- return TRUE;
- }
- }
- return FALSE;
- }
- _X_EXPORT void
- TimerCancel(OsTimerPtr timer)
- {
- OsTimerPtr *prev;
- if (!timer)
- return;
- for (prev = &timers; *prev; prev = &(*prev)->next)
- {
- if (*prev == timer)
- {
- *prev = timer->next;
- break;
- }
- }
- }
- _X_EXPORT void
- TimerFree(OsTimerPtr timer)
- {
- if (!timer)
- return;
- TimerCancel(timer);
- free(timer);
- }
- void
- TimerInit(void)
- {
- OsTimerPtr timer;
- while ((timer = timers))
- {
- timers = timer->next;
- free(timer);
- }
- }
- #ifdef DPMSExtension
- #define DPMS_CHECK_MODE(mode,time)\
- if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\
- DPMSSet(mode);
- #define DPMS_CHECK_TIMEOUT(time)\
- if (time > 0 && (time - timeout) > 0)\
- return time - timeout;
- static CARD32
- NextDPMSTimeout(INT32 timeout)
- {
- /*
- * Return the amount of time remaining until we should set
- * the next power level. Fallthroughs are intentional.
- */
- switch (DPMSPowerLevel)
- {
- case DPMSModeOn:
- DPMS_CHECK_TIMEOUT(DPMSStandbyTime)
- case DPMSModeStandby:
- DPMS_CHECK_TIMEOUT(DPMSSuspendTime)
- case DPMSModeSuspend:
- DPMS_CHECK_TIMEOUT(DPMSOffTime)
- default: /* DPMSModeOff */
- return 0;
- }
- }
- #endif /* DPMSExtension */
- static CARD32
- ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg)
- {
- INT32 timeout = now - lastDeviceEventTime.milliseconds;
- CARD32 nextTimeout = 0;
- #ifdef DPMSExtension
- /*
- * Check each mode lowest to highest, since a lower mode can
- * have the same timeout as a higher one.
- */
- if (DPMSEnabled)
- {
- DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime)
- DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime)
- DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime)
- nextTimeout = NextDPMSTimeout(timeout);
- }
- /*
- * Only do the screensaver checks if we're not in a DPMS
- * power saving mode
- */
- if (DPMSPowerLevel != DPMSModeOn)
- return nextTimeout;
- #endif /* DPMSExtension */
- if (!ScreenSaverTime)
- return nextTimeout;
- if (timeout < ScreenSaverTime)
- {
- return nextTimeout > 0 ?
- min(ScreenSaverTime - timeout, nextTimeout) :
- ScreenSaverTime - timeout;
- }
- ResetOsBuffers(); /* not ideal, but better than nothing */
- SaveScreens(SCREEN_SAVER_ON, ScreenSaverActive);
- if (ScreenSaverInterval > 0)
- {
- nextTimeout = nextTimeout > 0 ?
- min(ScreenSaverInterval, nextTimeout) :
- ScreenSaverInterval;
- }
- return nextTimeout;
- }
- static OsTimerPtr ScreenSaverTimer = NULL;
- void
- FreeScreenSaverTimer(void)
- {
- if (ScreenSaverTimer) {
- TimerFree(ScreenSaverTimer);
- ScreenSaverTimer = NULL;
- }
- }
- void
- SetScreenSaverTimer(void)
- {
- CARD32 timeout = 0;
- #ifdef DPMSExtension
- if (DPMSEnabled)
- {
- /*
- * A higher DPMS level has a timeout that's either less
- * than or equal to that of a lower DPMS level.
- */
- if (DPMSStandbyTime > 0)
- timeout = DPMSStandbyTime;
- else if (DPMSSuspendTime > 0)
- timeout = DPMSSuspendTime;
- else if (DPMSOffTime > 0)
- timeout = DPMSOffTime;
- }
- #endif
- if (ScreenSaverTime > 0)
- {
- timeout = timeout > 0 ?
- min(ScreenSaverTime, timeout) :
- ScreenSaverTime;
- }
- #ifdef SCREENSAVER
- if (timeout && !screenSaverSuspended) {
- #else
- if (timeout) {
- #endif
- ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout,
- ScreenSaverTimeoutExpire, NULL);
- }
- else if (ScreenSaverTimer) {
- FreeScreenSaverTimer();
- }
- }
|