sleepuntil.c revision 35c4bbdf
105b261ecSmrg/* 205b261ecSmrg * 305b261ecSmrgCopyright 1992, 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 * Author: Keith Packard, MIT X Consortium 2605b261ecSmrg */ 2705b261ecSmrg 2805b261ecSmrg/* dixsleep.c - implement millisecond timeouts for X clients */ 2905b261ecSmrg 3005b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3105b261ecSmrg#include <dix-config.h> 3205b261ecSmrg#endif 3305b261ecSmrg 3405b261ecSmrg#include "sleepuntil.h" 3505b261ecSmrg#include <X11/X.h> 3605b261ecSmrg#include <X11/Xmd.h> 3705b261ecSmrg#include "misc.h" 3805b261ecSmrg#include "windowstr.h" 3905b261ecSmrg#include "dixstruct.h" 4005b261ecSmrg#include "pixmapstr.h" 4105b261ecSmrg#include "scrnintstr.h" 4205b261ecSmrg 4305b261ecSmrgtypedef struct _Sertafied { 4435c4bbdfSmrg struct _Sertafied *next; 4535c4bbdfSmrg TimeStamp revive; 4635c4bbdfSmrg ClientPtr pClient; 4735c4bbdfSmrg XID id; 4835c4bbdfSmrg void (*notifyFunc) (ClientPtr /* client */ , 4935c4bbdfSmrg void * /* closure */ 5035c4bbdfSmrg ); 5135c4bbdfSmrg 5235c4bbdfSmrg void *closure; 5305b261ecSmrg} SertafiedRec, *SertafiedPtr; 5405b261ecSmrg 5505b261ecSmrgstatic SertafiedPtr pPending; 5635c4bbdfSmrgstatic RESTYPE SertafiedResType; 5735c4bbdfSmrgstatic Bool BlockHandlerRegistered; 5835c4bbdfSmrgstatic int SertafiedGeneration; 5935c4bbdfSmrg 6035c4bbdfSmrgstatic void ClientAwaken(ClientPtr /* client */ , 6135c4bbdfSmrg void * /* closure */ 6235c4bbdfSmrg ); 6335c4bbdfSmrgstatic int SertafiedDelete(void * /* value */ , 6435c4bbdfSmrg XID /* id */ 6535c4bbdfSmrg ); 6635c4bbdfSmrgstatic void SertafiedBlockHandler(void * /* data */ , 6735c4bbdfSmrg OSTimePtr /* wt */ , 6835c4bbdfSmrg void * /* LastSelectMask */ 6935c4bbdfSmrg ); 7035c4bbdfSmrgstatic void SertafiedWakeupHandler(void * /* data */ , 7135c4bbdfSmrg int /* i */ , 7235c4bbdfSmrg void * /* LastSelectMask */ 7335c4bbdfSmrg ); 7405b261ecSmrg 756747b715Smrgint 7635c4bbdfSmrgClientSleepUntil(ClientPtr client, 7735c4bbdfSmrg TimeStamp *revive, 7835c4bbdfSmrg void (*notifyFunc) (ClientPtr, void *), void *closure) 7905b261ecSmrg{ 8035c4bbdfSmrg SertafiedPtr pRequest, pReq, pPrev; 8135c4bbdfSmrg 8235c4bbdfSmrg if (SertafiedGeneration != serverGeneration) { 8335c4bbdfSmrg SertafiedResType = CreateNewResourceType(SertafiedDelete, 8435c4bbdfSmrg "ClientSleep"); 8535c4bbdfSmrg if (!SertafiedResType) 8635c4bbdfSmrg return FALSE; 8735c4bbdfSmrg SertafiedGeneration = serverGeneration; 8835c4bbdfSmrg BlockHandlerRegistered = FALSE; 8905b261ecSmrg } 9035c4bbdfSmrg pRequest = malloc(sizeof(SertafiedRec)); 9105b261ecSmrg if (!pRequest) 9235c4bbdfSmrg return FALSE; 9305b261ecSmrg pRequest->pClient = client; 9405b261ecSmrg pRequest->revive = *revive; 9535c4bbdfSmrg pRequest->id = FakeClientID(client->index); 9605b261ecSmrg pRequest->closure = closure; 9735c4bbdfSmrg if (!BlockHandlerRegistered) { 9835c4bbdfSmrg if (!RegisterBlockAndWakeupHandlers(SertafiedBlockHandler, 9935c4bbdfSmrg SertafiedWakeupHandler, 10035c4bbdfSmrg (void *) 0)) { 10135c4bbdfSmrg free(pRequest); 10235c4bbdfSmrg return FALSE; 10335c4bbdfSmrg } 10435c4bbdfSmrg BlockHandlerRegistered = TRUE; 10505b261ecSmrg } 10605b261ecSmrg pRequest->notifyFunc = 0; 10735c4bbdfSmrg if (!AddResource(pRequest->id, SertafiedResType, (void *) pRequest)) 10835c4bbdfSmrg return FALSE; 10905b261ecSmrg if (!notifyFunc) 11035c4bbdfSmrg notifyFunc = ClientAwaken; 11105b261ecSmrg pRequest->notifyFunc = notifyFunc; 11205b261ecSmrg /* Insert into time-ordered queue, with earliest activation time coming first. */ 11305b261ecSmrg pPrev = 0; 11435c4bbdfSmrg for (pReq = pPending; pReq; pReq = pReq->next) { 11535c4bbdfSmrg if (CompareTimeStamps(pReq->revive, *revive) == LATER) 11635c4bbdfSmrg break; 11735c4bbdfSmrg pPrev = pReq; 11805b261ecSmrg } 11905b261ecSmrg if (pPrev) 12035c4bbdfSmrg pPrev->next = pRequest; 12105b261ecSmrg else 12235c4bbdfSmrg pPending = pRequest; 12305b261ecSmrg pRequest->next = pReq; 12435c4bbdfSmrg IgnoreClient(client); 12505b261ecSmrg return TRUE; 12605b261ecSmrg} 12705b261ecSmrg 12805b261ecSmrgstatic void 12935c4bbdfSmrgClientAwaken(ClientPtr client, void *closure) 13005b261ecSmrg{ 13105b261ecSmrg if (!client->clientGone) 13235c4bbdfSmrg AttendClient(client); 13305b261ecSmrg} 13405b261ecSmrg 13505b261ecSmrgstatic int 13635c4bbdfSmrgSertafiedDelete(void *value, XID id) 13705b261ecSmrg{ 13835c4bbdfSmrg SertafiedPtr pRequest = (SertafiedPtr) value; 13935c4bbdfSmrg SertafiedPtr pReq, pPrev; 14005b261ecSmrg 14105b261ecSmrg pPrev = 0; 14205b261ecSmrg for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next) 14335c4bbdfSmrg if (pReq == pRequest) { 14435c4bbdfSmrg if (pPrev) 14535c4bbdfSmrg pPrev->next = pReq->next; 14635c4bbdfSmrg else 14735c4bbdfSmrg pPending = pReq->next; 14835c4bbdfSmrg break; 14935c4bbdfSmrg } 15005b261ecSmrg if (pRequest->notifyFunc) 15135c4bbdfSmrg (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure); 1526747b715Smrg free(pRequest); 15305b261ecSmrg return TRUE; 15405b261ecSmrg} 15505b261ecSmrg 15605b261ecSmrgstatic void 15735c4bbdfSmrgSertafiedBlockHandler(void *data, OSTimePtr wt, void *LastSelectMask) 15805b261ecSmrg{ 15935c4bbdfSmrg SertafiedPtr pReq, pNext; 16035c4bbdfSmrg unsigned long delay; 16135c4bbdfSmrg TimeStamp now; 16205b261ecSmrg 16305b261ecSmrg if (!pPending) 16435c4bbdfSmrg return; 16535c4bbdfSmrg now.milliseconds = GetTimeInMillis(); 16605b261ecSmrg now.months = currentTime.months; 16705b261ecSmrg if ((int) (now.milliseconds - currentTime.milliseconds) < 0) 16835c4bbdfSmrg now.months++; 16935c4bbdfSmrg for (pReq = pPending; pReq; pReq = pNext) { 17035c4bbdfSmrg pNext = pReq->next; 17135c4bbdfSmrg if (CompareTimeStamps(pReq->revive, now) == LATER) 17235c4bbdfSmrg break; 17335c4bbdfSmrg FreeResource(pReq->id, RT_NONE); 17435c4bbdfSmrg 17535c4bbdfSmrg /* AttendClient() may have been called via the resource delete 17635c4bbdfSmrg * function so a client may have input to be processed and so 17735c4bbdfSmrg * set delay to 0 to prevent blocking in WaitForSomething(). 17835c4bbdfSmrg */ 17935c4bbdfSmrg AdjustWaitForDelay(wt, 0); 18005b261ecSmrg } 18105b261ecSmrg pReq = pPending; 18205b261ecSmrg if (!pReq) 18335c4bbdfSmrg return; 18405b261ecSmrg delay = pReq->revive.milliseconds - now.milliseconds; 18535c4bbdfSmrg AdjustWaitForDelay(wt, delay); 18605b261ecSmrg} 18705b261ecSmrg 18805b261ecSmrgstatic void 18935c4bbdfSmrgSertafiedWakeupHandler(void *data, int i, void *LastSelectMask) 19005b261ecSmrg{ 19135c4bbdfSmrg SertafiedPtr pReq, pNext; 19235c4bbdfSmrg TimeStamp now; 19305b261ecSmrg 19435c4bbdfSmrg now.milliseconds = GetTimeInMillis(); 19505b261ecSmrg now.months = currentTime.months; 19605b261ecSmrg if ((int) (now.milliseconds - currentTime.milliseconds) < 0) 19735c4bbdfSmrg now.months++; 19835c4bbdfSmrg for (pReq = pPending; pReq; pReq = pNext) { 19935c4bbdfSmrg pNext = pReq->next; 20035c4bbdfSmrg if (CompareTimeStamps(pReq->revive, now) == LATER) 20135c4bbdfSmrg break; 20235c4bbdfSmrg FreeResource(pReq->id, RT_NONE); 20305b261ecSmrg } 20435c4bbdfSmrg if (!pPending) { 20535c4bbdfSmrg RemoveBlockAndWakeupHandlers(SertafiedBlockHandler, 20635c4bbdfSmrg SertafiedWakeupHandler, (void *) 0); 20735c4bbdfSmrg BlockHandlerRegistered = FALSE; 20805b261ecSmrg } 20905b261ecSmrg} 210