Commit 9dcaeca2 authored by Ulrich Weigand's avatar Ulrich Weigand Committed by Alexandre Julliard

Use SERVICES callback to implement Windows timers.

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