WaitFor.c revision 4642e01f
105b261ecSmrg/*********************************************************** 205b261ecSmrg 305b261ecSmrgCopyright 1987, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrg 2605b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 2705b261ecSmrg 2805b261ecSmrg All Rights Reserved 2905b261ecSmrg 3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its 3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted, 3205b261ecSmrgprovided that the above copyright notice appear in all copies and that 3305b261ecSmrgboth that copyright notice and this permission notice appear in 3405b261ecSmrgsupporting documentation, and that the name of Digital not be 3505b261ecSmrgused in advertising or publicity pertaining to distribution of the 3605b261ecSmrgsoftware without specific, written prior permission. 3705b261ecSmrg 3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4405b261ecSmrgSOFTWARE. 4505b261ecSmrg 4605b261ecSmrg******************************************************************/ 4705b261ecSmrg 4805b261ecSmrg 4905b261ecSmrg/***************************************************************** 5005b261ecSmrg * OS Dependent input routines: 5105b261ecSmrg * 5205b261ecSmrg * WaitForSomething 5305b261ecSmrg * TimerForce, TimerSet, TimerCheck, TimerFree 5405b261ecSmrg * 5505b261ecSmrg *****************************************************************/ 5605b261ecSmrg 5705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 5805b261ecSmrg#include <dix-config.h> 5905b261ecSmrg#endif 6005b261ecSmrg 6105b261ecSmrg#ifdef WIN32 6205b261ecSmrg#include <X11/Xwinsock.h> 6305b261ecSmrg#endif 6405b261ecSmrg#include <X11/Xos.h> /* for strings, fcntl, time */ 6505b261ecSmrg#include <errno.h> 6605b261ecSmrg#include <stdio.h> 6705b261ecSmrg#include <X11/X.h> 6805b261ecSmrg#include "misc.h" 6905b261ecSmrg 7005b261ecSmrg#include "osdep.h" 7105b261ecSmrg#include <X11/Xpoll.h> 7205b261ecSmrg#include "dixstruct.h" 7305b261ecSmrg#include "opaque.h" 7405b261ecSmrg#ifdef DPMSExtension 7505b261ecSmrg#include "dpmsproc.h" 7605b261ecSmrg#endif 7705b261ecSmrg 7805b261ecSmrg#ifdef WIN32 7905b261ecSmrg/* Error codes from windows sockets differ from fileio error codes */ 8005b261ecSmrg#undef EINTR 8105b261ecSmrg#define EINTR WSAEINTR 8205b261ecSmrg#undef EINVAL 8305b261ecSmrg#define EINVAL WSAEINVAL 8405b261ecSmrg#undef EBADF 8505b261ecSmrg#define EBADF WSAENOTSOCK 8605b261ecSmrg/* Windows select does not set errno. Use GetErrno as wrapper for 8705b261ecSmrg WSAGetLastError */ 8805b261ecSmrg#define GetErrno WSAGetLastError 8905b261ecSmrg#else 9005b261ecSmrg/* This is just a fallback to errno to hide the differences between unix and 9105b261ecSmrg Windows in the code */ 9205b261ecSmrg#define GetErrno() errno 9305b261ecSmrg#endif 9405b261ecSmrg 9505b261ecSmrg/* modifications by raphael */ 9605b261ecSmrgint 9705b261ecSmrgmffs(fd_mask mask) 9805b261ecSmrg{ 9905b261ecSmrg int i; 10005b261ecSmrg 10105b261ecSmrg if (!mask) return 0; 10205b261ecSmrg i = 1; 10305b261ecSmrg while (!(mask & 1)) 10405b261ecSmrg { 10505b261ecSmrg i++; 10605b261ecSmrg mask >>= 1; 10705b261ecSmrg } 10805b261ecSmrg return i; 10905b261ecSmrg} 11005b261ecSmrg 11105b261ecSmrg#ifdef DPMSExtension 11205b261ecSmrg#define DPMS_SERVER 11305b261ecSmrg#include <X11/extensions/dpms.h> 11405b261ecSmrg#endif 11505b261ecSmrg 11605b261ecSmrgstruct _OsTimerRec { 11705b261ecSmrg OsTimerPtr next; 11805b261ecSmrg CARD32 expires; 11905b261ecSmrg CARD32 delta; 12005b261ecSmrg OsTimerCallback callback; 12105b261ecSmrg pointer arg; 12205b261ecSmrg}; 12305b261ecSmrg 12405b261ecSmrgstatic void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev); 12505b261ecSmrgstatic void CheckAllTimers(void); 12605b261ecSmrgstatic OsTimerPtr timers = NULL; 12705b261ecSmrg 12805b261ecSmrg/***************** 12905b261ecSmrg * WaitForSomething: 13005b261ecSmrg * Make the server suspend until there is 13105b261ecSmrg * 1. data from clients or 13205b261ecSmrg * 2. input events available or 13305b261ecSmrg * 3. ddx notices something of interest (graphics 13405b261ecSmrg * queue ready, etc.) or 13505b261ecSmrg * 4. clients that have buffered replies/events are ready 13605b261ecSmrg * 13705b261ecSmrg * If the time between INPUT events is 13805b261ecSmrg * greater than ScreenSaverTime, the display is turned off (or 13905b261ecSmrg * saved, depending on the hardware). So, WaitForSomething() 14005b261ecSmrg * has to handle this also (that's why the select() has a timeout. 14105b261ecSmrg * For more info on ClientsWithInput, see ReadRequestFromClient(). 14205b261ecSmrg * pClientsReady is an array to store ready client->index values into. 14305b261ecSmrg *****************/ 14405b261ecSmrg 14505b261ecSmrgint 14605b261ecSmrgWaitForSomething(int *pClientsReady) 14705b261ecSmrg{ 14805b261ecSmrg int i; 14905b261ecSmrg struct timeval waittime, *wt; 15005b261ecSmrg INT32 timeout = 0; 15105b261ecSmrg fd_set clientsReadable; 15205b261ecSmrg fd_set clientsWritable; 15305b261ecSmrg int curclient; 15405b261ecSmrg int selecterr; 15505b261ecSmrg int nready; 15605b261ecSmrg fd_set devicesReadable; 15705b261ecSmrg CARD32 now = 0; 15805b261ecSmrg Bool someReady = FALSE; 15905b261ecSmrg 16005b261ecSmrg FD_ZERO(&clientsReadable); 16105b261ecSmrg 16205b261ecSmrg /* We need a while loop here to handle 16305b261ecSmrg crashed connections and the screen saver timeout */ 16405b261ecSmrg while (1) 16505b261ecSmrg { 16605b261ecSmrg /* deal with any blocked jobs */ 16705b261ecSmrg if (workQueue) 16805b261ecSmrg ProcessWorkQueue(); 16905b261ecSmrg if (XFD_ANYSET (&ClientsWithInput)) 17005b261ecSmrg { 17105b261ecSmrg if (!SmartScheduleDisable) 17205b261ecSmrg { 17305b261ecSmrg someReady = TRUE; 17405b261ecSmrg waittime.tv_sec = 0; 17505b261ecSmrg waittime.tv_usec = 0; 17605b261ecSmrg wt = &waittime; 17705b261ecSmrg } 17805b261ecSmrg else 17905b261ecSmrg { 18005b261ecSmrg XFD_COPYSET (&ClientsWithInput, &clientsReadable); 18105b261ecSmrg break; 18205b261ecSmrg } 18305b261ecSmrg } 18405b261ecSmrg if (someReady) 18505b261ecSmrg { 18605b261ecSmrg XFD_COPYSET(&AllSockets, &LastSelectMask); 18705b261ecSmrg XFD_UNSET(&LastSelectMask, &ClientsWithInput); 18805b261ecSmrg } 18905b261ecSmrg else 19005b261ecSmrg { 19105b261ecSmrg wt = NULL; 19205b261ecSmrg if (timers) 19305b261ecSmrg { 19405b261ecSmrg now = GetTimeInMillis(); 19505b261ecSmrg timeout = timers->expires - now; 19605b261ecSmrg if (timeout > 0 && timeout > timers->delta + 250) { 19705b261ecSmrg /* time has rewound. reset the timers. */ 19805b261ecSmrg CheckAllTimers(); 19905b261ecSmrg } 20005b261ecSmrg 20105b261ecSmrg if (timers) { 20205b261ecSmrg timeout = timers->expires - now; 20305b261ecSmrg if (timeout < 0) 20405b261ecSmrg timeout = 0; 20505b261ecSmrg waittime.tv_sec = timeout / MILLI_PER_SECOND; 20605b261ecSmrg waittime.tv_usec = (timeout % MILLI_PER_SECOND) * 20705b261ecSmrg (1000000 / MILLI_PER_SECOND); 20805b261ecSmrg wt = &waittime; 20905b261ecSmrg } 21005b261ecSmrg } 21105b261ecSmrg XFD_COPYSET(&AllSockets, &LastSelectMask); 21205b261ecSmrg } 2134642e01fSmrg SmartScheduleStopTimer (); 2144642e01fSmrg 21505b261ecSmrg BlockHandler((pointer)&wt, (pointer)&LastSelectMask); 21605b261ecSmrg if (NewOutputPending) 21705b261ecSmrg FlushAllOutput(); 21805b261ecSmrg /* keep this check close to select() call to minimize race */ 21905b261ecSmrg if (dispatchException) 22005b261ecSmrg i = -1; 22105b261ecSmrg else if (AnyClientsWriteBlocked) 22205b261ecSmrg { 22305b261ecSmrg XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable); 22405b261ecSmrg i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt); 22505b261ecSmrg } 22605b261ecSmrg else 22705b261ecSmrg { 22805b261ecSmrg i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt); 22905b261ecSmrg } 23005b261ecSmrg selecterr = GetErrno(); 23105b261ecSmrg WakeupHandler(i, (pointer)&LastSelectMask); 2324642e01fSmrg SmartScheduleStartTimer (); 23305b261ecSmrg if (i <= 0) /* An error or timeout occurred */ 23405b261ecSmrg { 23505b261ecSmrg if (dispatchException) 23605b261ecSmrg return 0; 23705b261ecSmrg if (i < 0) 23805b261ecSmrg { 23905b261ecSmrg if (selecterr == EBADF) /* Some client disconnected */ 24005b261ecSmrg { 24105b261ecSmrg CheckConnections (); 24205b261ecSmrg if (! XFD_ANYSET (&AllClients)) 24305b261ecSmrg return 0; 24405b261ecSmrg } 24505b261ecSmrg else if (selecterr == EINVAL) 24605b261ecSmrg { 2474642e01fSmrg FatalError("WaitForSomething(): select: %s\n", 2484642e01fSmrg strerror(selecterr)); 24905b261ecSmrg } 25005b261ecSmrg else if (selecterr != EINTR && selecterr != EAGAIN) 25105b261ecSmrg { 2524642e01fSmrg ErrorF("WaitForSomething(): select: %s\n", 2534642e01fSmrg strerror(selecterr)); 25405b261ecSmrg } 25505b261ecSmrg } 25605b261ecSmrg else if (someReady) 25705b261ecSmrg { 25805b261ecSmrg /* 25905b261ecSmrg * If no-one else is home, bail quickly 26005b261ecSmrg */ 26105b261ecSmrg XFD_COPYSET(&ClientsWithInput, &LastSelectMask); 26205b261ecSmrg XFD_COPYSET(&ClientsWithInput, &clientsReadable); 26305b261ecSmrg break; 26405b261ecSmrg } 26505b261ecSmrg if (*checkForInput[0] != *checkForInput[1]) 26605b261ecSmrg return 0; 26705b261ecSmrg 26805b261ecSmrg if (timers) 26905b261ecSmrg { 27005b261ecSmrg int expired = 0; 27105b261ecSmrg now = GetTimeInMillis(); 27205b261ecSmrg if ((int) (timers->expires - now) <= 0) 27305b261ecSmrg expired = 1; 27405b261ecSmrg 27505b261ecSmrg while (timers && (int) (timers->expires - now) <= 0) 27605b261ecSmrg DoTimer(timers, now, &timers); 27705b261ecSmrg 27805b261ecSmrg if (expired) 27905b261ecSmrg return 0; 28005b261ecSmrg } 28105b261ecSmrg } 28205b261ecSmrg else 28305b261ecSmrg { 28405b261ecSmrg fd_set tmp_set; 28505b261ecSmrg 28605b261ecSmrg if (*checkForInput[0] == *checkForInput[1]) { 28705b261ecSmrg if (timers) 28805b261ecSmrg { 28905b261ecSmrg int expired = 0; 29005b261ecSmrg now = GetTimeInMillis(); 29105b261ecSmrg if ((int) (timers->expires - now) <= 0) 29205b261ecSmrg expired = 1; 29305b261ecSmrg 29405b261ecSmrg while (timers && (int) (timers->expires - now) <= 0) 29505b261ecSmrg DoTimer(timers, now, &timers); 29605b261ecSmrg 29705b261ecSmrg if (expired) 29805b261ecSmrg return 0; 29905b261ecSmrg } 30005b261ecSmrg } 30105b261ecSmrg if (someReady) 30205b261ecSmrg XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask); 30305b261ecSmrg if (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable)) 30405b261ecSmrg { 30505b261ecSmrg NewOutputPending = TRUE; 30605b261ecSmrg XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending); 30705b261ecSmrg XFD_UNSET(&ClientsWriteBlocked, &clientsWritable); 30805b261ecSmrg if (! XFD_ANYSET(&ClientsWriteBlocked)) 30905b261ecSmrg AnyClientsWriteBlocked = FALSE; 31005b261ecSmrg } 31105b261ecSmrg 31205b261ecSmrg XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices); 31305b261ecSmrg XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients); 31405b261ecSmrg XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections); 31505b261ecSmrg if (XFD_ANYSET(&tmp_set)) 31605b261ecSmrg QueueWorkProc(EstablishNewConnections, NULL, 31705b261ecSmrg (pointer)&LastSelectMask); 31805b261ecSmrg 31905b261ecSmrg if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable)) 32005b261ecSmrg break; 3214642e01fSmrg /* check here for DDXes that queue events during Block/Wakeup */ 32205b261ecSmrg if (*checkForInput[0] != *checkForInput[1]) 32305b261ecSmrg return 0; 32405b261ecSmrg } 32505b261ecSmrg } 32605b261ecSmrg 32705b261ecSmrg nready = 0; 32805b261ecSmrg if (XFD_ANYSET (&clientsReadable)) 32905b261ecSmrg { 33005b261ecSmrg#ifndef WIN32 33105b261ecSmrg for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++) 33205b261ecSmrg { 33305b261ecSmrg int highest_priority = 0; 33405b261ecSmrg 33505b261ecSmrg while (clientsReadable.fds_bits[i]) 33605b261ecSmrg { 33705b261ecSmrg int client_priority, client_index; 33805b261ecSmrg 33905b261ecSmrg curclient = ffs (clientsReadable.fds_bits[i]) - 1; 34005b261ecSmrg client_index = /* raphael: modified */ 34105b261ecSmrg ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))]; 34205b261ecSmrg#else 34305b261ecSmrg int highest_priority = 0; 34405b261ecSmrg fd_set savedClientsReadable; 34505b261ecSmrg XFD_COPYSET(&clientsReadable, &savedClientsReadable); 34605b261ecSmrg for (i = 0; i < XFD_SETCOUNT(&savedClientsReadable); i++) 34705b261ecSmrg { 34805b261ecSmrg int client_priority, client_index; 34905b261ecSmrg 35005b261ecSmrg curclient = XFD_FD(&savedClientsReadable, i); 35105b261ecSmrg client_index = GetConnectionTranslation(curclient); 35205b261ecSmrg#endif 35305b261ecSmrg /* We implement "strict" priorities. 35405b261ecSmrg * Only the highest priority client is returned to 35505b261ecSmrg * dix. If multiple clients at the same priority are 35605b261ecSmrg * ready, they are all returned. This means that an 35705b261ecSmrg * aggressive client could take over the server. 35805b261ecSmrg * This was not considered a big problem because 35905b261ecSmrg * aggressive clients can hose the server in so many 36005b261ecSmrg * other ways :) 36105b261ecSmrg */ 36205b261ecSmrg client_priority = clients[client_index]->priority; 36305b261ecSmrg if (nready == 0 || client_priority > highest_priority) 36405b261ecSmrg { 36505b261ecSmrg /* Either we found the first client, or we found 36605b261ecSmrg * a client whose priority is greater than all others 36705b261ecSmrg * that have been found so far. Either way, we want 36805b261ecSmrg * to initialize the list of clients to contain just 36905b261ecSmrg * this client. 37005b261ecSmrg */ 37105b261ecSmrg pClientsReady[0] = client_index; 37205b261ecSmrg highest_priority = client_priority; 37305b261ecSmrg nready = 1; 37405b261ecSmrg } 37505b261ecSmrg /* the following if makes sure that multiple same-priority 37605b261ecSmrg * clients get batched together 37705b261ecSmrg */ 37805b261ecSmrg else if (client_priority == highest_priority) 37905b261ecSmrg { 38005b261ecSmrg pClientsReady[nready++] = client_index; 38105b261ecSmrg } 38205b261ecSmrg#ifndef WIN32 38305b261ecSmrg clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient); 38405b261ecSmrg } 38505b261ecSmrg#else 38605b261ecSmrg FD_CLR(curclient, &clientsReadable); 38705b261ecSmrg#endif 38805b261ecSmrg } 38905b261ecSmrg } 39005b261ecSmrg return nready; 39105b261ecSmrg} 39205b261ecSmrg 39305b261ecSmrg/* If time has rewound, re-run every affected timer. 39405b261ecSmrg * Timers might drop out of the list, so we have to restart every time. */ 39505b261ecSmrgstatic void 39605b261ecSmrgCheckAllTimers(void) 39705b261ecSmrg{ 39805b261ecSmrg OsTimerPtr timer; 39905b261ecSmrg CARD32 now; 40005b261ecSmrg 40105b261ecSmrgstart: 40205b261ecSmrg now = GetTimeInMillis(); 40305b261ecSmrg 40405b261ecSmrg for (timer = timers; timer; timer = timer->next) { 40505b261ecSmrg if (timer->expires - now > timer->delta + 250) { 40605b261ecSmrg TimerForce(timer); 40705b261ecSmrg goto start; 40805b261ecSmrg } 40905b261ecSmrg } 41005b261ecSmrg} 41105b261ecSmrg 41205b261ecSmrgstatic void 41305b261ecSmrgDoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev) 41405b261ecSmrg{ 41505b261ecSmrg CARD32 newTime; 41605b261ecSmrg 41705b261ecSmrg *prev = timer->next; 41805b261ecSmrg timer->next = NULL; 41905b261ecSmrg newTime = (*timer->callback)(timer, now, timer->arg); 42005b261ecSmrg if (newTime) 42105b261ecSmrg TimerSet(timer, 0, newTime, timer->callback, timer->arg); 42205b261ecSmrg} 42305b261ecSmrg 42405b261ecSmrg_X_EXPORT OsTimerPtr 42505b261ecSmrgTimerSet(OsTimerPtr timer, int flags, CARD32 millis, 42605b261ecSmrg OsTimerCallback func, pointer arg) 42705b261ecSmrg{ 42805b261ecSmrg register OsTimerPtr *prev; 42905b261ecSmrg CARD32 now = GetTimeInMillis(); 43005b261ecSmrg 43105b261ecSmrg if (!timer) 43205b261ecSmrg { 43305b261ecSmrg timer = (OsTimerPtr)xalloc(sizeof(struct _OsTimerRec)); 43405b261ecSmrg if (!timer) 43505b261ecSmrg return NULL; 43605b261ecSmrg } 43705b261ecSmrg else 43805b261ecSmrg { 43905b261ecSmrg for (prev = &timers; *prev; prev = &(*prev)->next) 44005b261ecSmrg { 44105b261ecSmrg if (*prev == timer) 44205b261ecSmrg { 44305b261ecSmrg *prev = timer->next; 44405b261ecSmrg if (flags & TimerForceOld) 44505b261ecSmrg (void)(*timer->callback)(timer, now, timer->arg); 44605b261ecSmrg break; 44705b261ecSmrg } 44805b261ecSmrg } 44905b261ecSmrg } 45005b261ecSmrg if (!millis) 45105b261ecSmrg return timer; 45205b261ecSmrg if (flags & TimerAbsolute) { 45305b261ecSmrg timer->delta = millis - now; 45405b261ecSmrg } 45505b261ecSmrg else { 45605b261ecSmrg timer->delta = millis; 45705b261ecSmrg millis += now; 45805b261ecSmrg } 45905b261ecSmrg timer->expires = millis; 46005b261ecSmrg timer->callback = func; 46105b261ecSmrg timer->arg = arg; 46205b261ecSmrg if ((int) (millis - now) <= 0) 46305b261ecSmrg { 46405b261ecSmrg timer->next = NULL; 46505b261ecSmrg millis = (*timer->callback)(timer, now, timer->arg); 46605b261ecSmrg if (!millis) 46705b261ecSmrg return timer; 46805b261ecSmrg } 46905b261ecSmrg for (prev = &timers; 47005b261ecSmrg *prev && (int) ((*prev)->expires - millis) <= 0; 47105b261ecSmrg prev = &(*prev)->next) 47205b261ecSmrg ; 47305b261ecSmrg timer->next = *prev; 47405b261ecSmrg *prev = timer; 47505b261ecSmrg return timer; 47605b261ecSmrg} 47705b261ecSmrg 47805b261ecSmrgBool 47905b261ecSmrgTimerForce(OsTimerPtr timer) 48005b261ecSmrg{ 48105b261ecSmrg OsTimerPtr *prev; 48205b261ecSmrg 48305b261ecSmrg for (prev = &timers; *prev; prev = &(*prev)->next) 48405b261ecSmrg { 48505b261ecSmrg if (*prev == timer) 48605b261ecSmrg { 48705b261ecSmrg DoTimer(timer, GetTimeInMillis(), prev); 48805b261ecSmrg return TRUE; 48905b261ecSmrg } 49005b261ecSmrg } 49105b261ecSmrg return FALSE; 49205b261ecSmrg} 49305b261ecSmrg 49405b261ecSmrg 49505b261ecSmrg_X_EXPORT void 49605b261ecSmrgTimerCancel(OsTimerPtr timer) 49705b261ecSmrg{ 49805b261ecSmrg OsTimerPtr *prev; 49905b261ecSmrg 50005b261ecSmrg if (!timer) 50105b261ecSmrg return; 50205b261ecSmrg for (prev = &timers; *prev; prev = &(*prev)->next) 50305b261ecSmrg { 50405b261ecSmrg if (*prev == timer) 50505b261ecSmrg { 50605b261ecSmrg *prev = timer->next; 50705b261ecSmrg break; 50805b261ecSmrg } 50905b261ecSmrg } 51005b261ecSmrg} 51105b261ecSmrg 51205b261ecSmrg_X_EXPORT void 51305b261ecSmrgTimerFree(OsTimerPtr timer) 51405b261ecSmrg{ 51505b261ecSmrg if (!timer) 51605b261ecSmrg return; 51705b261ecSmrg TimerCancel(timer); 51805b261ecSmrg xfree(timer); 51905b261ecSmrg} 52005b261ecSmrg 52105b261ecSmrgvoid 52205b261ecSmrgTimerCheck(void) 52305b261ecSmrg{ 52405b261ecSmrg CARD32 now = GetTimeInMillis(); 52505b261ecSmrg 52605b261ecSmrg while (timers && (int) (timers->expires - now) <= 0) 52705b261ecSmrg DoTimer(timers, now, &timers); 52805b261ecSmrg} 52905b261ecSmrg 53005b261ecSmrgvoid 53105b261ecSmrgTimerInit(void) 53205b261ecSmrg{ 53305b261ecSmrg OsTimerPtr timer; 53405b261ecSmrg 53505b261ecSmrg while ((timer = timers)) 53605b261ecSmrg { 53705b261ecSmrg timers = timer->next; 53805b261ecSmrg xfree(timer); 53905b261ecSmrg } 54005b261ecSmrg} 54105b261ecSmrg 54205b261ecSmrg#ifdef DPMSExtension 54305b261ecSmrg 54405b261ecSmrg#define DPMS_CHECK_MODE(mode,time)\ 54505b261ecSmrg if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\ 5464642e01fSmrg DPMSSet(serverClient, mode); 54705b261ecSmrg 54805b261ecSmrg#define DPMS_CHECK_TIMEOUT(time)\ 54905b261ecSmrg if (time > 0 && (time - timeout) > 0)\ 55005b261ecSmrg return time - timeout; 55105b261ecSmrg 55205b261ecSmrgstatic CARD32 55305b261ecSmrgNextDPMSTimeout(INT32 timeout) 55405b261ecSmrg{ 55505b261ecSmrg /* 55605b261ecSmrg * Return the amount of time remaining until we should set 55705b261ecSmrg * the next power level. Fallthroughs are intentional. 55805b261ecSmrg */ 55905b261ecSmrg switch (DPMSPowerLevel) 56005b261ecSmrg { 56105b261ecSmrg case DPMSModeOn: 56205b261ecSmrg DPMS_CHECK_TIMEOUT(DPMSStandbyTime) 56305b261ecSmrg 56405b261ecSmrg case DPMSModeStandby: 56505b261ecSmrg DPMS_CHECK_TIMEOUT(DPMSSuspendTime) 56605b261ecSmrg 56705b261ecSmrg case DPMSModeSuspend: 56805b261ecSmrg DPMS_CHECK_TIMEOUT(DPMSOffTime) 56905b261ecSmrg 57005b261ecSmrg default: /* DPMSModeOff */ 57105b261ecSmrg return 0; 57205b261ecSmrg } 57305b261ecSmrg} 57405b261ecSmrg#endif /* DPMSExtension */ 57505b261ecSmrg 57605b261ecSmrgstatic CARD32 57705b261ecSmrgScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg) 57805b261ecSmrg{ 57905b261ecSmrg INT32 timeout = now - lastDeviceEventTime.milliseconds; 58005b261ecSmrg CARD32 nextTimeout = 0; 58105b261ecSmrg 58205b261ecSmrg#ifdef DPMSExtension 58305b261ecSmrg /* 58405b261ecSmrg * Check each mode lowest to highest, since a lower mode can 58505b261ecSmrg * have the same timeout as a higher one. 58605b261ecSmrg */ 58705b261ecSmrg if (DPMSEnabled) 58805b261ecSmrg { 58905b261ecSmrg DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime) 59005b261ecSmrg DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime) 59105b261ecSmrg DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime) 59205b261ecSmrg 59305b261ecSmrg nextTimeout = NextDPMSTimeout(timeout); 59405b261ecSmrg } 59505b261ecSmrg 59605b261ecSmrg /* 59705b261ecSmrg * Only do the screensaver checks if we're not in a DPMS 59805b261ecSmrg * power saving mode 59905b261ecSmrg */ 60005b261ecSmrg if (DPMSPowerLevel != DPMSModeOn) 60105b261ecSmrg return nextTimeout; 60205b261ecSmrg#endif /* DPMSExtension */ 60305b261ecSmrg 60405b261ecSmrg if (!ScreenSaverTime) 60505b261ecSmrg return nextTimeout; 60605b261ecSmrg 60705b261ecSmrg if (timeout < ScreenSaverTime) 60805b261ecSmrg { 60905b261ecSmrg return nextTimeout > 0 ? 61005b261ecSmrg min(ScreenSaverTime - timeout, nextTimeout) : 61105b261ecSmrg ScreenSaverTime - timeout; 61205b261ecSmrg } 61305b261ecSmrg 61405b261ecSmrg ResetOsBuffers(); /* not ideal, but better than nothing */ 6154642e01fSmrg dixSaveScreens(serverClient, SCREEN_SAVER_ON, ScreenSaverActive); 61605b261ecSmrg 61705b261ecSmrg if (ScreenSaverInterval > 0) 61805b261ecSmrg { 61905b261ecSmrg nextTimeout = nextTimeout > 0 ? 62005b261ecSmrg min(ScreenSaverInterval, nextTimeout) : 62105b261ecSmrg ScreenSaverInterval; 62205b261ecSmrg } 62305b261ecSmrg 62405b261ecSmrg return nextTimeout; 62505b261ecSmrg} 62605b261ecSmrg 62705b261ecSmrgstatic OsTimerPtr ScreenSaverTimer = NULL; 62805b261ecSmrg 62905b261ecSmrgvoid 63005b261ecSmrgFreeScreenSaverTimer(void) 63105b261ecSmrg{ 63205b261ecSmrg if (ScreenSaverTimer) { 63305b261ecSmrg TimerFree(ScreenSaverTimer); 63405b261ecSmrg ScreenSaverTimer = NULL; 63505b261ecSmrg } 63605b261ecSmrg} 63705b261ecSmrg 63805b261ecSmrgvoid 63905b261ecSmrgSetScreenSaverTimer(void) 64005b261ecSmrg{ 64105b261ecSmrg CARD32 timeout = 0; 64205b261ecSmrg 64305b261ecSmrg#ifdef DPMSExtension 64405b261ecSmrg if (DPMSEnabled) 64505b261ecSmrg { 64605b261ecSmrg /* 64705b261ecSmrg * A higher DPMS level has a timeout that's either less 64805b261ecSmrg * than or equal to that of a lower DPMS level. 64905b261ecSmrg */ 65005b261ecSmrg if (DPMSStandbyTime > 0) 65105b261ecSmrg timeout = DPMSStandbyTime; 65205b261ecSmrg 65305b261ecSmrg else if (DPMSSuspendTime > 0) 65405b261ecSmrg timeout = DPMSSuspendTime; 65505b261ecSmrg 65605b261ecSmrg else if (DPMSOffTime > 0) 65705b261ecSmrg timeout = DPMSOffTime; 65805b261ecSmrg } 65905b261ecSmrg#endif 66005b261ecSmrg 66105b261ecSmrg if (ScreenSaverTime > 0) 66205b261ecSmrg { 66305b261ecSmrg timeout = timeout > 0 ? 66405b261ecSmrg min(ScreenSaverTime, timeout) : 66505b261ecSmrg ScreenSaverTime; 66605b261ecSmrg } 66705b261ecSmrg 66805b261ecSmrg#ifdef SCREENSAVER 66905b261ecSmrg if (timeout && !screenSaverSuspended) { 67005b261ecSmrg#else 67105b261ecSmrg if (timeout) { 67205b261ecSmrg#endif 67305b261ecSmrg ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout, 67405b261ecSmrg ScreenSaverTimeoutExpire, NULL); 67505b261ecSmrg } 67605b261ecSmrg else if (ScreenSaverTimer) { 67705b261ecSmrg FreeScreenSaverTimer(); 67805b261ecSmrg } 67905b261ecSmrg} 68005b261ecSmrg 681