sleepuntil.c revision 6747b715
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 { 4405b261ecSmrg struct _Sertafied *next; 4505b261ecSmrg TimeStamp revive; 4605b261ecSmrg ClientPtr pClient; 4705b261ecSmrg XID id; 4805b261ecSmrg void (*notifyFunc)( 4905b261ecSmrg ClientPtr /* client */, 5005b261ecSmrg pointer /* closure */ 5105b261ecSmrg ); 5205b261ecSmrg 5305b261ecSmrg pointer closure; 5405b261ecSmrg} SertafiedRec, *SertafiedPtr; 5505b261ecSmrg 5605b261ecSmrgstatic SertafiedPtr pPending; 5705b261ecSmrgstatic RESTYPE SertafiedResType; 5805b261ecSmrgstatic Bool BlockHandlerRegistered; 5905b261ecSmrgstatic int SertafiedGeneration; 6005b261ecSmrg 6105b261ecSmrgstatic void ClientAwaken( 6205b261ecSmrg ClientPtr /* client */, 6305b261ecSmrg pointer /* closure */ 6405b261ecSmrg); 6505b261ecSmrgstatic int SertafiedDelete( 6605b261ecSmrg pointer /* value */, 6705b261ecSmrg XID /* id */ 6805b261ecSmrg); 6905b261ecSmrgstatic void SertafiedBlockHandler( 7005b261ecSmrg pointer /* data */, 7105b261ecSmrg OSTimePtr /* wt */, 7205b261ecSmrg pointer /* LastSelectMask */ 7305b261ecSmrg); 7405b261ecSmrgstatic void SertafiedWakeupHandler( 7505b261ecSmrg pointer /* data */, 7605b261ecSmrg int /* i */, 7705b261ecSmrg pointer /* LastSelectMask */ 7805b261ecSmrg); 7905b261ecSmrg 806747b715Smrgint 816747b715SmrgClientSleepUntil (ClientPtr client, 826747b715Smrg TimeStamp *revive, 836747b715Smrg void (*notifyFunc)(ClientPtr, pointer), 846747b715Smrg pointer closure) 8505b261ecSmrg{ 8605b261ecSmrg SertafiedPtr pRequest, pReq, pPrev; 8705b261ecSmrg 8805b261ecSmrg if (SertafiedGeneration != serverGeneration) 8905b261ecSmrg { 906747b715Smrg SertafiedResType = CreateNewResourceType (SertafiedDelete, 916747b715Smrg "ClientSleep"); 9205b261ecSmrg if (!SertafiedResType) 9305b261ecSmrg return FALSE; 9405b261ecSmrg SertafiedGeneration = serverGeneration; 9505b261ecSmrg BlockHandlerRegistered = FALSE; 9605b261ecSmrg } 976747b715Smrg pRequest = malloc(sizeof (SertafiedRec)); 9805b261ecSmrg if (!pRequest) 9905b261ecSmrg return FALSE; 10005b261ecSmrg pRequest->pClient = client; 10105b261ecSmrg pRequest->revive = *revive; 10205b261ecSmrg pRequest->id = FakeClientID (client->index); 10305b261ecSmrg pRequest->closure = closure; 10405b261ecSmrg if (!BlockHandlerRegistered) 10505b261ecSmrg { 10605b261ecSmrg if (!RegisterBlockAndWakeupHandlers (SertafiedBlockHandler, 10705b261ecSmrg SertafiedWakeupHandler, 10805b261ecSmrg (pointer) 0)) 10905b261ecSmrg { 1106747b715Smrg free(pRequest); 11105b261ecSmrg return FALSE; 11205b261ecSmrg } 11305b261ecSmrg BlockHandlerRegistered = TRUE; 11405b261ecSmrg } 11505b261ecSmrg pRequest->notifyFunc = 0; 11605b261ecSmrg if (!AddResource (pRequest->id, SertafiedResType, (pointer) pRequest)) 11705b261ecSmrg return FALSE; 11805b261ecSmrg if (!notifyFunc) 11905b261ecSmrg notifyFunc = ClientAwaken; 12005b261ecSmrg pRequest->notifyFunc = notifyFunc; 12105b261ecSmrg /* Insert into time-ordered queue, with earliest activation time coming first. */ 12205b261ecSmrg pPrev = 0; 12305b261ecSmrg for (pReq = pPending; pReq; pReq = pReq->next) 12405b261ecSmrg { 12505b261ecSmrg if (CompareTimeStamps (pReq->revive, *revive) == LATER) 12605b261ecSmrg break; 12705b261ecSmrg pPrev = pReq; 12805b261ecSmrg } 12905b261ecSmrg if (pPrev) 13005b261ecSmrg pPrev->next = pRequest; 13105b261ecSmrg else 13205b261ecSmrg pPending = pRequest; 13305b261ecSmrg pRequest->next = pReq; 13405b261ecSmrg IgnoreClient (client); 13505b261ecSmrg return TRUE; 13605b261ecSmrg} 13705b261ecSmrg 13805b261ecSmrgstatic void 1396747b715SmrgClientAwaken (ClientPtr client, pointer closure) 14005b261ecSmrg{ 14105b261ecSmrg if (!client->clientGone) 14205b261ecSmrg AttendClient (client); 14305b261ecSmrg} 14405b261ecSmrg 14505b261ecSmrg 14605b261ecSmrgstatic int 1476747b715SmrgSertafiedDelete (pointer value, XID id) 14805b261ecSmrg{ 14905b261ecSmrg SertafiedPtr pRequest = (SertafiedPtr)value; 15005b261ecSmrg SertafiedPtr pReq, pPrev; 15105b261ecSmrg 15205b261ecSmrg pPrev = 0; 15305b261ecSmrg for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next) 15405b261ecSmrg if (pReq == pRequest) 15505b261ecSmrg { 15605b261ecSmrg if (pPrev) 15705b261ecSmrg pPrev->next = pReq->next; 15805b261ecSmrg else 15905b261ecSmrg pPending = pReq->next; 16005b261ecSmrg break; 16105b261ecSmrg } 16205b261ecSmrg if (pRequest->notifyFunc) 16305b261ecSmrg (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure); 1646747b715Smrg free(pRequest); 16505b261ecSmrg return TRUE; 16605b261ecSmrg} 16705b261ecSmrg 16805b261ecSmrgstatic void 1696747b715SmrgSertafiedBlockHandler (pointer data, OSTimePtr wt, pointer LastSelectMask) 17005b261ecSmrg{ 17105b261ecSmrg SertafiedPtr pReq, pNext; 17205b261ecSmrg unsigned long delay; 17305b261ecSmrg TimeStamp now; 17405b261ecSmrg 17505b261ecSmrg if (!pPending) 17605b261ecSmrg return; 17705b261ecSmrg now.milliseconds = GetTimeInMillis (); 17805b261ecSmrg now.months = currentTime.months; 17905b261ecSmrg if ((int) (now.milliseconds - currentTime.milliseconds) < 0) 18005b261ecSmrg now.months++; 18105b261ecSmrg for (pReq = pPending; pReq; pReq = pNext) 18205b261ecSmrg { 18305b261ecSmrg pNext = pReq->next; 18405b261ecSmrg if (CompareTimeStamps (pReq->revive, now) == LATER) 18505b261ecSmrg break; 18605b261ecSmrg FreeResource (pReq->id, RT_NONE); 18705b261ecSmrg 18805b261ecSmrg /* AttendClient() may have been called via the resource delete 18905b261ecSmrg * function so a client may have input to be processed and so 19005b261ecSmrg * set delay to 0 to prevent blocking in WaitForSomething(). 19105b261ecSmrg */ 19205b261ecSmrg AdjustWaitForDelay (wt, 0); 19305b261ecSmrg } 19405b261ecSmrg pReq = pPending; 19505b261ecSmrg if (!pReq) 19605b261ecSmrg return; 19705b261ecSmrg delay = pReq->revive.milliseconds - now.milliseconds; 19805b261ecSmrg AdjustWaitForDelay (wt, delay); 19905b261ecSmrg} 20005b261ecSmrg 20105b261ecSmrgstatic void 2026747b715SmrgSertafiedWakeupHandler (pointer data, int i, pointer LastSelectMask) 20305b261ecSmrg{ 20405b261ecSmrg SertafiedPtr pReq, pNext; 20505b261ecSmrg TimeStamp now; 20605b261ecSmrg 20705b261ecSmrg now.milliseconds = GetTimeInMillis (); 20805b261ecSmrg now.months = currentTime.months; 20905b261ecSmrg if ((int) (now.milliseconds - currentTime.milliseconds) < 0) 21005b261ecSmrg now.months++; 21105b261ecSmrg for (pReq = pPending; pReq; pReq = pNext) 21205b261ecSmrg { 21305b261ecSmrg pNext = pReq->next; 21405b261ecSmrg if (CompareTimeStamps (pReq->revive, now) == LATER) 21505b261ecSmrg break; 21605b261ecSmrg FreeResource (pReq->id, RT_NONE); 21705b261ecSmrg } 21805b261ecSmrg if (!pPending) 21905b261ecSmrg { 22005b261ecSmrg RemoveBlockAndWakeupHandlers (SertafiedBlockHandler, 22105b261ecSmrg SertafiedWakeupHandler, 22205b261ecSmrg (pointer) 0); 22305b261ecSmrg BlockHandlerRegistered = FALSE; 22405b261ecSmrg } 22505b261ecSmrg} 226