Implemented waitable timers.
This commit is contained in:
parent
1a61a03be4
commit
ad47a30f5e
|
@ -18,9 +18,6 @@
|
||||||
|
|
||||||
DEFAULT_DEBUG_CHANNEL(ntdll)
|
DEFAULT_DEBUG_CHANNEL(ntdll)
|
||||||
|
|
||||||
/* move to winbase.h */
|
|
||||||
typedef VOID (CALLBACK *PTIMERAPCROUTINE)(LPVOID lpArgToCompletionRoutine,DWORD dwTimerLowValue,DWORD dwTimerHighValue);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Timer object
|
* Timer object
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -967,6 +967,43 @@ struct set_registry_levels_request
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a waitable timer */
|
||||||
|
struct create_timer_request
|
||||||
|
{
|
||||||
|
IN int inherit; /* inherit flag */
|
||||||
|
IN int manual; /* manual reset */
|
||||||
|
OUT int handle; /* handle to the timer */
|
||||||
|
IN WCHAR name[1]; /* timer name */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Open a waitable timer */
|
||||||
|
struct open_timer_request
|
||||||
|
{
|
||||||
|
IN unsigned int access; /* wanted access rights */
|
||||||
|
IN int inherit; /* inherit flag */
|
||||||
|
OUT int handle; /* handle to the timer */
|
||||||
|
IN WCHAR name[1]; /* timer name */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set a waitable timer */
|
||||||
|
struct set_timer_request
|
||||||
|
{
|
||||||
|
IN int handle; /* handle to the timer */
|
||||||
|
IN int sec; /* next expiration absolute time */
|
||||||
|
IN int usec; /* next expiration absolute time */
|
||||||
|
IN int period; /* timer period in ms */
|
||||||
|
IN void* callback; /* callback function */
|
||||||
|
IN void* arg; /* callback argument */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Cancel a waitable timer */
|
||||||
|
struct cancel_timer_request
|
||||||
|
{
|
||||||
|
IN int handle; /* handle to the timer */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Everything below this line is generated automatically by tools/make_requests */
|
/* Everything below this line is generated automatically by tools/make_requests */
|
||||||
/* ### make_requests begin ### */
|
/* ### make_requests begin ### */
|
||||||
|
|
||||||
|
@ -1058,6 +1095,10 @@ enum request
|
||||||
REQ_LOAD_REGISTRY,
|
REQ_LOAD_REGISTRY,
|
||||||
REQ_SAVE_REGISTRY,
|
REQ_SAVE_REGISTRY,
|
||||||
REQ_SET_REGISTRY_LEVELS,
|
REQ_SET_REGISTRY_LEVELS,
|
||||||
|
REQ_CREATE_TIMER,
|
||||||
|
REQ_OPEN_TIMER,
|
||||||
|
REQ_SET_TIMER,
|
||||||
|
REQ_CANCEL_TIMER,
|
||||||
REQ_NB_REQUESTS
|
REQ_NB_REQUESTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1086,7 +1086,8 @@ typedef struct tagCOMMTIMEOUTS {
|
||||||
|
|
||||||
#include "poppack.h"
|
#include "poppack.h"
|
||||||
|
|
||||||
typedef VOID (CALLBACK *PAPCFUNC)(ULONG_PTR);
|
typedef void (CALLBACK *PAPCFUNC)(ULONG_PTR);
|
||||||
|
typedef void (CALLBACK *PTIMERAPCROUTINE)(LPVOID,DWORD,DWORD);
|
||||||
|
|
||||||
BOOL WINAPI ClearCommError(INT,LPDWORD,LPCOMSTAT);
|
BOOL WINAPI ClearCommError(INT,LPDWORD,LPCOMSTAT);
|
||||||
BOOL WINAPI BuildCommDCBA(LPCSTR,LPDCB);
|
BOOL WINAPI BuildCommDCBA(LPCSTR,LPDCB);
|
||||||
|
@ -1154,7 +1155,8 @@ BOOL WINAPI AreFileApisANSI(void);
|
||||||
BOOL WINAPI BackupEventLogA(HANDLE,LPCSTR);
|
BOOL WINAPI BackupEventLogA(HANDLE,LPCSTR);
|
||||||
BOOL WINAPI BackupEventLogW(HANDLE,LPCWSTR);
|
BOOL WINAPI BackupEventLogW(HANDLE,LPCWSTR);
|
||||||
#define BackupEventLog WINELIB_NAME_AW(BackupEventLog)
|
#define BackupEventLog WINELIB_NAME_AW(BackupEventLog)
|
||||||
BOOL WINAPI Beep(DWORD,DWORD);
|
BOOL WINAPI Beep(DWORD,DWORD);
|
||||||
|
BOOL WINAPI CancelWaitableTimer(HANDLE);
|
||||||
BOOL WINAPI ClearEventLogA(HANDLE,LPCSTR);
|
BOOL WINAPI ClearEventLogA(HANDLE,LPCSTR);
|
||||||
BOOL WINAPI ClearEventLogW(HANDLE,LPCWSTR);
|
BOOL WINAPI ClearEventLogW(HANDLE,LPCWSTR);
|
||||||
#define ClearEventLog WINELIB_NAME_AW(ClearEventLog)
|
#define ClearEventLog WINELIB_NAME_AW(ClearEventLog)
|
||||||
|
@ -1198,6 +1200,9 @@ HANDLE WINAPI CreateSemaphoreA(LPSECURITY_ATTRIBUTES,LONG,LONG,LPCSTR);
|
||||||
HANDLE WINAPI CreateSemaphoreW(LPSECURITY_ATTRIBUTES,LONG,LONG,LPCWSTR);
|
HANDLE WINAPI CreateSemaphoreW(LPSECURITY_ATTRIBUTES,LONG,LONG,LPCWSTR);
|
||||||
#define CreateSemaphore WINELIB_NAME_AW(CreateSemaphore)
|
#define CreateSemaphore WINELIB_NAME_AW(CreateSemaphore)
|
||||||
HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES,DWORD,LPTHREAD_START_ROUTINE,LPVOID,DWORD,LPDWORD);
|
HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES,DWORD,LPTHREAD_START_ROUTINE,LPVOID,DWORD,LPDWORD);
|
||||||
|
HANDLE WINAPI CreateWaitableTimerA(LPSECURITY_ATTRIBUTES,BOOL,LPCSTR);
|
||||||
|
HANDLE WINAPI CreateWaitableTimerW(LPSECURITY_ATTRIBUTES,BOOL,LPCWSTR);
|
||||||
|
#define CreateWaitableTimer WINELIB_NAME_AW(CreateWaitableTimer)
|
||||||
BOOL WINAPI DebugActiveProcess(DWORD);
|
BOOL WINAPI DebugActiveProcess(DWORD);
|
||||||
void WINAPI DebugBreak(void);
|
void WINAPI DebugBreak(void);
|
||||||
BOOL WINAPI DeregisterEventSource(HANDLE);
|
BOOL WINAPI DeregisterEventSource(HANDLE);
|
||||||
|
@ -1335,10 +1340,11 @@ BOOL WINAPI GetStringTypeExA(LCID,DWORD,LPCSTR,INT,LPWORD);
|
||||||
BOOL WINAPI GetStringTypeExW(LCID,DWORD,LPCWSTR,INT,LPWORD);
|
BOOL WINAPI GetStringTypeExW(LCID,DWORD,LPCWSTR,INT,LPWORD);
|
||||||
#define GetStringTypeEx WINELIB_NAME_AW(GetStringTypeEx)
|
#define GetStringTypeEx WINELIB_NAME_AW(GetStringTypeEx)
|
||||||
VOID WINAPI GetSystemInfo(LPSYSTEM_INFO);
|
VOID WINAPI GetSystemInfo(LPSYSTEM_INFO);
|
||||||
BOOL WINAPI GetSystemPowerStatus(LPSYSTEM_POWER_STATUS);
|
BOOL WINAPI GetSystemPowerStatus(LPSYSTEM_POWER_STATUS);
|
||||||
VOID WINAPI GetSystemTime(LPSYSTEMTIME);
|
VOID WINAPI GetSystemTime(LPSYSTEMTIME);
|
||||||
INT WINAPI GetTimeFormatA(LCID,DWORD,LPSYSTEMTIME,LPCSTR,LPSTR,INT);
|
VOID WINAPI GetSystemTimeAsFileTime(LPFILETIME);
|
||||||
INT WINAPI GetTimeFormatW(LCID,DWORD,LPSYSTEMTIME,LPCWSTR,LPWSTR,INT);
|
INT WINAPI GetTimeFormatA(LCID,DWORD,LPSYSTEMTIME,LPCSTR,LPSTR,INT);
|
||||||
|
INT WINAPI GetTimeFormatW(LCID,DWORD,LPSYSTEMTIME,LPCWSTR,LPWSTR,INT);
|
||||||
#define GetTimeFormat WINELIB_NAME_AW(GetTimeFormat)
|
#define GetTimeFormat WINELIB_NAME_AW(GetTimeFormat)
|
||||||
BOOL WINAPI GetThreadContext(HANDLE,CONTEXT *);
|
BOOL WINAPI GetThreadContext(HANDLE,CONTEXT *);
|
||||||
LCID WINAPI GetThreadLocale(void);
|
LCID WINAPI GetThreadLocale(void);
|
||||||
|
@ -1413,8 +1419,11 @@ HANDLE WINAPI OpenSemaphoreA(DWORD,BOOL,LPCSTR);
|
||||||
HANDLE WINAPI OpenSemaphoreW(DWORD,BOOL,LPCWSTR);
|
HANDLE WINAPI OpenSemaphoreW(DWORD,BOOL,LPCWSTR);
|
||||||
#define OpenSemaphore WINELIB_NAME_AW(OpenSemaphore)
|
#define OpenSemaphore WINELIB_NAME_AW(OpenSemaphore)
|
||||||
BOOL WINAPI OpenThreadToken(HANDLE,DWORD,BOOL,PHANDLE);
|
BOOL WINAPI OpenThreadToken(HANDLE,DWORD,BOOL,PHANDLE);
|
||||||
BOOL WINAPI PulseEvent(HANDLE);
|
HANDLE WINAPI OpenWaitableTimerA(DWORD,BOOL,LPCSTR);
|
||||||
BOOL WINAPI PurgeComm(HANDLE,DWORD);
|
HANDLE WINAPI OpenWaitableTimerW(DWORD,BOOL,LPCWSTR);
|
||||||
|
#define OpenWaitableTimer WINELIB_NAME_AW(OpenWaitableTimer)
|
||||||
|
BOOL WINAPI PulseEvent(HANDLE);
|
||||||
|
BOOL WINAPI PurgeComm(HANDLE,DWORD);
|
||||||
DWORD WINAPI QueryDosDeviceA(LPCSTR,LPSTR,DWORD);
|
DWORD WINAPI QueryDosDeviceA(LPCSTR,LPSTR,DWORD);
|
||||||
DWORD WINAPI QueryDosDeviceW(LPCWSTR,LPWSTR,DWORD);
|
DWORD WINAPI QueryDosDeviceW(LPCWSTR,LPWSTR,DWORD);
|
||||||
#define QueryDosDevice WINELIB_NAME_AW(QueryDosDevice)
|
#define QueryDosDevice WINELIB_NAME_AW(QueryDosDevice)
|
||||||
|
@ -1484,9 +1493,10 @@ BOOL WINAPI SetSystemPowerState(BOOL,BOOL);
|
||||||
BOOL WINAPI SetSystemTime(const SYSTEMTIME*);
|
BOOL WINAPI SetSystemTime(const SYSTEMTIME*);
|
||||||
DWORD WINAPI SetThreadAffinityMask(HANDLE,DWORD);
|
DWORD WINAPI SetThreadAffinityMask(HANDLE,DWORD);
|
||||||
BOOL WINAPI SetThreadContext(HANDLE,const CONTEXT *);
|
BOOL WINAPI SetThreadContext(HANDLE,const CONTEXT *);
|
||||||
BOOL WINAPI SetThreadLocale(LCID);
|
BOOL WINAPI SetThreadLocale(LCID);
|
||||||
BOOL WINAPI SetThreadPriority(HANDLE,INT);
|
BOOL WINAPI SetThreadPriority(HANDLE,INT);
|
||||||
BOOL WINAPI SetTimeZoneInformation(const LPTIME_ZONE_INFORMATION);
|
BOOL WINAPI SetTimeZoneInformation(const LPTIME_ZONE_INFORMATION);
|
||||||
|
BOOL WINAPI SetWaitableTimer(HANDLE,const LARGE_INTEGER*,LONG,PTIMERAPCROUTINE,LPVOID,BOOL);
|
||||||
VOID WINAPI Sleep(DWORD);
|
VOID WINAPI Sleep(DWORD);
|
||||||
DWORD WINAPI SleepEx(DWORD,BOOL);
|
DWORD WINAPI SleepEx(DWORD,BOOL);
|
||||||
DWORD WINAPI SuspendThread(HANDLE);
|
DWORD WINAPI SuspendThread(HANDLE);
|
||||||
|
|
|
@ -873,12 +873,12 @@ import ntdll.dll
|
||||||
|
|
||||||
# NT 4.0 additions
|
# NT 4.0 additions
|
||||||
856 stub CancelIo
|
856 stub CancelIo
|
||||||
857 stub CancelWaitableTimer
|
857 stdcall CancelWaitableTimer(long) CancelWaitableTimer
|
||||||
858 stdcall CopyFileExA (str str ptr ptr ptr long) CopyFileExA
|
858 stdcall CopyFileExA (str str ptr ptr ptr long) CopyFileExA
|
||||||
859 stdcall CopyFileExW (wstr wstr ptr ptr ptr long) CopyFileExW
|
859 stdcall CopyFileExW (wstr wstr ptr ptr ptr long) CopyFileExW
|
||||||
860 stub CreateFiber
|
860 stub CreateFiber
|
||||||
861 stub CreateWaitableTimerA
|
861 stdcall CreateWaitableTimerA(ptr long str) CreateWaitableTimerA
|
||||||
862 stub CreateWaitableTimerW
|
862 stdcall CreateWaitableTimerW(ptr long wstr) CreateWaitableTimerW
|
||||||
863 stub DeleteFiber
|
863 stub DeleteFiber
|
||||||
864 stub DuplicateConsoleHandle
|
864 stub DuplicateConsoleHandle
|
||||||
865 stub FindFirstFileExA
|
865 stub FindFirstFileExA
|
||||||
|
@ -896,8 +896,8 @@ import ntdll.dll
|
||||||
878 stdcall InterlockedCompareExchange (ptr long long) InterlockedCompareExchange
|
878 stdcall InterlockedCompareExchange (ptr long long) InterlockedCompareExchange
|
||||||
879 stdcall InterlockedExchangeAdd (ptr long ) InterlockedExchangeAdd
|
879 stdcall InterlockedExchangeAdd (ptr long ) InterlockedExchangeAdd
|
||||||
880 stdcall IsProcessorFeaturePresent(long) IsProcessorFeaturePresent
|
880 stdcall IsProcessorFeaturePresent(long) IsProcessorFeaturePresent
|
||||||
881 stub OpenWaitableTimerA
|
881 stdcall OpenWaitableTimerA(long long str) OpenWaitableTimerA
|
||||||
882 stub OpenWaitableTimerW
|
882 stdcall OpenWaitableTimerW(long long wstr) OpenWaitableTimerW
|
||||||
883 stub ReadConsoleInputExA
|
883 stub ReadConsoleInputExA
|
||||||
884 stub ReadConsoleInputExW
|
884 stub ReadConsoleInputExW
|
||||||
885 stub ReadDirectoryChangesW
|
885 stub ReadDirectoryChangesW
|
||||||
|
@ -909,7 +909,7 @@ import ntdll.dll
|
||||||
891 stdcall SetProcessPriorityBoost(long long) SetProcessPriorityBoost
|
891 stdcall SetProcessPriorityBoost(long long) SetProcessPriorityBoost
|
||||||
892 stub SetThreadIdealProcessor
|
892 stub SetThreadIdealProcessor
|
||||||
893 stub SetThreadPriorityBoost
|
893 stub SetThreadPriorityBoost
|
||||||
894 stub SetWaitableTimer
|
894 stdcall SetWaitableTimer(long ptr long ptr ptr long) SetWaitableTimer
|
||||||
895 stub SignalObjectAndWait
|
895 stub SignalObjectAndWait
|
||||||
896 stub SwitchToFiber
|
896 stub SwitchToFiber
|
||||||
897 stub SwitchToThread
|
897 stub SwitchToThread
|
||||||
|
|
|
@ -19,7 +19,8 @@ C_SRCS = \
|
||||||
synchro.c \
|
synchro.c \
|
||||||
sysdeps.c \
|
sysdeps.c \
|
||||||
syslevel.c \
|
syslevel.c \
|
||||||
thread.c
|
thread.c \
|
||||||
|
timer.c
|
||||||
|
|
||||||
all: $(MODULE).o
|
all: $(MODULE).o
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* Win32 waitable timers
|
||||||
|
*
|
||||||
|
* Copyright 1999 Alexandre Julliard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "winerror.h"
|
||||||
|
#include "file.h" /* for FILETIME routines */
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CreateWaitableTimerA (KERNEL32.861)
|
||||||
|
*/
|
||||||
|
HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
|
||||||
|
{
|
||||||
|
struct create_timer_request *req = get_req_buffer();
|
||||||
|
|
||||||
|
req->manual = manual;
|
||||||
|
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||||
|
server_strcpyAtoW( req->name, name );
|
||||||
|
SetLastError(0);
|
||||||
|
server_call( REQ_CREATE_TIMER );
|
||||||
|
if (req->handle == -1) return 0;
|
||||||
|
return req->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CreateWaitableTimerW (KERNEL32.862)
|
||||||
|
*/
|
||||||
|
HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
|
||||||
|
{
|
||||||
|
struct create_timer_request *req = get_req_buffer();
|
||||||
|
|
||||||
|
req->manual = manual;
|
||||||
|
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||||
|
server_strcpyW( req->name, name );
|
||||||
|
SetLastError(0);
|
||||||
|
server_call( REQ_CREATE_TIMER );
|
||||||
|
if (req->handle == -1) return 0;
|
||||||
|
return req->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* OpenWaitableTimerA (KERNEL32.881)
|
||||||
|
*/
|
||||||
|
HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
|
||||||
|
{
|
||||||
|
struct open_timer_request *req = get_req_buffer();
|
||||||
|
|
||||||
|
req->access = access;
|
||||||
|
req->inherit = inherit;
|
||||||
|
server_strcpyAtoW( req->name, name );
|
||||||
|
server_call( REQ_OPEN_TIMER );
|
||||||
|
if (req->handle == -1) return 0; /* must return 0 on failure, not -1 */
|
||||||
|
return req->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* OpenWaitableTimerW (KERNEL32.882)
|
||||||
|
*/
|
||||||
|
HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
|
||||||
|
{
|
||||||
|
struct open_timer_request *req = get_req_buffer();
|
||||||
|
|
||||||
|
req->access = access;
|
||||||
|
req->inherit = inherit;
|
||||||
|
server_strcpyW( req->name, name );
|
||||||
|
server_call( REQ_OPEN_TIMER );
|
||||||
|
if (req->handle == -1) return 0; /* must return 0 on failure, not -1 */
|
||||||
|
return req->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SetWaitableTimer (KERNEL32.894)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
|
||||||
|
PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
|
||||||
|
{
|
||||||
|
FILETIME ft;
|
||||||
|
DWORD remainder;
|
||||||
|
struct set_timer_request *req = get_req_buffer();
|
||||||
|
|
||||||
|
if (when->s.HighPart < 0) /* relative time */
|
||||||
|
{
|
||||||
|
DWORD low = ft.dwLowDateTime;
|
||||||
|
GetSystemTimeAsFileTime( &ft );
|
||||||
|
ft.dwLowDateTime -= when->s.LowPart;
|
||||||
|
ft.dwHighDateTime -= when->s.HighPart;
|
||||||
|
if (low < ft.dwLowDateTime) ft.dwHighDateTime--; /* overflow */
|
||||||
|
}
|
||||||
|
else /* absolute time */
|
||||||
|
{
|
||||||
|
ft.dwLowDateTime = when->s.LowPart;
|
||||||
|
ft.dwHighDateTime = when->s.HighPart;
|
||||||
|
}
|
||||||
|
req->handle = handle;
|
||||||
|
req->sec = DOSFS_FileTimeToUnixTime( &ft, &remainder );
|
||||||
|
req->usec = remainder / 10; /* convert from 100-ns to us units */
|
||||||
|
req->period = period;
|
||||||
|
req->callback = callback;
|
||||||
|
req->arg = arg;
|
||||||
|
if (resume) SetLastError( ERROR_NOT_SUPPORTED ); /* set error but can still succeed */
|
||||||
|
return !server_call( REQ_SET_TIMER );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CancelWaitableTimer (KERNEL32.857)
|
||||||
|
*/
|
||||||
|
BOOL WINAPI CancelWaitableTimer( HANDLE handle )
|
||||||
|
{
|
||||||
|
struct cancel_timer_request *req = get_req_buffer();
|
||||||
|
req->handle = handle;
|
||||||
|
return !server_call( REQ_CANCEL_TIMER );
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ C_SRCS = \
|
||||||
sock.c \
|
sock.c \
|
||||||
socket.c \
|
socket.c \
|
||||||
thread.c \
|
thread.c \
|
||||||
|
timer.c \
|
||||||
trace.c \
|
trace.c \
|
||||||
unicode.c
|
unicode.c
|
||||||
|
|
||||||
|
|
|
@ -155,6 +155,10 @@ DECL_HANDLER(delete_key_value);
|
||||||
DECL_HANDLER(load_registry);
|
DECL_HANDLER(load_registry);
|
||||||
DECL_HANDLER(save_registry);
|
DECL_HANDLER(save_registry);
|
||||||
DECL_HANDLER(set_registry_levels);
|
DECL_HANDLER(set_registry_levels);
|
||||||
|
DECL_HANDLER(create_timer);
|
||||||
|
DECL_HANDLER(open_timer);
|
||||||
|
DECL_HANDLER(set_timer);
|
||||||
|
DECL_HANDLER(cancel_timer);
|
||||||
|
|
||||||
#ifdef WANT_REQUEST_HANDLERS
|
#ifdef WANT_REQUEST_HANDLERS
|
||||||
|
|
||||||
|
@ -248,6 +252,10 @@ static const struct handler {
|
||||||
{ (void(*)())req_load_registry, sizeof(struct load_registry_request) },
|
{ (void(*)())req_load_registry, sizeof(struct load_registry_request) },
|
||||||
{ (void(*)())req_save_registry, sizeof(struct save_registry_request) },
|
{ (void(*)())req_save_registry, sizeof(struct save_registry_request) },
|
||||||
{ (void(*)())req_set_registry_levels, sizeof(struct set_registry_levels_request) },
|
{ (void(*)())req_set_registry_levels, sizeof(struct set_registry_levels_request) },
|
||||||
|
{ (void(*)())req_create_timer, sizeof(struct create_timer_request) },
|
||||||
|
{ (void(*)())req_open_timer, sizeof(struct open_timer_request) },
|
||||||
|
{ (void(*)())req_set_timer, sizeof(struct set_timer_request) },
|
||||||
|
{ (void(*)())req_cancel_timer, sizeof(struct cancel_timer_request) },
|
||||||
};
|
};
|
||||||
#endif /* WANT_REQUEST_HANDLERS */
|
#endif /* WANT_REQUEST_HANDLERS */
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
* Waitable timers management
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999 Alexandre Julliard
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "winerror.h"
|
||||||
|
|
||||||
|
#include "handle.h"
|
||||||
|
#include "request.h"
|
||||||
|
|
||||||
|
/* FIXME: check values and move to standard header */
|
||||||
|
#define TIMER_MODIFY_STATE 0x0001
|
||||||
|
#define TIMER_QUERY_STATE 0x0002
|
||||||
|
#define TIMER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
|
||||||
|
|
||||||
|
struct timer
|
||||||
|
{
|
||||||
|
struct object obj; /* object header */
|
||||||
|
int manual; /* manual reset */
|
||||||
|
int signaled; /* current signaled state */
|
||||||
|
int period; /* timer period in ms */
|
||||||
|
struct timeval when; /* next expiration */
|
||||||
|
struct timeout_user *timeout; /* timeout user */
|
||||||
|
void *callback; /* callback APC function */
|
||||||
|
void *arg; /* callback argument */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void timer_dump( struct object *obj, int verbose );
|
||||||
|
static int timer_signaled( struct object *obj, struct thread *thread );
|
||||||
|
static int timer_satisfied( struct object *obj, struct thread *thread );
|
||||||
|
static void timer_destroy( struct object *obj );
|
||||||
|
|
||||||
|
static const struct object_ops timer_ops =
|
||||||
|
{
|
||||||
|
sizeof(struct timer),
|
||||||
|
timer_dump,
|
||||||
|
add_queue,
|
||||||
|
remove_queue,
|
||||||
|
timer_signaled,
|
||||||
|
timer_satisfied,
|
||||||
|
no_read_fd,
|
||||||
|
no_write_fd,
|
||||||
|
no_flush,
|
||||||
|
no_get_file_info,
|
||||||
|
timer_destroy
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* create a timer object */
|
||||||
|
static struct timer *create_timer( const WCHAR *name, size_t len, int manual )
|
||||||
|
{
|
||||||
|
struct timer *timer;
|
||||||
|
|
||||||
|
if ((timer = create_named_object( &timer_ops, name, len )))
|
||||||
|
{
|
||||||
|
if (get_error() != ERROR_ALREADY_EXISTS)
|
||||||
|
{
|
||||||
|
/* initialize it if it didn't already exist */
|
||||||
|
timer->manual = manual;
|
||||||
|
timer->signaled = 0;
|
||||||
|
timer->when.tv_sec = 0;
|
||||||
|
timer->when.tv_usec = 0;
|
||||||
|
timer->period = 0;
|
||||||
|
timer->timeout = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* callback on timer expiration */
|
||||||
|
static void timer_callback( void *private )
|
||||||
|
{
|
||||||
|
struct timer *timer = (struct timer *)private;
|
||||||
|
|
||||||
|
if (timer->period) /* schedule the next expiration */
|
||||||
|
{
|
||||||
|
make_timeout( &timer->when, timer->period );
|
||||||
|
timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
|
||||||
|
}
|
||||||
|
else timer->timeout = NULL;
|
||||||
|
|
||||||
|
/* wake up waiters */
|
||||||
|
timer->signaled = 1;
|
||||||
|
wake_up( &timer->obj, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the timer expiration and period */
|
||||||
|
static void set_timer( struct timer *timer, int sec, int usec, int period,
|
||||||
|
void *callback, void *arg )
|
||||||
|
{
|
||||||
|
if (timer->manual)
|
||||||
|
{
|
||||||
|
period = 0; /* period doesn't make any sense for a manual timer */
|
||||||
|
timer->signaled = 0;
|
||||||
|
}
|
||||||
|
if (timer->timeout) remove_timeout_user( timer->timeout );
|
||||||
|
timer->when.tv_sec = sec;
|
||||||
|
timer->when.tv_usec = usec;
|
||||||
|
timer->period = period;
|
||||||
|
timer->callback = callback;
|
||||||
|
timer->arg = arg;
|
||||||
|
timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cancel a running timer */
|
||||||
|
static void cancel_timer( struct timer *timer )
|
||||||
|
{
|
||||||
|
if (timer->timeout)
|
||||||
|
{
|
||||||
|
remove_timeout_user( timer->timeout );
|
||||||
|
timer->timeout = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timer_dump( struct object *obj, int verbose )
|
||||||
|
{
|
||||||
|
struct timer *timer = (struct timer *)obj;
|
||||||
|
assert( obj->ops == &timer_ops );
|
||||||
|
fprintf( stderr, "Timer manual=%d when=%ld.%06ld period=%d ",
|
||||||
|
timer->manual, timer->when.tv_sec, timer->when.tv_usec, timer->period );
|
||||||
|
dump_object_name( &timer->obj );
|
||||||
|
fputc( '\n', stderr );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int timer_signaled( struct object *obj, struct thread *thread )
|
||||||
|
{
|
||||||
|
struct timer *timer = (struct timer *)obj;
|
||||||
|
assert( obj->ops == &timer_ops );
|
||||||
|
return timer->signaled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int timer_satisfied( struct object *obj, struct thread *thread )
|
||||||
|
{
|
||||||
|
struct timer *timer = (struct timer *)obj;
|
||||||
|
assert( obj->ops == &timer_ops );
|
||||||
|
if (!timer->manual) timer->signaled = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timer_destroy( struct object *obj )
|
||||||
|
{
|
||||||
|
struct timer *timer = (struct timer *)obj;
|
||||||
|
assert( obj->ops == &timer_ops );
|
||||||
|
|
||||||
|
if (timer->timeout) remove_timeout_user( timer->timeout );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a timer */
|
||||||
|
DECL_HANDLER(create_timer)
|
||||||
|
{
|
||||||
|
size_t len = get_req_strlenW( req->name );
|
||||||
|
struct timer *timer;
|
||||||
|
|
||||||
|
req->handle = -1;
|
||||||
|
if ((timer = create_timer( req->name, len, req->manual )))
|
||||||
|
{
|
||||||
|
req->handle = alloc_handle( current->process, timer, TIMER_ALL_ACCESS, req->inherit );
|
||||||
|
release_object( timer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open a handle to a timer */
|
||||||
|
DECL_HANDLER(open_timer)
|
||||||
|
{
|
||||||
|
size_t len = get_req_strlenW( req->name );
|
||||||
|
req->handle = open_object( req->name, len, &timer_ops, req->access, req->inherit );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set a waitable timer */
|
||||||
|
DECL_HANDLER(set_timer)
|
||||||
|
{
|
||||||
|
struct timer *timer;
|
||||||
|
|
||||||
|
if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
|
||||||
|
TIMER_MODIFY_STATE, &timer_ops )))
|
||||||
|
{
|
||||||
|
set_timer( timer, req->sec, req->usec, req->period, req->callback, req->arg );
|
||||||
|
release_object( timer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cancel a waitable timer */
|
||||||
|
DECL_HANDLER(cancel_timer)
|
||||||
|
{
|
||||||
|
struct timer *timer;
|
||||||
|
|
||||||
|
if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
|
||||||
|
TIMER_MODIFY_STATE, &timer_ops )))
|
||||||
|
{
|
||||||
|
cancel_timer( timer );
|
||||||
|
release_object( timer );
|
||||||
|
}
|
||||||
|
}
|
|
@ -999,6 +999,47 @@ static void dump_set_registry_levels_request( struct set_registry_levels_request
|
||||||
fprintf( stderr, " version=%d", req->version );
|
fprintf( stderr, " version=%d", req->version );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_create_timer_request( struct create_timer_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " inherit=%d,", req->inherit );
|
||||||
|
fprintf( stderr, " manual=%d,", req->manual );
|
||||||
|
fprintf( stderr, " name=" );
|
||||||
|
dump_unicode_string( req->name );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_create_timer_reply( struct create_timer_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_open_timer_request( struct open_timer_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " access=%08x,", req->access );
|
||||||
|
fprintf( stderr, " inherit=%d,", req->inherit );
|
||||||
|
fprintf( stderr, " name=" );
|
||||||
|
dump_unicode_string( req->name );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_open_timer_reply( struct open_timer_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_set_timer_request( struct set_timer_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d,", req->handle );
|
||||||
|
fprintf( stderr, " sec=%d,", req->sec );
|
||||||
|
fprintf( stderr, " usec=%d,", req->usec );
|
||||||
|
fprintf( stderr, " period=%d,", req->period );
|
||||||
|
fprintf( stderr, " callback=%p,", req->callback );
|
||||||
|
fprintf( stderr, " arg=%p", req->arg );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_cancel_timer_request( struct cancel_timer_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
|
}
|
||||||
|
|
||||||
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_new_process_request,
|
(dump_func)dump_new_process_request,
|
||||||
(dump_func)dump_new_thread_request,
|
(dump_func)dump_new_thread_request,
|
||||||
|
@ -1086,6 +1127,10 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_load_registry_request,
|
(dump_func)dump_load_registry_request,
|
||||||
(dump_func)dump_save_registry_request,
|
(dump_func)dump_save_registry_request,
|
||||||
(dump_func)dump_set_registry_levels_request,
|
(dump_func)dump_set_registry_levels_request,
|
||||||
|
(dump_func)dump_create_timer_request,
|
||||||
|
(dump_func)dump_open_timer_request,
|
||||||
|
(dump_func)dump_set_timer_request,
|
||||||
|
(dump_func)dump_cancel_timer_request,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
|
@ -1175,6 +1220,10 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
|
(dump_func)dump_create_timer_reply,
|
||||||
|
(dump_func)dump_open_timer_reply,
|
||||||
|
(dump_func)0,
|
||||||
|
(dump_func)0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const req_names[REQ_NB_REQUESTS] = {
|
static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
|
@ -1264,6 +1313,10 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
"load_registry",
|
"load_registry",
|
||||||
"save_registry",
|
"save_registry",
|
||||||
"set_registry_levels",
|
"set_registry_levels",
|
||||||
|
"create_timer",
|
||||||
|
"open_timer",
|
||||||
|
"set_timer",
|
||||||
|
"cancel_timer",
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ### make_requests end ### */
|
/* ### make_requests end ### */
|
||||||
|
|
Loading…
Reference in New Issue