Use SERVICES callback to implement Windows timers.
Timer expiration handling removed from EVENT_WaitNetEvent loop.
This commit is contained in:
parent
d38ae1f79b
commit
9dcaeca29f
|
@ -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 @@
|
||||||
#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,48 +190,23 @@ 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.
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
*
|
*
|
||||||
* Mark expired timers and wake the appropriate queues.
|
* 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;
|
TIMER *pTimer;
|
||||||
DWORD curTime = GetTickCount();
|
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 */
|
||||||
|
@ -242,6 +218,37 @@ void TIMER_ExpireTimers(void)
|
||||||
pTimer = pTimer->next;
|
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 );
|
LeaveCriticalSection( &csTimer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
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,
|
||||||
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)
|
||||||
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 )
|
||||||
/* 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
|
||||||
|
|
Loading…
Reference in New Issue