Use SERVICES callback to implement Windows timers. Timer expiration handling removed from EVENT_WaitNetEvent loop.
diff --git a/include/message.h b/include/message.h index ffe942e..b8dcc10 100644 --- a/include/message.h +++ b/include/message.h
@@ -22,8 +22,6 @@ extern void TIMER_RemoveWindowTimers( HWND hwnd ); extern void TIMER_RemoveQueueTimers( HQUEUE16 hqueue ); extern void TIMER_SwitchQueue( HQUEUE16 hOldQueue, HQUEUE16 hNewQueue ); -extern LONG TIMER_GetNextExpiration(void); -extern void TIMER_ExpireTimers(void); extern BOOL TIMER_GetTimerMsg( MSG *msg, HWND hwnd, HQUEUE16 hQueue, BOOL remove );
diff --git a/windows/timer.c b/windows/timer.c index 2163101..89dd416 100644 --- a/windows/timer.c +++ b/windows/timer.c
@@ -8,6 +8,7 @@ #include "queue.h" #include "task.h" #include "winproc.h" +#include "services.h" #include "debug.h" DEFAULT_DEBUG_CHANNEL(timer) @@ -189,47 +190,22 @@ TIMER_InsertTimer( pTimer ); } - /*********************************************************************** - * TIMER_GetNextExpiration - * - * Return next timer expiration time, or -1 if none. - */ -LONG TIMER_GetNextExpiration(void) -{ - TIMER *pTimer; - LONG retValue; - - EnterCriticalSection( &csTimer ); - - pTimer = pNextTimer; - - while (pTimer && !pTimer->expires) /* Skip already expired timers */ - pTimer = pTimer->next; - - if (pTimer) - { - DWORD now = GetTickCount(); - retValue = (pTimer->expires <= now) ? 0 : (pTimer->expires - now); - } - else retValue = -1; - - LeaveCriticalSection( &csTimer ); - return retValue; -} - - -/*********************************************************************** - * TIMER_ExpireTimers + * TIMER_CheckTimers * * Mark expired timers and wake the appropriate queues. */ -void TIMER_ExpireTimers(void) +static void CALLBACK TIMER_CheckTimers( ULONG_PTR forceTimer ) { + static HANDLE ServiceHandle = INVALID_HANDLE_VALUE; + static LONG ServiceTimeout = 0; + TIMER *pTimer; DWORD curTime = GetTickCount(); EnterCriticalSection( &csTimer ); + + TRACE(timer, "Called at %ld (%s)\n", curTime, forceTimer? "manual" : "auto" ); pTimer = pNextTimer; @@ -241,6 +217,37 @@ QUEUE_IncTimerCount( pTimer->hq ); pTimer = pTimer->next; } + + /* Install service callback with appropriate timeout, so that + we get called again once the next timer has expired */ + + if (pTimer) + { + LONG timeout = pTimer->expires - curTime; + + if ( forceTimer || timeout != ServiceTimeout ) + { + if ( ServiceHandle != INVALID_HANDLE_VALUE ) + SERVICE_Delete( ServiceHandle ); + + ServiceHandle = SERVICE_AddTimer( timeout * 1000L, + TIMER_CheckTimers, FALSE ); + ServiceTimeout = timeout; + + TRACE(timer, "Installed service callback with timeout %ld\n", timeout ); + } + } + else + { + if ( ServiceHandle != INVALID_HANDLE_VALUE ) + { + SERVICE_Delete( ServiceHandle ); + ServiceHandle = INVALID_HANDLE_VALUE; + ServiceTimeout = 0; + + TRACE(timer, "Deleted service callback\n" ); + } + } LeaveCriticalSection( &csTimer ); } @@ -272,11 +279,15 @@ return FALSE; /* No timer */ } - if (remove) TIMER_RestartTimer( pTimer, curTime ); /* Restart it */ - TRACE(timer, "Timer expired: %04x, %04x, %04x, %08lx\n", pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc); + if (remove) + { + TIMER_RestartTimer( pTimer, curTime ); /* Restart it */ + TIMER_CheckTimers( TRUE ); + } + /* Build the message */ msg->hwnd = pTimer->hwnd; msg->message = pTimer->msg; @@ -318,6 +329,7 @@ type, WIN_PROC_TIMER ); pTimer->expires = GetTickCount() + timeout; TIMER_InsertTimer( pTimer ); + TIMER_CheckTimers( TRUE ); LeaveCriticalSection( &csTimer ); return id; } @@ -351,6 +363,7 @@ pTimer, pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc ); TIMER_InsertTimer( pTimer ); + TIMER_CheckTimers( TRUE ); LeaveCriticalSection( &csTimer );
diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c index 5c65024..91c0e7b 100644 --- a/windows/x11drv/event.c +++ b/windows/x11drv/event.c
@@ -205,26 +205,15 @@ BOOL X11DRV_EVENT_WaitNetEvent( BOOL sleep, BOOL peek ) { XEvent event; - LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0; int pending = TSXPending(display); - /* Wait for an event or a timeout. If maxWait is -1, we have no timeout; - * in this case, we fall through directly to the XNextEvent loop. - */ - - if (!pending) + if (!pending && sleep) { int num_pending; - struct timeval timeout; fd_set io_set[3]; memcpy( io_set, __event_io_set, sizeof(io_set) ); - if(maxWait != -1) { - timeout.tv_usec = (maxWait % 1000) * 1000; - timeout.tv_sec = maxWait / 1000; - } - #ifdef CONFIG_IPC sigsetjmp(env_wait_x, 1); stop_wait_op= CONT; @@ -238,37 +227,24 @@ /* The code up to the next "stop_wait_op = CONT" must be reentrant */ num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ], &io_set[EVENT_IO_WRITE], - &io_set[EVENT_IO_EXCEPT], (maxWait == -1) ? 0 : &timeout ); + &io_set[EVENT_IO_EXCEPT], NULL ); if ( num_pending == -1 ) { /* Error - signal, invalid arguments, out of memory */ stop_wait_op = CONT; return FALSE; } - if ( num_pending == 0 ) - { - /* Timeout */ - stop_wait_op = CONT; - TIMER_ExpireTimers(); /* FIXME: should this be done even if sleep == 0? */ - return FALSE; - } - else stop_wait_op = CONT; + stop_wait_op = CONT; #else /* CONFIG_IPC */ num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ], &io_set[EVENT_IO_WRITE], - &io_set[EVENT_IO_EXCEPT], (maxWait == -1) ? 0 : &timeout ); + &io_set[EVENT_IO_EXCEPT], NULL ); if ( num_pending == -1 ) { /* Error - signal, invalid arguments, out of memory */ return FALSE; } - if ( num_pending == 0 ) - { - /* Timeout */ - TIMER_ExpireTimers(); /* FIXME: should this be done even if sleep == 0? */ - return FALSE; - } #endif /* CONFIG_IPC */ /* Flush the wake-up pipe, it's just dummy data for waking-up this