server: Change the timeout handling to use NT-style 64-bit timeouts everywhere.

This commit is contained in:
Alexandre Julliard 2007-04-17 20:08:59 +02:00
parent 31368dec93
commit aaf477f292
31 changed files with 298 additions and 404 deletions

View file

@ -1301,7 +1301,10 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
} }
pipe_wait->TimeoutSpecified = !(nTimeOut == NMPWAIT_USE_DEFAULT_WAIT); pipe_wait->TimeoutSpecified = !(nTimeOut == NMPWAIT_USE_DEFAULT_WAIT);
pipe_wait->Timeout.QuadPart = (ULONGLONG)nTimeOut * -10000; if (nTimeOut == NMPWAIT_WAIT_FOREVER)
pipe_wait->Timeout.QuadPart = ((ULONGLONG)0x7fffffff << 32) | 0xffffffff;
else
pipe_wait->Timeout.QuadPart = (ULONGLONG)nTimeOut * -10000;
pipe_wait->NameLength = nt_name.Length - sizeof(leadin); pipe_wait->NameLength = nt_name.Length - sizeof(leadin);
memcpy(pipe_wait->Name, nt_name.Buffer + sizeof(leadin)/sizeof(WCHAR), memcpy(pipe_wait->Name, nt_name.Buffer + sizeof(leadin)/sizeof(WCHAR),
pipe_wait->NameLength); pipe_wait->NameLength);
@ -1771,8 +1774,12 @@ BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
if( lpMessageCount ) if( lpMessageCount )
*lpMessageCount = info.MessagesAvailable; *lpMessageCount = info.MessagesAvailable;
if( lpReadTimeout ) if( lpReadTimeout )
*lpReadTimeout = info.ReadTimeout.QuadPart / -10000; {
if (info.ReadTimeout.QuadPart == (((LONGLONG)0x7fffffff << 32) | 0xffffffff))
*lpReadTimeout = MAILSLOT_WAIT_FOREVER;
else
*lpReadTimeout = info.ReadTimeout.QuadPart / -10000;
}
return TRUE; return TRUE;
} }
@ -1798,7 +1805,10 @@ BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
TRACE("%p %d\n", hMailslot, dwReadTimeout); TRACE("%p %d\n", hMailslot, dwReadTimeout);
info.ReadTimeout.QuadPart = dwReadTimeout * -10000; if (dwReadTimeout != MAILSLOT_WAIT_FOREVER)
info.ReadTimeout.QuadPart = (ULONGLONG)dwReadTimeout * -10000;
else
info.ReadTimeout.QuadPart = ((LONGLONG)0x7fffffff << 32) | 0xffffffff;
status = NtSetInformationFile( hMailslot, &iosb, &info, sizeof info, status = NtSetInformationFile( hMailslot, &iosb, &info, sizeof info,
FileMailslotSetInformation ); FileMailslotSetInformation );
if( status != STATUS_SUCCESS ) if( status != STATUS_SUCCESS )

View file

@ -430,7 +430,9 @@ static NTSTATUS get_io_timeouts( HANDLE handle, enum server_fd_type type, ULONG
{ {
req->handle = handle; req->handle = handle;
req->flags = 0; req->flags = 0;
if (!(status = wine_server_call( req ))) timeouts->total = reply->read_timeout; if (!(status = wine_server_call( req )) &&
reply->read_timeout != TIMEOUT_INFINITE)
timeouts->total = reply->read_timeout / -10000;
} }
SERVER_END_REQ; SERVER_END_REQ;
} }
@ -1113,8 +1115,7 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
SERVER_START_REQ(wait_named_pipe) SERVER_START_REQ(wait_named_pipe)
{ {
req->handle = handle; req->handle = handle;
req->timeout = buff->TimeoutSpecified ? buff->Timeout.QuadPart / -10000L req->timeout = buff->TimeoutSpecified ? buff->Timeout.QuadPart : 0;
: NMPWAIT_USE_DEFAULT_WAIT;
req->async.callback = pipe_completion_wait; req->async.callback = pipe_completion_wait;
req->async.iosb = io; req->async.iosb = io;
req->async.arg = NULL; req->async.arg = NULL;
@ -1467,7 +1468,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
info->MailslotQuota = 0; info->MailslotQuota = 0;
info->NextMessageSize = 0; info->NextMessageSize = 0;
info->MessagesAvailable = 0; info->MessagesAvailable = 0;
info->ReadTimeout.QuadPart = reply->read_timeout * -10000; info->ReadTimeout.QuadPart = reply->read_timeout;
} }
} }
SERVER_END_REQ; SERVER_END_REQ;
@ -1660,7 +1661,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
{ {
req->handle = handle; req->handle = handle;
req->flags = MAILSLOT_SET_READ_TIMEOUT; req->flags = MAILSLOT_SET_READ_TIMEOUT;
req->read_timeout = info->ReadTimeout.QuadPart / -10000; req->read_timeout = info->ReadTimeout.QuadPart;
io->u.Status = wine_server_call( req ); io->u.Status = wine_server_call( req );
} }
SERVER_END_REQ; SERVER_END_REQ;
@ -2186,8 +2187,8 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
options, pipe_type, read_mode, completion_mode, max_inst, inbound_quota, options, pipe_type, read_mode, completion_mode, max_inst, inbound_quota,
outbound_quota, timeout); outbound_quota, timeout);
/* assume we only get relative timeout, and storable in a DWORD as ms */ /* assume we only get relative timeout */
if (timeout->QuadPart > 0 || (timeout->QuadPart / -10000) >> 32) if (timeout->QuadPart > 0)
FIXME("Wrong time %s\n", wine_dbgstr_longlong(timeout->QuadPart)); FIXME("Wrong time %s\n", wine_dbgstr_longlong(timeout->QuadPart));
SERVER_START_REQ( create_named_pipe ) SERVER_START_REQ( create_named_pipe )
@ -2203,7 +2204,7 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
req->maxinstances = max_inst; req->maxinstances = max_inst;
req->outsize = outbound_quota; req->outsize = outbound_quota;
req->insize = inbound_quota; req->insize = inbound_quota;
req->timeout = timeout->QuadPart / -10000; req->timeout = timeout->QuadPart;
wine_server_add_data( req, attr->ObjectName->Buffer, wine_server_add_data( req, attr->ObjectName->Buffer,
attr->ObjectName->Length ); attr->ObjectName->Length );
status = wine_server_call( req ); status = wine_server_call( req );
@ -2306,7 +2307,7 @@ NTSTATUS WINAPI NtCreateMailslotFile(PHANDLE pHandle, ULONG DesiredAccess,
req->attributes = attr->Attributes; req->attributes = attr->Attributes;
req->rootdir = attr->RootDirectory; req->rootdir = attr->RootDirectory;
req->max_msgsize = MaxMessageSize; req->max_msgsize = MaxMessageSize;
req->read_timeout = (timeout.QuadPart <= 0) ? timeout.QuadPart / -10000 : -1; req->read_timeout = timeout.QuadPart;
wine_server_add_data( req, attr->ObjectName->Buffer, wine_server_add_data( req, attr->ObjectName->Buffer,
attr->ObjectName->Length ); attr->ObjectName->Length );
ret = wine_server_call( req ); ret = wine_server_call( req );

View file

@ -696,7 +696,7 @@ NTSTATUS WINAPI NtQuerySystemInformation(
memset(&sti, 0 , sizeof(sti)); memset(&sti, 0 , sizeof(sti));
/* liKeSystemTime, liExpTimeZoneBias, uCurrentTimeZoneId */ /* liKeSystemTime, liExpTimeZoneBias, uCurrentTimeZoneId */
NTDLL_from_server_abstime( &sti.liKeBootTime, &server_start_time ); sti.liKeBootTime.QuadPart = server_start_time;
if (Length <= sizeof(sti)) if (Length <= sizeof(sti))
{ {

View file

@ -40,8 +40,6 @@ extern void set_cpu_context( const CONTEXT *context );
extern LPCSTR debugstr_us( const UNICODE_STRING *str ); extern LPCSTR debugstr_us( const UNICODE_STRING *str );
extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes); extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes);
extern void NTDLL_get_server_abstime( abs_time_t *when, const LARGE_INTEGER *timeout );
extern void NTDLL_from_server_abstime( LARGE_INTEGER *time, const abs_time_t *when );
extern NTSTATUS NTDLL_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result ); extern NTSTATUS NTDLL_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result );
extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags, extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags,
const LARGE_INTEGER *timeout, HANDLE signal_object ); const LARGE_INTEGER *timeout, HANDLE signal_object );
@ -56,7 +54,7 @@ extern void virtual_init(void);
extern void virtual_init_threading(void); extern void virtual_init_threading(void);
/* server support */ /* server support */
extern abs_time_t server_start_time; extern timeout_t server_start_time;
extern void server_init_process(void); extern void server_init_process(void);
extern NTSTATUS server_init_process_done(void); extern NTSTATUS server_init_process_done(void);
extern size_t server_init_thread( int unix_pid, int unix_tid, void *entry_point ); extern size_t server_init_thread( int unix_pid, int unix_tid, void *entry_point );

View file

@ -236,8 +236,8 @@ NTSTATUS WINAPI NtQueryInformationProcess(
req->handle = ProcessHandle; req->handle = ProcessHandle;
if ((ret = wine_server_call( req )) == STATUS_SUCCESS) if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
{ {
NTDLL_from_server_abstime(&pti.CreateTime, &reply->start_time); pti.CreateTime.QuadPart = reply->start_time;
NTDLL_from_server_abstime(&pti.ExitTime, &reply->end_time); pti.ExitTime.QuadPart = reply->end_time;
} }
} }
SERVER_END_REQ; SERVER_END_REQ;

View file

@ -85,7 +85,7 @@ struct cmsg_fd
}; };
#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
abs_time_t server_start_time = { 0, 0 }; /* time of server startup */ timeout_t server_start_time = 0; /* time of server startup */
extern struct wine_pthread_functions pthread_functions; extern struct wine_pthread_functions pthread_functions;

View file

@ -478,16 +478,9 @@ NTSTATUS WINAPI NtSetTimer(IN HANDLE handle,
SERVER_START_REQ( set_timer ) SERVER_START_REQ( set_timer )
{ {
if (!when->u.LowPart && !when->u.HighPart)
{
/* special case to start timeout on now+period without too many calculations */
req->expire.sec = 0;
req->expire.usec = 0;
}
else NTDLL_get_server_abstime( &req->expire, when );
req->handle = handle; req->handle = handle;
req->period = period; req->period = period;
req->expire = when->QuadPart;
req->callback = callback; req->callback = callback;
req->arg = callback_arg; req->arg = callback_arg;
status = wine_server_call( req ); status = wine_server_call( req );
@ -564,7 +557,7 @@ NTSTATUS WINAPI NtQueryTimer(
status = wine_server_call(req); status = wine_server_call(req);
/* convert server time to absolute NTDLL time */ /* convert server time to absolute NTDLL time */
NTDLL_from_server_abstime(&basic_info->RemainingTime, &reply->when); basic_info->RemainingTime.QuadPart = reply->when;
basic_info->TimerState = reply->signaled; basic_info->TimerState = reply->signaled;
} }
SERVER_END_REQ; SERVER_END_REQ;
@ -670,15 +663,9 @@ static BOOL invoke_apc( const apc_call_t *call, apc_result_t *result )
user_apc = TRUE; user_apc = TRUE;
break; break;
case APC_TIMER: case APC_TIMER:
{ call->timer.func( call->timer.arg, (DWORD)call->timer.time, (DWORD)(call->timer.time >> 32) );
LARGE_INTEGER time;
/* convert sec/usec to NT time */
RtlSecondsSince1970ToTime( call->timer.time.sec, &time );
time.QuadPart += call->timer.time.usec * 10;
call->timer.func( call->timer.arg, time.u.LowPart, time.u.HighPart );
user_apc = TRUE; user_apc = TRUE;
break; break;
}
case APC_ASYNC_IO: case APC_ASYNC_IO:
result->type = call->type; result->type = call->type;
result->async_io.status = call->async_io.func( call->async_io.user, result->async_io.status = call->async_io.func( call->async_io.user,
@ -895,10 +882,8 @@ NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UIN
{ {
NTSTATUS ret; NTSTATUS ret;
int cookie; int cookie;
abs_time_t abs_timeout; timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
NTDLL_get_server_abstime( &abs_timeout, timeout );
if (timeout) flags |= SELECT_TIMEOUT;
for (;;) for (;;)
{ {
SERVER_START_REQ( select ) SERVER_START_REQ( select )
@ -909,6 +894,7 @@ NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UIN
req->timeout = abs_timeout; req->timeout = abs_timeout;
wine_server_add_data( req, handles, count * sizeof(HANDLE) ); wine_server_add_data( req, handles, count * sizeof(HANDLE) );
ret = wine_server_call( req ); ret = wine_server_call( req );
abs_timeout = reply->timeout;
} }
SERVER_END_REQ; SERVER_END_REQ;
if (ret == STATUS_PENDING) ret = wait_reply( &cookie ); if (ret == STATUS_PENDING) ret = wait_reply( &cookie );
@ -995,32 +981,33 @@ NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeou
return NTDLL_wait_for_multiple_objects( 0, NULL, flags, timeout, 0 ); return NTDLL_wait_for_multiple_objects( 0, NULL, flags, timeout, 0 );
} }
if (!timeout) /* sleep forever */ if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) /* sleep forever */
{ {
for (;;) select( 0, NULL, NULL, NULL, NULL ); for (;;) select( 0, NULL, NULL, NULL, NULL );
} }
else else
{ {
abs_time_t when; LARGE_INTEGER now;
timeout_t when, diff;
NTDLL_get_server_abstime( &when, timeout ); if ((when = timeout->QuadPart) < 0)
{
NtQuerySystemTime( &now );
when = now.QuadPart - when;
}
/* Note that we yield after establishing the desired timeout */ /* Note that we yield after establishing the desired timeout */
NtYieldExecution(); NtYieldExecution();
if (!when) return STATUS_SUCCESS;
for (;;) for (;;)
{ {
struct timeval tv; struct timeval tv;
gettimeofday( &tv, 0 ); NtQuerySystemTime( &now );
tv.tv_sec = when.sec - tv.tv_sec; diff = (when - now.QuadPart + 9) / 10;
if ((tv.tv_usec = when.usec - tv.tv_usec) < 0) if (diff <= 0) break;
{ tv.tv_sec = diff / 1000000;
tv.tv_usec += 1000000; tv.tv_usec = diff % 1000000;
tv.tv_sec--;
}
/* if our yield already passed enough time, we're done */
if (tv.tv_sec < 0) break;
if (select( 0, NULL, NULL, NULL, &tv ) != -1) break; if (select( 0, NULL, NULL, NULL, &tv ) != -1) break;
} }
} }

View file

@ -1186,8 +1186,8 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
status = wine_server_call( req ); status = wine_server_call( req );
if (status == STATUS_SUCCESS) if (status == STATUS_SUCCESS)
{ {
NTDLL_from_server_abstime( &kusrt.CreateTime, &reply->creation_time ); kusrt.CreateTime.QuadPart = reply->creation_time;
NTDLL_from_server_abstime( &kusrt.ExitTime, &reply->exit_time ); kusrt.ExitTime.QuadPart = reply->exit_time;
} }
} }
SERVER_END_REQ; SERVER_END_REQ;

View file

@ -446,67 +446,6 @@ static inline int IsLeapYear(int Year)
return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0; return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
} }
/***********************************************************************
* NTDLL_get_server_abstime
*
* Convert a NTDLL time into an abs_time_t struct to send to the server.
*/
void NTDLL_get_server_abstime( abs_time_t *when, const LARGE_INTEGER *timeout )
{
UINT remainder;
if (!timeout) /* infinite timeout */
{
when->sec = when->usec = 0;
}
else if (timeout->QuadPart <= 0) /* relative timeout */
{
struct timeval tv;
if (-timeout->QuadPart > (LONGLONG)INT_MAX * TICKSPERSEC)
when->sec = when->usec = INT_MAX;
else
{
ULONG sec = RtlEnlargedUnsignedDivide( -timeout->QuadPart, TICKSPERSEC, &remainder );
gettimeofday( &tv, 0 );
when->sec = tv.tv_sec + sec;
if ((when->usec = tv.tv_usec + (remainder / 10)) >= 1000000)
{
when->usec -= 1000000;
when->sec++;
}
if (when->sec < tv.tv_sec) /* overflow */
when->sec = when->usec = INT_MAX;
}
}
else /* absolute time */
{
if (timeout->QuadPart < TICKS_1601_TO_1970)
when->sec = when->usec = 0;
else if (timeout->QuadPart > TICKS_1601_TO_UNIX_MAX)
when->sec = when->usec = INT_MAX;
else
{
when->sec = RtlEnlargedUnsignedDivide( timeout->QuadPart - TICKS_1601_TO_1970,
TICKSPERSEC, &remainder );
when->usec = remainder / 10;
}
}
}
/***********************************************************************
* NTDLL_from_server_abstime
*
* Convert a timeval struct from the server into an NTDLL time.
*/
void NTDLL_from_server_abstime( LARGE_INTEGER *time, const abs_time_t *when )
{
time->QuadPart = when->sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
time->QuadPart += when->usec * 10;
}
/****************************************************************************** /******************************************************************************
* RtlTimeToTimeFields [NTDLL.@] * RtlTimeToTimeFields [NTDLL.@]
* *
@ -878,16 +817,15 @@ NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time )
*/ */
NTSTATUS WINAPI NtQueryPerformanceCounter( PLARGE_INTEGER Counter, PLARGE_INTEGER Frequency ) NTSTATUS WINAPI NtQueryPerformanceCounter( PLARGE_INTEGER Counter, PLARGE_INTEGER Frequency )
{ {
struct timeval now; LARGE_INTEGER now;
if (!Counter) return STATUS_ACCESS_VIOLATION; if (!Counter) return STATUS_ACCESS_VIOLATION;
gettimeofday( &now, 0 );
/* convert a counter that increments at a rate of 1 MHz /* convert a counter that increments at a rate of 10 MHz
* to one of 1.193182 MHz, with some care for arithmetic * to one of 1.193182 MHz, with some care for arithmetic
* overflow ( will not overflow for 5000 years ) and * overflow and good accuracy (21/176 = 0.11931818) */
* good accuracy ( 105/88 = 1.19318182) */ NtQuerySystemTime( &now );
Counter->QuadPart = (((now.tv_sec - server_start_time.sec) * (ULONGLONG)1000000 + Counter->QuadPart = ((now.QuadPart - server_start_time) * 21) / 176;
(now.tv_usec - server_start_time.usec)) * 105) / 88;
if (Frequency) Frequency->QuadPart = 1193182; if (Frequency) Frequency->QuadPart = 1193182;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -899,11 +837,10 @@ NTSTATUS WINAPI NtQueryPerformanceCounter( PLARGE_INTEGER Counter, PLARGE_INTEGE
*/ */
ULONG WINAPI NtGetTickCount(void) ULONG WINAPI NtGetTickCount(void)
{ {
struct timeval current_time; LARGE_INTEGER now;
gettimeofday(&current_time, NULL); NtQuerySystemTime( &now );
return (current_time.tv_sec - server_start_time.sec) * 1000 + return (now.QuadPart - server_start_time) / 10000;
(current_time.tv_usec - server_start_time.usec) / 1000;
} }

View file

@ -1399,7 +1399,7 @@ static BOOL post_dde_message( struct packed_message *data, const struct send_mes
req->msg = info->msg; req->msg = info->msg;
req->wparam = info->wparam; req->wparam = info->wparam;
req->lparam = lp; req->lparam = lp;
req->timeout = 0; req->timeout = TIMEOUT_INFINITE;
for (i = 0; i < data->count; i++) for (i = 0; i < data->count; i++)
wine_server_add_data( req, data->data[i], data->size[i] ); wine_server_add_data( req, data->data[i], data->size[i] );
if ((res = wine_server_call( req ))) if ((res = wine_server_call( req )))
@ -2201,7 +2201,8 @@ static BOOL put_message_in_queue( const struct send_message_info *info, size_t *
struct packed_message data; struct packed_message data;
message_data_t msg_data; message_data_t msg_data;
unsigned int res; unsigned int res;
int i, timeout = 0; int i;
timeout_t timeout = TIMEOUT_INFINITE;
/* Check for INFINITE timeout for compatibility with Win9x, /* Check for INFINITE timeout for compatibility with Win9x,
* although Windows >= NT does not do so * although Windows >= NT does not do so
@ -2209,8 +2210,12 @@ static BOOL put_message_in_queue( const struct send_message_info *info, size_t *
if (info->type != MSG_NOTIFY && if (info->type != MSG_NOTIFY &&
info->type != MSG_CALLBACK && info->type != MSG_CALLBACK &&
info->type != MSG_POSTED && info->type != MSG_POSTED &&
info->timeout &&
info->timeout != INFINITE) info->timeout != INFINITE)
timeout = info->timeout; {
/* timeout is signed despite the prototype */
timeout = (timeout_t)max( 0, (int)info->timeout ) * -10000;
}
data.count = 0; data.count = 0;
if (info->type == MSG_OTHER_PROCESS) if (info->type == MSG_OTHER_PROCESS)

View file

@ -133,11 +133,8 @@ struct wake_up_reply
}; };
typedef struct typedef __int64 timeout_t;
{ #define TIMEOUT_INFINITE (((timeout_t)0x7fffffff) << 32 | 0xffffffff)
int sec;
int usec;
} abs_time_t;
typedef struct typedef struct
@ -257,7 +254,7 @@ typedef union
{ {
enum apc_type type; enum apc_type type;
void (__stdcall *func)(void*, unsigned int, unsigned int); void (__stdcall *func)(void*, unsigned int, unsigned int);
abs_time_t time; timeout_t time;
void *arg; void *arg;
} timer; } timer;
struct struct
@ -540,7 +537,7 @@ struct init_thread_reply
process_id_t pid; process_id_t pid;
thread_id_t tid; thread_id_t tid;
data_size_t info_size; data_size_t info_size;
abs_time_t server_start; timeout_t server_start;
int version; int version;
}; };
@ -589,8 +586,8 @@ struct get_process_info_reply
int priority; int priority;
int affinity; int affinity;
void* peb; void* peb;
abs_time_t start_time; timeout_t start_time;
abs_time_t end_time; timeout_t end_time;
}; };
@ -627,8 +624,8 @@ struct get_thread_info_reply
int exit_code; int exit_code;
int priority; int priority;
int affinity; int affinity;
abs_time_t creation_time; timeout_t creation_time;
abs_time_t exit_time; timeout_t exit_time;
int last; int last;
}; };
@ -856,17 +853,17 @@ struct select_request
int flags; int flags;
void* cookie; void* cookie;
obj_handle_t signal; obj_handle_t signal;
abs_time_t timeout; timeout_t timeout;
/* VARARG(handles,handles); */ /* VARARG(handles,handles); */
}; };
struct select_reply struct select_reply
{ {
struct reply_header __header; struct reply_header __header;
timeout_t timeout;
}; };
#define SELECT_ALL 1 #define SELECT_ALL 1
#define SELECT_ALERTABLE 2 #define SELECT_ALERTABLE 2
#define SELECT_INTERRUPTIBLE 4 #define SELECT_INTERRUPTIBLE 4
#define SELECT_TIMEOUT 8
@ -2181,7 +2178,7 @@ struct set_timer_request
{ {
struct request_header __header; struct request_header __header;
obj_handle_t handle; obj_handle_t handle;
abs_time_t expire; timeout_t expire;
int period; int period;
void* callback; void* callback;
void* arg; void* arg;
@ -2213,7 +2210,7 @@ struct get_timer_info_request
struct get_timer_info_reply struct get_timer_info_reply
{ {
struct reply_header __header; struct reply_header __header;
abs_time_t when; timeout_t when;
int signaled; int signaled;
}; };
@ -2442,7 +2439,7 @@ struct send_message_request
unsigned int msg; unsigned int msg;
unsigned long wparam; unsigned long wparam;
unsigned long lparam; unsigned long lparam;
int timeout; timeout_t timeout;
/* VARARG(data,message_data); */ /* VARARG(data,message_data); */
}; };
struct send_message_reply struct send_message_reply
@ -2694,7 +2691,7 @@ struct create_named_pipe_request
unsigned int maxinstances; unsigned int maxinstances;
unsigned int outsize; unsigned int outsize;
unsigned int insize; unsigned int insize;
unsigned int timeout; timeout_t timeout;
/* VARARG(name,unicode_str); */ /* VARARG(name,unicode_str); */
}; };
struct create_named_pipe_reply struct create_named_pipe_reply
@ -2728,7 +2725,7 @@ struct wait_named_pipe_request
struct request_header __header; struct request_header __header;
obj_handle_t handle; obj_handle_t handle;
async_data_t async; async_data_t async;
unsigned int timeout; timeout_t timeout;
/* VARARG(name,unicode_str); */ /* VARARG(name,unicode_str); */
}; };
struct wait_named_pipe_reply struct wait_named_pipe_reply
@ -3853,7 +3850,7 @@ struct create_mailslot_request
unsigned int attributes; unsigned int attributes;
obj_handle_t rootdir; obj_handle_t rootdir;
unsigned int max_msgsize; unsigned int max_msgsize;
int read_timeout; timeout_t read_timeout;
/* VARARG(name,unicode_str); */ /* VARARG(name,unicode_str); */
}; };
struct create_mailslot_reply struct create_mailslot_reply
@ -3869,13 +3866,13 @@ struct set_mailslot_info_request
struct request_header __header; struct request_header __header;
obj_handle_t handle; obj_handle_t handle;
unsigned int flags; unsigned int flags;
int read_timeout; timeout_t read_timeout;
}; };
struct set_mailslot_info_reply struct set_mailslot_info_reply
{ {
struct reply_header __header; struct reply_header __header;
unsigned int max_msgsize; unsigned int max_msgsize;
int read_timeout; timeout_t read_timeout;
}; };
#define MAILSLOT_SET_READ_TIMEOUT 1 #define MAILSLOT_SET_READ_TIMEOUT 1
@ -4660,6 +4657,6 @@ union generic_reply
struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply; struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply;
}; };
#define SERVER_PROTOCOL_VERSION 295 #define SERVER_PROTOCOL_VERSION 296
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View file

@ -214,10 +214,10 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
} }
/* set the timeout of an async operation */ /* set the timeout of an async operation */
void async_set_timeout( struct async *async, const struct timeval *timeout, unsigned int status ) void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status )
{ {
if (async->timeout) remove_timeout_user( async->timeout ); if (async->timeout) remove_timeout_user( async->timeout );
if (timeout) async->timeout = add_timeout_user( timeout, async_timeout, async ); if (timeout != TIMEOUT_INFINITE) async->timeout = add_timeout_user( timeout, async_timeout, async );
else async->timeout = NULL; else async->timeout = NULL;
async->timeout_status = status; async->timeout_status = status;
} }

View file

@ -322,23 +322,30 @@ static file_pos_t max_unix_offset = OFF_T_MAX;
struct timeout_user struct timeout_user
{ {
struct list entry; /* entry in sorted timeout list */ struct list entry; /* entry in sorted timeout list */
struct timeval when; /* timeout expiry (absolute time) */ timeout_t when; /* timeout expiry (absolute time) */
timeout_callback callback; /* callback function */ timeout_callback callback; /* callback function */
void *private; /* callback private data */ void *private; /* callback private data */
}; };
static struct list timeout_list = LIST_INIT(timeout_list); /* sorted timeouts list */ static struct list timeout_list = LIST_INIT(timeout_list); /* sorted timeouts list */
struct timeval current_time; timeout_t current_time;
static inline void set_current_time(void)
{
static const timeout_t ticks_1601_to_1970 = (timeout_t)86400 * (369 * 365 + 89) * TICKS_PER_SEC;
struct timeval now;
gettimeofday( &now, NULL );
current_time = (timeout_t)now.tv_sec * TICKS_PER_SEC + now.tv_usec * 10 + ticks_1601_to_1970;
}
/* add a timeout user */ /* add a timeout user */
struct timeout_user *add_timeout_user( const struct timeval *when, timeout_callback func, struct timeout_user *add_timeout_user( timeout_t when, timeout_callback func, void *private )
void *private )
{ {
struct timeout_user *user; struct timeout_user *user;
struct list *ptr; struct list *ptr;
if (!(user = mem_alloc( sizeof(*user) ))) return NULL; if (!(user = mem_alloc( sizeof(*user) ))) return NULL;
user->when = *when; user->when = (when > 0) ? when : current_time - when;
user->callback = func; user->callback = func;
user->private = private; user->private = private;
@ -347,7 +354,7 @@ struct timeout_user *add_timeout_user( const struct timeval *when, timeout_callb
LIST_FOR_EACH( ptr, &timeout_list ) LIST_FOR_EACH( ptr, &timeout_list )
{ {
struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry ); struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry );
if (!time_before( &timeout->when, when )) break; if (timeout->when >= user->when) break;
} }
list_add_before( ptr, &user->entry ); list_add_before( ptr, &user->entry );
return user; return user;
@ -360,19 +367,39 @@ void remove_timeout_user( struct timeout_user *user )
free( user ); free( user );
} }
/* add a timeout in milliseconds to an absolute time */ /* return a text description of a timeout for debugging purposes */
void add_timeout( struct timeval *when, int timeout ) const char *get_timeout_str( timeout_t timeout )
{ {
if (timeout) static char buffer[64];
long secs, nsecs;
if (!timeout) return "0";
if (timeout == TIMEOUT_INFINITE) return "infinite";
if (timeout < 0) /* relative */
{ {
long sec = timeout / 1000; secs = -timeout / TICKS_PER_SEC;
if ((when->tv_usec += (timeout - 1000*sec) * 1000) >= 1000000) nsecs = -timeout % TICKS_PER_SEC;
{ sprintf( buffer, "+%ld.%07ld", secs, nsecs );
when->tv_usec -= 1000000;
when->tv_sec++;
}
when->tv_sec += sec;
} }
else /* absolute */
{
secs = (timeout - current_time) / TICKS_PER_SEC;
nsecs = (timeout - current_time) % TICKS_PER_SEC;
if (nsecs < 0)
{
nsecs += TICKS_PER_SEC;
secs--;
}
if (secs >= 0)
sprintf( buffer, "%x%08x (+%ld.%07ld)",
(unsigned int)(timeout >> 32), (unsigned int)timeout, secs, nsecs );
else
sprintf( buffer, "%x%08x (-%ld.%07ld)",
(unsigned int)(timeout >> 32), (unsigned int)timeout,
-(secs + 1), TICKS_PER_SEC - nsecs );
}
return buffer;
} }
@ -467,7 +494,7 @@ static inline void main_loop_epoll(void)
if (epoll_fd == -1) break; /* an error occurred with epoll */ if (epoll_fd == -1) break; /* an error occurred with epoll */
ret = epoll_wait( epoll_fd, events, sizeof(events)/sizeof(events[0]), timeout ); ret = epoll_wait( epoll_fd, events, sizeof(events)/sizeof(events[0]), timeout );
gettimeofday( &current_time, NULL ); set_current_time();
/* put the events into the pollfd array first, like poll does */ /* put the events into the pollfd array first, like poll does */
for (i = 0; i < ret; i++) for (i = 0; i < ret; i++)
@ -573,7 +600,7 @@ static inline void main_loop_epoll(void)
} }
else ret = kevent( kqueue_fd, NULL, 0, events, sizeof(events)/sizeof(events[0]), NULL ); else ret = kevent( kqueue_fd, NULL, 0, events, sizeof(events)/sizeof(events[0]), NULL );
gettimeofday( &current_time, NULL ); set_current_time();
/* put the events into the pollfd array first, like poll does */ /* put the events into the pollfd array first, like poll does */
for (i = 0; i < ret; i++) for (i = 0; i < ret; i++)
@ -679,7 +706,7 @@ static int get_next_timeout(void)
{ {
struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry ); struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry );
if (!time_before( &current_time, &timeout->when )) if (timeout->when <= current_time)
{ {
list_remove( &timeout->entry ); list_remove( &timeout->entry );
list_add_tail( &expired_list, &timeout->entry ); list_add_tail( &expired_list, &timeout->entry );
@ -700,8 +727,7 @@ static int get_next_timeout(void)
if ((ptr = list_head( &timeout_list )) != NULL) if ((ptr = list_head( &timeout_list )) != NULL)
{ {
struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry ); struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry );
int diff = (timeout->when.tv_sec - current_time.tv_sec) * 1000 int diff = (timeout->when - current_time + 9999) / 10000;
+ (timeout->when.tv_usec - current_time.tv_usec + 999) / 1000;
if (diff < 0) diff = 0; if (diff < 0) diff = 0;
return diff; return diff;
} }
@ -714,7 +740,8 @@ void main_loop(void)
{ {
int i, ret, timeout; int i, ret, timeout;
gettimeofday( &current_time, NULL ); set_current_time();
server_start_time = current_time;
main_loop_epoll(); main_loop_epoll();
/* fall through to normal poll loop */ /* fall through to normal poll loop */
@ -726,7 +753,7 @@ void main_loop(void)
if (!active_users) break; /* last user removed by a timeout */ if (!active_users) break; /* last user removed by a timeout */
ret = poll( pollfd, nb_users, timeout ); ret = poll( pollfd, nb_users, timeout );
gettimeofday( &current_time, NULL ); set_current_time();
if (ret > 0) if (ret > 0)
{ {

View file

@ -91,20 +91,15 @@ static inline struct fd *get_obj_fd( struct object *obj ) { return obj->ops->get
/* timeout functions */ /* timeout functions */
struct timeout_user; struct timeout_user;
extern struct timeval current_time; extern timeout_t current_time;
#define TICKS_PER_SEC 10000000
typedef void (*timeout_callback)( void *private ); typedef void (*timeout_callback)( void *private );
extern struct timeout_user *add_timeout_user( const struct timeval *when, extern struct timeout_user *add_timeout_user( timeout_t when, timeout_callback func, void *private );
timeout_callback func, void *private );
extern void remove_timeout_user( struct timeout_user *user ); extern void remove_timeout_user( struct timeout_user *user );
extern void add_timeout( struct timeval *when, int timeout ); extern const char *get_timeout_str( timeout_t timeout );
/* return 1 if t1 is before t2 */
static inline int time_before( const struct timeval *t1, const struct timeval *t2 )
{
return ((t1->tv_sec < t2->tv_sec) ||
((t1->tv_sec == t2->tv_sec) && (t1->tv_usec < t2->tv_usec)));
}
/* file functions */ /* file functions */
@ -133,8 +128,7 @@ extern struct async_queue *create_async_queue( struct fd *fd );
extern void free_async_queue( struct async_queue *queue ); extern void free_async_queue( struct async_queue *queue );
extern struct async *create_async( struct thread *thread, struct async_queue *queue, extern struct async *create_async( struct thread *thread, struct async_queue *queue,
const async_data_t *data ); const async_data_t *data );
extern void async_set_timeout( struct async *async, const struct timeval *timeout, extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );
unsigned int status );
extern void async_set_result( struct object *obj, unsigned int status ); extern void async_set_result( struct object *obj, unsigned int status );
extern int async_waiting( struct async_queue *queue ); extern int async_waiting( struct async_queue *queue );
extern void async_wake_up( struct async_queue *queue, unsigned int status ); extern void async_wake_up( struct async_queue *queue, unsigned int status );

View file

@ -58,7 +58,7 @@ struct mailslot
struct fd *fd; struct fd *fd;
int write_fd; int write_fd;
unsigned int max_msgsize; unsigned int max_msgsize;
int read_timeout; timeout_t read_timeout;
struct list writers; struct list writers;
}; };
@ -214,8 +214,8 @@ static void mailslot_dump( struct object *obj, int verbose )
struct mailslot *mailslot = (struct mailslot *) obj; struct mailslot *mailslot = (struct mailslot *) obj;
assert( obj->ops == &mailslot_ops ); assert( obj->ops == &mailslot_ops );
fprintf( stderr, "Mailslot max_msgsize=%d read_timeout=%d\n", fprintf( stderr, "Mailslot max_msgsize=%d read_timeout=%s\n",
mailslot->max_msgsize, mailslot->read_timeout ); mailslot->max_msgsize, get_timeout_str(mailslot->read_timeout) );
} }
static enum server_fd_type mailslot_get_fd_type( struct fd *fd ) static enum server_fd_type mailslot_get_fd_type( struct fd *fd )
@ -299,12 +299,8 @@ static void mailslot_queue_async( struct fd *fd, const async_data_t *data, int t
if ((async = fd_queue_async( fd, data, type, count ))) if ((async = fd_queue_async( fd, data, type, count )))
{ {
if (mailslot->read_timeout != -1) async_set_timeout( async, mailslot->read_timeout ? mailslot->read_timeout : -1,
{ STATUS_IO_TIMEOUT );
struct timeval when = current_time;
add_timeout( &when, max(1,mailslot->read_timeout) );
async_set_timeout( async, &when, STATUS_IO_TIMEOUT );
}
release_object( async ); release_object( async );
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
} }
@ -375,7 +371,7 @@ void create_mailslot_device( struct directory *root, const struct unicode_str *n
static struct mailslot *create_mailslot( struct directory *root, static struct mailslot *create_mailslot( struct directory *root,
const struct unicode_str *name, unsigned int attr, const struct unicode_str *name, unsigned int attr,
int max_msgsize, int read_timeout ) int max_msgsize, timeout_t read_timeout )
{ {
struct object *obj; struct object *obj;
struct unicode_str new_name; struct unicode_str new_name;

View file

@ -36,8 +36,8 @@
/* command-line options */ /* command-line options */
int debug_level = 0; int debug_level = 0;
int master_socket_timeout = 3; /* master socket timeout in seconds, default is 3 s */
int foreground = 0; int foreground = 0;
timeout_t master_socket_timeout = 3 * -TICKS_PER_SEC; /* master socket timeout, default is 3 seconds */
const char *server_argv0; const char *server_argv0;
/* parse-line args */ /* parse-line args */
@ -84,8 +84,10 @@ static void parse_args( int argc, char *argv[] )
else ret = kill_lock_owner(-1); else ret = kill_lock_owner(-1);
exit( !ret ); exit( !ret );
case 'p': case 'p':
if (isdigit(argv[i][2])) master_socket_timeout = atoi( argv[i] + 2 ); if (isdigit(argv[i][2]))
else master_socket_timeout = -1; master_socket_timeout = (timeout_t)atoi( argv[i] + 2 ) * -TICKS_PER_SEC;
else
master_socket_timeout = TIMEOUT_INFINITE;
break; break;
case 'v': case 'v':
fprintf( stderr, "%s\n", PACKAGE_STRING ); fprintf( stderr, "%s\n", PACKAGE_STRING );

View file

@ -94,8 +94,8 @@ struct named_pipe
unsigned int maxinstances; unsigned int maxinstances;
unsigned int outsize; unsigned int outsize;
unsigned int insize; unsigned int insize;
unsigned int timeout;
unsigned int instances; unsigned int instances;
timeout_t timeout;
struct list servers; /* list of servers using this pipe */ struct list servers; /* list of servers using this pipe */
struct async_queue *waiters; /* list of clients waiting to connect */ struct async_queue *waiters; /* list of clients waiting to connect */
}; };
@ -512,9 +512,7 @@ static void check_flushed( void *arg )
assert( server->event ); assert( server->event );
if (pipe_data_remaining( server )) if (pipe_data_remaining( server ))
{ {
struct timeval tv = current_time; server->flush_poll = add_timeout_user( -TICKS_PER_SEC / 10, check_flushed, server );
add_timeout( &tv, 100 );
server->flush_poll = add_timeout_user( &tv, check_flushed, server );
} }
else else
{ {
@ -538,14 +536,11 @@ static void pipe_server_flush( struct fd *fd, struct event **event )
if (pipe_data_remaining( server )) if (pipe_data_remaining( server ))
{ {
struct timeval tv = current_time;
/* this kind of sux - /* this kind of sux -
there's no unix way to be alerted when a pipe becomes empty */ there's no unix way to be alerted when a pipe becomes empty */
server->event = create_event( NULL, NULL, 0, 0, 0 ); server->event = create_event( NULL, NULL, 0, 0, 0 );
if (!server->event) return; if (!server->event) return;
add_timeout( &tv, 100 ); server->flush_poll = add_timeout_user( -TICKS_PER_SEC / 10, check_flushed, server );
server->flush_poll = add_timeout_user( &tv, check_flushed, server );
*event = server->event; *event = server->event;
} }
} }
@ -901,13 +896,7 @@ DECL_HANDLER(wait_named_pipe)
if ((async = create_async( current, pipe->waiters, &req->async ))) if ((async = create_async( current, pipe->waiters, &req->async )))
{ {
if (req->timeout != NMPWAIT_WAIT_FOREVER) async_set_timeout( async, req->timeout ? req->timeout : pipe->timeout, STATUS_TIMEOUT );
{
struct timeval when = current_time;
if (req->timeout == NMPWAIT_USE_DEFAULT_WAIT) add_timeout( &when, pipe->timeout );
else add_timeout( &when, req->timeout );
async_set_timeout( async, &when, STATUS_TIMEOUT );
}
release_object( async ); release_object( async );
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
} }

View file

@ -214,11 +214,11 @@ extern void create_mailslot_device( struct directory *root, const struct unicode
/* command-line options */ /* command-line options */
extern int debug_level; extern int debug_level;
extern int master_socket_timeout;
extern int foreground; extern int foreground;
extern timeout_t master_socket_timeout;
extern const char *server_argv0; extern const char *server_argv0;
/* server start time used for GetTickCount() */ /* server start time used for GetTickCount() */
extern struct timeval server_start_time; extern timeout_t server_start_time;
#endif /* __WINE_SERVER_OBJECT_H */ #endif /* __WINE_SERVER_OBJECT_H */

View file

@ -244,13 +244,9 @@ static void start_sigkill_timer( struct process *process )
{ {
grab_object( process ); grab_object( process );
if (process->unix_pid != -1 && process->msg_fd) if (process->unix_pid != -1 && process->msg_fd)
{ process->sigkill_timeout = add_timeout_user( -TICKS_PER_SEC, process_sigkill, process );
struct timeval when = current_time; else
process_died( process );
add_timeout( &when, 1000 );
process->sigkill_timeout = add_timeout_user( &when, process_sigkill, process );
}
else process_died( process );
} }
/* create a new process and its main thread */ /* create a new process and its main thread */
@ -295,7 +291,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
list_init( &process->dlls ); list_init( &process->dlls );
process->start_time = current_time; process->start_time = current_time;
process->end_time.tv_sec = process->end_time.tv_usec = 0; process->end_time = 0;
list_add_head( &process_list, &process->entry ); list_add_head( &process_list, &process->entry );
if (!(process->id = process->group_id = alloc_ptid( process ))) if (!(process->id = process->group_id = alloc_ptid( process )))
@ -1013,10 +1009,8 @@ DECL_HANDLER(get_process_info)
reply->priority = process->priority; reply->priority = process->priority;
reply->affinity = process->affinity; reply->affinity = process->affinity;
reply->peb = process->peb; reply->peb = process->peb;
reply->start_time.sec = process->start_time.tv_sec; reply->start_time = process->start_time;
reply->start_time.usec = process->start_time.tv_usec; reply->end_time = process->end_time;
reply->end_time.sec = process->end_time.tv_sec;
reply->end_time.usec = process->end_time.tv_usec;
release_object( process ); release_object( process );
} }
} }

View file

@ -61,8 +61,8 @@ struct process
int unix_pid; /* Unix pid for final SIGKILL */ int unix_pid; /* Unix pid for final SIGKILL */
int exit_code; /* process exit code */ int exit_code; /* process exit code */
int running_threads; /* number of threads running in this process */ int running_threads; /* number of threads running in this process */
struct timeval start_time; /* absolute time at process start */ timeout_t start_time; /* absolute time at process start */
struct timeval end_time; /* absolute time at process end */ timeout_t end_time; /* absolute time at process end */
int priority; /* priority class */ int priority; /* priority class */
int affinity; /* process affinity mask */ int affinity; /* process affinity mask */
int suspend; /* global process suspend count */ int suspend; /* global process suspend count */

View file

@ -148,12 +148,9 @@ struct wake_up_reply
int signaled; /* wait result */ int signaled; /* wait result */
}; };
/* structure for absolute timeouts */ /* NT-style timeout, in 100ns units, negative means relative timeout */
typedef struct typedef __int64 timeout_t;
{ #define TIMEOUT_INFINITE (((timeout_t)0x7fffffff) << 32 | 0xffffffff)
int sec; /* seconds since Unix epoch */
int usec; /* microseconds */
} abs_time_t;
/* structure returned in the list of window properties */ /* structure returned in the list of window properties */
typedef struct typedef struct
@ -273,7 +270,7 @@ typedef union
{ {
enum apc_type type; /* APC_TIMER */ enum apc_type type; /* APC_TIMER */
void (__stdcall *func)(void*, unsigned int, unsigned int); void (__stdcall *func)(void*, unsigned int, unsigned int);
abs_time_t time; /* absolute time of expiration */ timeout_t time; /* absolute time of expiration */
void *arg; /* user argument */ void *arg; /* user argument */
} timer; } timer;
struct struct
@ -525,7 +522,7 @@ typedef union
process_id_t pid; /* process id of the new thread's process */ process_id_t pid; /* process id of the new thread's process */
thread_id_t tid; /* thread id of the new thread */ thread_id_t tid; /* thread id of the new thread */
data_size_t info_size; /* total size of startup info */ data_size_t info_size; /* total size of startup info */
abs_time_t server_start; /* server start time */ timeout_t server_start; /* server start time */
int version; /* protocol version */ int version; /* protocol version */
@END @END
@ -559,8 +556,8 @@ typedef union
int priority; /* priority class */ int priority; /* priority class */
int affinity; /* process affinity mask */ int affinity; /* process affinity mask */
void* peb; /* PEB address in process address space */ void* peb; /* PEB address in process address space */
abs_time_t start_time; /* process start time */ timeout_t start_time; /* process start time */
abs_time_t end_time; /* process end time */ timeout_t end_time; /* process end time */
@END @END
@ -586,8 +583,8 @@ typedef union
int exit_code; /* thread exit code */ int exit_code; /* thread exit code */
int priority; /* thread priority level */ int priority; /* thread priority level */
int affinity; /* thread affinity mask */ int affinity; /* thread affinity mask */
abs_time_t creation_time; /* thread creation time */ timeout_t creation_time; /* thread creation time */
abs_time_t exit_time; /* thread exit time */ timeout_t exit_time; /* thread exit time */
int last; /* last thread in process */ int last; /* last thread in process */
@END @END
@ -739,13 +736,14 @@ typedef union
int flags; /* wait flags (see below) */ int flags; /* wait flags (see below) */
void* cookie; /* magic cookie to return to client */ void* cookie; /* magic cookie to return to client */
obj_handle_t signal; /* object to signal (0 if none) */ obj_handle_t signal; /* object to signal (0 if none) */
abs_time_t timeout; /* absolute timeout */ timeout_t timeout; /* timeout */
VARARG(handles,handles); /* handles to select on */ VARARG(handles,handles); /* handles to select on */
@REPLY
timeout_t timeout; /* timeout converted to absolute */
@END @END
#define SELECT_ALL 1 #define SELECT_ALL 1
#define SELECT_ALERTABLE 2 #define SELECT_ALERTABLE 2
#define SELECT_INTERRUPTIBLE 4 #define SELECT_INTERRUPTIBLE 4
#define SELECT_TIMEOUT 8
/* Create an event */ /* Create an event */
@ -1647,7 +1645,7 @@ enum char_info_mode
/* Set a waitable timer */ /* Set a waitable timer */
@REQ(set_timer) @REQ(set_timer)
obj_handle_t handle; /* handle to the timer */ obj_handle_t handle; /* handle to the timer */
abs_time_t expire; /* next expiration absolute time */ timeout_t expire; /* next expiration absolute time */
int period; /* timer period in ms */ int period; /* timer period in ms */
void* callback; /* callback function */ void* callback; /* callback function */
void* arg; /* callback argument */ void* arg; /* callback argument */
@ -1666,7 +1664,7 @@ enum char_info_mode
@REQ(get_timer_info) @REQ(get_timer_info)
obj_handle_t handle; /* handle to the timer */ obj_handle_t handle; /* handle to the timer */
@REPLY @REPLY
abs_time_t when; /* absolute time when the timer next expires */ timeout_t when; /* absolute time when the timer next expires */
int signaled; /* is the timer signaled? */ int signaled; /* is the timer signaled? */
@END @END
@ -1814,7 +1812,7 @@ enum char_info_mode
unsigned int msg; /* message code */ unsigned int msg; /* message code */
unsigned long wparam; /* parameters */ unsigned long wparam; /* parameters */
unsigned long lparam; /* parameters */ unsigned long lparam; /* parameters */
int timeout; /* timeout for reply */ timeout_t timeout; /* timeout for reply */
VARARG(data,message_data); /* message data for sent messages */ VARARG(data,message_data); /* message data for sent messages */
@END @END
@ -1987,7 +1985,7 @@ enum message_type
unsigned int maxinstances; unsigned int maxinstances;
unsigned int outsize; unsigned int outsize;
unsigned int insize; unsigned int insize;
unsigned int timeout; timeout_t timeout;
VARARG(name,unicode_str); /* pipe name */ VARARG(name,unicode_str); /* pipe name */
@REPLY @REPLY
obj_handle_t handle; /* handle to the pipe */ obj_handle_t handle; /* handle to the pipe */
@ -2010,7 +2008,7 @@ enum message_type
@REQ(wait_named_pipe) @REQ(wait_named_pipe)
obj_handle_t handle; obj_handle_t handle;
async_data_t async; /* async I/O parameters */ async_data_t async; /* async I/O parameters */
unsigned int timeout; timeout_t timeout;
VARARG(name,unicode_str); /* pipe name */ VARARG(name,unicode_str); /* pipe name */
@END @END
@ -2774,7 +2772,7 @@ enum message_type
unsigned int attributes; /* object attributes */ unsigned int attributes; /* object attributes */
obj_handle_t rootdir; /* root directory */ obj_handle_t rootdir; /* root directory */
unsigned int max_msgsize; unsigned int max_msgsize;
int read_timeout; timeout_t read_timeout;
VARARG(name,unicode_str); /* mailslot name */ VARARG(name,unicode_str); /* mailslot name */
@REPLY @REPLY
obj_handle_t handle; /* handle to the mailslot */ obj_handle_t handle; /* handle to the mailslot */
@ -2785,10 +2783,10 @@ enum message_type
@REQ(set_mailslot_info) @REQ(set_mailslot_info)
obj_handle_t handle; /* handle to the mailslot */ obj_handle_t handle; /* handle to the mailslot */
unsigned int flags; unsigned int flags;
int read_timeout; timeout_t read_timeout;
@REPLY @REPLY
unsigned int max_msgsize; unsigned int max_msgsize;
int read_timeout; timeout_t read_timeout;
@END @END
#define MAILSLOT_SET_READ_TIMEOUT 1 #define MAILSLOT_SET_READ_TIMEOUT 1

View file

@ -85,7 +85,7 @@ struct message
struct timer struct timer
{ {
struct list entry; /* entry in timer list */ struct list entry; /* entry in timer list */
struct timeval when; /* next expiration */ timeout_t when; /* next expiration */
unsigned int rate; /* timer rate in ms */ unsigned int rate; /* timer rate in ms */
user_handle_t win; /* window handle */ user_handle_t win; /* window handle */
unsigned int msg; /* message to post */ unsigned int msg; /* message to post */
@ -131,7 +131,7 @@ struct msg_queue
struct timeout_user *timeout; /* timeout for next timer to expire */ struct timeout_user *timeout; /* timeout for next timer to expire */
struct thread_input *input; /* thread input descriptor */ struct thread_input *input; /* thread input descriptor */
struct hook_table *hooks; /* hook table */ struct hook_table *hooks; /* hook table */
struct timeval last_get_msg; /* time of last get message call */ timeout_t last_get_msg; /* time of last get message call */
}; };
static void msg_queue_dump( struct object *obj, int verbose ); static void msg_queue_dump( struct object *obj, int verbose );
@ -536,7 +536,7 @@ static void result_timeout( void *private )
/* allocate and fill a message result structure */ /* allocate and fill a message result structure */
static struct message_result *alloc_message_result( struct msg_queue *send_queue, static struct message_result *alloc_message_result( struct msg_queue *send_queue,
struct msg_queue *recv_queue, struct msg_queue *recv_queue,
struct message *msg, int timeout ) struct message *msg, timeout_t timeout )
{ {
struct message_result *result = mem_alloc( sizeof(*result) ); struct message_result *result = mem_alloc( sizeof(*result) );
if (result) if (result)
@ -583,12 +583,8 @@ static struct message_result *alloc_message_result( struct msg_queue *send_queue
list_add_head( &send_queue->send_result, &result->sender_entry ); list_add_head( &send_queue->send_result, &result->sender_entry );
} }
if (timeout) if (timeout != TIMEOUT_INFINITE)
{ result->timeout = add_timeout_user( timeout, result_timeout, result );
struct timeval when = current_time;
add_timeout( &when, timeout );
result->timeout = add_timeout_user( &when, result_timeout, result );
}
} }
return result; return result;
} }
@ -766,7 +762,7 @@ static int is_queue_hung( struct msg_queue *queue )
{ {
struct wait_queue_entry *entry; struct wait_queue_entry *entry;
if (current_time.tv_sec - queue->last_get_msg.tv_sec <= 5) if (current_time - queue->last_get_msg <= 5 * TICKS_PER_SEC)
return 0; /* less than 5 seconds since last get message -> not hung */ return 0; /* less than 5 seconds since last get message -> not hung */
LIST_FOR_EACH_ENTRY( entry, &queue->obj.wait_queue, struct wait_queue_entry, entry ) LIST_FOR_EACH_ENTRY( entry, &queue->obj.wait_queue, struct wait_queue_entry, entry )
@ -997,7 +993,7 @@ static void set_next_timer( struct msg_queue *queue )
if ((ptr = list_head( &queue->pending_timers ))) if ((ptr = list_head( &queue->pending_timers )))
{ {
struct timer *timer = LIST_ENTRY( ptr, struct timer, entry ); struct timer *timer = LIST_ENTRY( ptr, struct timer, entry );
queue->timeout = add_timeout_user( &timer->when, timer_callback, queue ); queue->timeout = add_timeout_user( timer->when, timer_callback, queue );
} }
/* set/clear QS_TIMER bit */ /* set/clear QS_TIMER bit */
if (list_empty( &queue->expired_timers )) if (list_empty( &queue->expired_timers ))
@ -1049,7 +1045,7 @@ static void link_timer( struct msg_queue *queue, struct timer *timer )
for (ptr = queue->pending_timers.next; ptr != &queue->pending_timers; ptr = ptr->next) for (ptr = queue->pending_timers.next; ptr != &queue->pending_timers; ptr = ptr->next)
{ {
struct timer *t = LIST_ENTRY( ptr, struct timer, entry ); struct timer *t = LIST_ENTRY( ptr, struct timer, entry );
if (!time_before( &t->when, &timer->when )) break; if (t->when >= timer->when) break;
} }
list_add_before( ptr, &timer->entry ); list_add_before( ptr, &timer->entry );
} }
@ -1066,7 +1062,7 @@ static void free_timer( struct msg_queue *queue, struct timer *timer )
static void restart_timer( struct msg_queue *queue, struct timer *timer ) static void restart_timer( struct msg_queue *queue, struct timer *timer )
{ {
list_remove( &timer->entry ); list_remove( &timer->entry );
while (!time_before( &current_time, &timer->when )) add_timeout( &timer->when, timer->rate ); while (timer->when <= current_time) timer->when += (timeout_t)timer->rate * 10000;
link_timer( queue, timer ); link_timer( queue, timer );
set_next_timer( queue ); set_next_timer( queue );
} }
@ -1098,8 +1094,7 @@ static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
if (timer) if (timer)
{ {
timer->rate = max( rate, 1 ); timer->rate = max( rate, 1 );
timer->when = current_time; timer->when = current_time + (timeout_t)timer->rate * 10000;
add_timeout( &timer->when, rate );
link_timer( queue, timer ); link_timer( queue, timer );
/* check if we replaced the next timer */ /* check if we replaced the next timer */
if (list_head( &queue->pending_timers ) == &timer->entry) set_next_timer( queue ); if (list_head( &queue->pending_timers ) == &timer->entry) set_next_timer( queue );

View file

@ -103,7 +103,7 @@ struct key_value
/* the root of the registry tree */ /* the root of the registry tree */
static struct key *root_key; static struct key *root_key;
static const int save_period = 30000; /* delay between periodic saves (in ms) */ static const timeout_t save_period = 30 * -TICKS_PER_SEC; /* delay between periodic saves */
static struct timeout_user *save_timeout_user; /* saving timer */ static struct timeout_user *save_timeout_user; /* saving timer */
static void set_periodic_save_timer(void); static void set_periodic_save_timer(void);
@ -1683,11 +1683,8 @@ static void periodic_save( void *arg )
/* start the periodic save timer */ /* start the periodic save timer */
static void set_periodic_save_timer(void) static void set_periodic_save_timer(void)
{ {
struct timeval next = current_time;
add_timeout( &next, save_period );
if (save_timeout_user) remove_timeout_user( save_timeout_user ); if (save_timeout_user) remove_timeout_user( save_timeout_user );
save_timeout_user = add_timeout_user( &next, periodic_save, NULL ); save_timeout_user = add_timeout_user( save_period, periodic_save, NULL );
} }
/* save the modified registry branches to disk */ /* save the modified registry branches to disk */

View file

@ -117,7 +117,7 @@ static const struct fd_ops master_socket_fd_ops =
struct thread *current = NULL; /* thread handling the current request */ struct thread *current = NULL; /* thread handling the current request */
unsigned int global_error = 0; /* global error code for when no thread is current */ unsigned int global_error = 0; /* global error code for when no thread is current */
struct timeval server_start_time = { 0, 0 }; /* server startup time */ timeout_t server_start_time = 0; /* server startup time */
static struct master_socket *master_socket; /* the master socket object */ static struct master_socket *master_socket; /* the master socket object */
static int force_shutdown; static int force_shutdown;
@ -468,8 +468,7 @@ int send_client_fd( struct process *process, int fd, obj_handle_t handle )
/* get current tick count to return to client */ /* get current tick count to return to client */
unsigned int get_tick_count(void) unsigned int get_tick_count(void)
{ {
return ((current_time.tv_sec - server_start_time.tv_sec) * 1000) + return (current_time - server_start_time) / 10000;
((current_time.tv_usec - server_start_time.tv_usec) / 1000);
} }
static void master_socket_dump( struct object *obj, int verbose ) static void master_socket_dump( struct object *obj, int verbose )
@ -801,9 +800,6 @@ void open_master_socket(void)
msghdr.msg_iov = &myiovec; msghdr.msg_iov = &myiovec;
msghdr.msg_iovlen = 1; msghdr.msg_iovlen = 1;
/* init startup time */
gettimeofday( &server_start_time, NULL );
/* init the process tracing mechanism */ /* init the process tracing mechanism */
init_tracing_mechanism(); init_tracing_mechanism();
} }
@ -828,15 +824,12 @@ static void close_socket_timeout( void *arg )
/* close the master socket and stop waiting for new clients */ /* close the master socket and stop waiting for new clients */
void close_master_socket(void) void close_master_socket(void)
{ {
if (master_socket_timeout == -1) return; /* just keep running forever */ if (master_socket_timeout == TIMEOUT_INFINITE) return; /* just keep running forever */
if (master_socket_timeout) if (master_socket_timeout)
{ master_socket->timeout = add_timeout_user( master_socket_timeout, close_socket_timeout, NULL );
struct timeval when = current_time; else
add_timeout( &when, master_socket_timeout * 1000 ); close_socket_timeout( NULL ); /* close it right away */
master_socket->timeout = add_timeout_user( &when, close_socket_timeout, NULL );
}
else close_socket_timeout( NULL ); /* close it right away */
} }
/* forced shutdown, used for wineserver -k */ /* forced shutdown, used for wineserver -k */

View file

@ -180,7 +180,7 @@ static enum server_fd_type serial_get_fd_type( struct fd *fd )
static void serial_queue_async( struct fd *fd, const async_data_t *data, int type, int count ) static void serial_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
{ {
struct serial *serial = get_fd_user( fd ); struct serial *serial = get_fd_user( fd );
int timeout = 0; timeout_t timeout = 0;
struct async *async; struct async *async;
assert(serial->obj.ops == &serial_ops); assert(serial->obj.ops == &serial_ops);
@ -188,21 +188,16 @@ static void serial_queue_async( struct fd *fd, const async_data_t *data, int typ
switch (type) switch (type)
{ {
case ASYNC_TYPE_READ: case ASYNC_TYPE_READ:
timeout = serial->readconst + serial->readmult*count; timeout = serial->readconst + (timeout_t)serial->readmult*count;
break; break;
case ASYNC_TYPE_WRITE: case ASYNC_TYPE_WRITE:
timeout = serial->writeconst + serial->writemult*count; timeout = serial->writeconst + (timeout_t)serial->writemult*count;
break; break;
} }
if ((async = fd_queue_async( fd, data, type, count ))) if ((async = fd_queue_async( fd, data, type, count )))
{ {
if (timeout) if (timeout) async_set_timeout( async, timeout * -10000, STATUS_TIMEOUT );
{
struct timeval when = current_time;
add_timeout( &when, timeout );
async_set_timeout( async, &when, STATUS_TIMEOUT );
}
release_object( async ); release_object( async );
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
} }

View file

@ -59,7 +59,7 @@ struct thread_wait
int count; /* count of objects */ int count; /* count of objects */
int flags; int flags;
void *cookie; /* magic cookie to return to client */ void *cookie; /* magic cookie to return to client */
struct timeval timeout; timeout_t timeout;
struct timeout_user *user; struct timeout_user *user;
struct wait_queue_entry queues[1]; struct wait_queue_entry queues[1];
}; };
@ -171,7 +171,7 @@ static inline void init_thread_structure( struct thread *thread )
thread->token = NULL; thread->token = NULL;
thread->creation_time = current_time; thread->creation_time = current_time;
thread->exit_time.tv_sec = thread->exit_time.tv_usec = 0; thread->exit_time = 0;
list_init( &thread->mutex_list ); list_init( &thread->mutex_list );
list_init( &thread->system_apc ); list_init( &thread->system_apc );
@ -461,24 +461,20 @@ static void end_wait( struct thread *thread )
} }
/* build the thread wait structure */ /* build the thread wait structure */
static int wait_on( int count, struct object *objects[], int flags, const abs_time_t *timeout ) static int wait_on( unsigned int count, struct object *objects[], int flags, timeout_t timeout )
{ {
struct thread_wait *wait; struct thread_wait *wait;
struct wait_queue_entry *entry; struct wait_queue_entry *entry;
int i; unsigned int i;
if (!(wait = mem_alloc( sizeof(*wait) + (count-1) * sizeof(*entry) ))) return 0; if (!(wait = mem_alloc( FIELD_OFFSET(struct thread_wait, queues[count]) ))) return 0;
wait->next = current->wait; wait->next = current->wait;
wait->thread = current; wait->thread = current;
wait->count = count; wait->count = count;
wait->flags = flags; wait->flags = flags;
wait->user = NULL; wait->user = NULL;
wait->timeout = timeout;
current->wait = wait; current->wait = wait;
if (flags & SELECT_TIMEOUT)
{
wait->timeout.tv_sec = timeout->sec;
wait->timeout.tv_usec = timeout->usec;
}
for (i = 0, entry = wait->queues; i < count; i++, entry++) for (i = 0, entry = wait->queues; i < count; i++, entry++)
{ {
@ -541,10 +537,7 @@ static int check_wait( struct thread *thread )
other_checks: other_checks:
if ((wait->flags & SELECT_INTERRUPTIBLE) && !list_empty(&thread->system_apc)) return STATUS_USER_APC; if ((wait->flags & SELECT_INTERRUPTIBLE) && !list_empty(&thread->system_apc)) return STATUS_USER_APC;
if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC; if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC;
if (wait->flags & SELECT_TIMEOUT) if (wait->timeout <= current_time) return STATUS_TIMEOUT;
{
if (!time_before( &current_time, &wait->timeout )) return STATUS_TIMEOUT;
}
return -1; return -1;
} }
@ -623,16 +616,19 @@ static int signal_object( obj_handle_t handle )
} }
/* select on a list of handles */ /* select on a list of handles */
static void select_on( int count, void *cookie, const obj_handle_t *handles, static timeout_t select_on( unsigned int count, void *cookie, const obj_handle_t *handles,
int flags, const abs_time_t *timeout, obj_handle_t signal_obj ) int flags, timeout_t timeout, obj_handle_t signal_obj )
{ {
int ret, i; int ret;
unsigned int i;
struct object *objects[MAXIMUM_WAIT_OBJECTS]; struct object *objects[MAXIMUM_WAIT_OBJECTS];
if ((count < 0) || (count > MAXIMUM_WAIT_OBJECTS)) if (timeout <= 0) timeout = current_time - timeout;
if (count > MAXIMUM_WAIT_OBJECTS)
{ {
set_error( STATUS_INVALID_PARAMETER ); set_error( STATUS_INVALID_PARAMETER );
return; return 0;
} }
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
@ -664,9 +660,9 @@ static void select_on( int count, void *cookie, const obj_handle_t *handles,
} }
/* now we need to wait */ /* now we need to wait */
if (flags & SELECT_TIMEOUT) if (current->wait->timeout != TIMEOUT_INFINITE)
{ {
if (!(current->wait->user = add_timeout_user( &current->wait->timeout, if (!(current->wait->user = add_timeout_user( current->wait->timeout,
thread_timeout, current->wait ))) thread_timeout, current->wait )))
{ {
end_wait( current ); end_wait( current );
@ -677,7 +673,8 @@ static void select_on( int count, void *cookie, const obj_handle_t *handles,
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
done: done:
while (--i >= 0) release_object( objects[i] ); while (i > 0) release_object( objects[--i] );
return timeout;
} }
/* attempt to wake threads sleeping on the object wait queue */ /* attempt to wake threads sleeping on the object wait queue */
@ -1035,8 +1032,7 @@ DECL_HANDLER(init_thread)
reply->pid = get_process_id( process ); reply->pid = get_process_id( process );
reply->tid = get_thread_id( current ); reply->tid = get_thread_id( current );
reply->version = SERVER_PROTOCOL_VERSION; reply->version = SERVER_PROTOCOL_VERSION;
reply->server_start.sec = server_start_time.tv_sec; reply->server_start = server_start_time;
reply->server_start.usec = server_start_time.tv_usec;
return; return;
error: error:
@ -1094,10 +1090,8 @@ DECL_HANDLER(get_thread_info)
reply->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STATUS_PENDING; reply->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STATUS_PENDING;
reply->priority = thread->priority; reply->priority = thread->priority;
reply->affinity = thread->affinity; reply->affinity = thread->affinity;
reply->creation_time.sec = thread->creation_time.tv_sec; reply->creation_time = thread->creation_time;
reply->creation_time.usec = thread->creation_time.tv_usec; reply->exit_time = thread->exit_time;
reply->exit_time.sec = thread->exit_time.tv_sec;
reply->exit_time.usec = thread->exit_time.tv_usec;
reply->last = thread->process->running_threads == 1; reply->last = thread->process->running_threads == 1;
release_object( thread ); release_object( thread );
@ -1145,8 +1139,8 @@ DECL_HANDLER(resume_thread)
/* select on a handle list */ /* select on a handle list */
DECL_HANDLER(select) DECL_HANDLER(select)
{ {
int count = get_req_data_size() / sizeof(obj_handle_t); unsigned int count = get_req_data_size() / sizeof(obj_handle_t);
select_on( count, req->cookie, get_req_data(), req->flags, &req->timeout, req->signal ); reply->timeout = select_on( count, req->cookie, get_req_data(), req->flags, req->timeout, req->signal );
} }
/* queue an APC for a thread or process */ /* queue an APC for a thread or process */

View file

@ -84,8 +84,8 @@ struct thread
int suspend; /* suspend count */ int suspend; /* suspend count */
obj_handle_t desktop; /* desktop handle */ obj_handle_t desktop; /* desktop handle */
int desktop_users; /* number of objects using the thread desktop */ int desktop_users; /* number of objects using the thread desktop */
struct timeval creation_time; /* Thread creation time */ timeout_t creation_time; /* Thread creation time */
struct timeval exit_time; /* Thread exit time */ timeout_t exit_time; /* Thread exit time */
struct token *token; /* security token associated with this thread */ struct token *token; /* security token associated with this thread */
}; };

View file

@ -42,8 +42,8 @@ struct timer
struct object obj; /* object header */ struct object obj; /* object header */
int manual; /* manual reset */ int manual; /* manual reset */
int signaled; /* current signaled state */ int signaled; /* current signaled state */
int period; /* timer period in ms */ unsigned int period; /* timer period in ms */
struct timeval when; /* next expiration */ timeout_t when; /* next expiration */
struct timeout_user *timeout; /* timeout user */ struct timeout_user *timeout; /* timeout user */
struct thread *thread; /* thread that set the APC function */ struct thread *thread; /* thread that set the APC function */
void *callback; /* callback APC function */ void *callback; /* callback APC function */
@ -85,13 +85,12 @@ static struct timer *create_timer( struct directory *root, const struct unicode_
if (get_error() != STATUS_OBJECT_NAME_EXISTS) if (get_error() != STATUS_OBJECT_NAME_EXISTS)
{ {
/* initialize it if it didn't already exist */ /* initialize it if it didn't already exist */
timer->manual = manual; timer->manual = manual;
timer->signaled = 0; timer->signaled = 0;
timer->when.tv_sec = 0; timer->when = 0;
timer->when.tv_usec = 0; timer->period = 0;
timer->period = 0; timer->timeout = NULL;
timer->timeout = NULL; timer->thread = NULL;
timer->thread = NULL;
} }
} }
return timer; return timer;
@ -110,11 +109,10 @@ static void timer_callback( void *private )
memset( &data, 0, sizeof(data) ); memset( &data, 0, sizeof(data) );
if (timer->callback) if (timer->callback)
{ {
data.type = APC_TIMER; data.type = APC_TIMER;
data.timer.func = timer->callback; data.timer.func = timer->callback;
data.timer.time.sec = timer->when.tv_sec; data.timer.time = timer->when;
data.timer.time.usec = timer->when.tv_usec; data.timer.arg = timer->arg;
data.timer.arg = timer->arg;
} }
else data.type = APC_NONE; /* wake up only */ else data.type = APC_NONE; /* wake up only */
@ -127,8 +125,8 @@ static void timer_callback( void *private )
if (timer->period) /* schedule the next expiration */ if (timer->period) /* schedule the next expiration */
{ {
add_timeout( &timer->when, timer->period ); timer->when += (timeout_t)timer->period * 10000;
timer->timeout = add_timeout_user( &timer->when, timer_callback, timer ); timer->timeout = add_timeout_user( timer->when, timer_callback, timer );
} }
else timer->timeout = NULL; else timer->timeout = NULL;
@ -157,7 +155,7 @@ static int cancel_timer( struct timer *timer )
} }
/* set the timer expiration and period */ /* set the timer expiration and period */
static int set_timer( struct timer *timer, const abs_time_t *expire, int period, static int set_timer( struct timer *timer, timeout_t expire, unsigned int period,
void *callback, void *arg ) void *callback, void *arg )
{ {
int signaled = cancel_timer( timer ); int signaled = cancel_timer( timer );
@ -166,22 +164,12 @@ static int set_timer( struct timer *timer, const abs_time_t *expire, int period,
period = 0; /* period doesn't make any sense for a manual timer */ period = 0; /* period doesn't make any sense for a manual timer */
timer->signaled = 0; timer->signaled = 0;
} }
if (!expire->sec && !expire->usec)
{ timer->period = period;
/* special case: use now + period as first expiration */ timer->callback = callback;
timer->when = current_time; timer->arg = arg;
add_timeout( &timer->when, period );
}
else
{
timer->when.tv_sec = expire->sec;
timer->when.tv_usec = expire->usec;
}
timer->period = period;
timer->callback = callback;
timer->arg = arg;
if (callback) timer->thread = (struct thread *)grab_object( current ); if (callback) timer->thread = (struct thread *)grab_object( current );
timer->timeout = add_timeout_user( &timer->when, timer_callback, timer ); timer->timeout = add_timeout_user( timer->when, timer_callback, timer );
return signaled; return signaled;
} }
@ -189,8 +177,8 @@ static void timer_dump( struct object *obj, int verbose )
{ {
struct timer *timer = (struct timer *)obj; struct timer *timer = (struct timer *)obj;
assert( obj->ops == &timer_ops ); assert( obj->ops == &timer_ops );
fprintf( stderr, "Timer manual=%d when=%ld.%06u period=%d ", fprintf( stderr, "Timer manual=%d when=%s period=%u ",
timer->manual, timer->when.tv_sec, (unsigned int)timer->when.tv_usec, timer->period ); timer->manual, get_timeout_str(timer->when), timer->period );
dump_object_name( &timer->obj ); dump_object_name( &timer->obj );
fputc( '\n', stderr ); fputc( '\n', stderr );
} }
@ -277,7 +265,7 @@ DECL_HANDLER(set_timer)
if ((timer = (struct timer *)get_handle_obj( current->process, req->handle, if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
TIMER_MODIFY_STATE, &timer_ops ))) TIMER_MODIFY_STATE, &timer_ops )))
{ {
reply->signaled = set_timer( timer, &req->expire, req->period, req->callback, req->arg ); reply->signaled = set_timer( timer, req->expire, req->period, req->callback, req->arg );
release_object( timer ); release_object( timer );
} }
} }
@ -303,8 +291,7 @@ DECL_HANDLER(get_timer_info)
if ((timer = (struct timer *)get_handle_obj( current->process, req->handle, if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
TIMER_QUERY_STATE, &timer_ops ))) TIMER_QUERY_STATE, &timer_ops )))
{ {
reply->when.sec = timer->when.tv_sec; reply->when = timer->when;
reply->when.usec = timer->when.tv_usec;
reply->signaled = timer->signaled; reply->signaled = timer->signaled;
release_object( timer ); release_object( timer );
} }

View file

@ -64,25 +64,9 @@ static void dump_uints( const int *ptr, int len )
fputc( '}', stderr ); fputc( '}', stderr );
} }
static void dump_abs_time( const abs_time_t *time ) static void dump_timeout( const timeout_t *time )
{ {
int secs, usecs; fprintf( stderr, get_timeout_str(*time) );
if (!time->sec && !time->usec)
{
fprintf( stderr, "0" );
return;
}
secs = time->sec - current_time.tv_sec;
if ((usecs = time->usec - current_time.tv_usec) < 0)
{
usecs += 1000000;
secs--;
}
if (secs > 0 || (secs == 0 && usecs >= 0))
fprintf( stderr, "%d.%06d (+%d.%06d)", time->sec, time->usec, secs, usecs );
else
fprintf( stderr, "%d.%06d (-%d.%06d)", time->sec, time->usec, abs(secs+1), 1000000-usecs );
} }
static void dump_rectangle( const rectangle_t *rect ) static void dump_rectangle( const rectangle_t *rect )
@ -112,7 +96,7 @@ static void dump_apc_call( const apc_call_t *call )
break; break;
case APC_TIMER: case APC_TIMER:
fprintf( stderr, "APC_TIMER,time=" ); fprintf( stderr, "APC_TIMER,time=" );
dump_abs_time( &call->timer.time ); dump_timeout( &call->timer.time );
fprintf( stderr, ",arg=%p", call->timer.arg ); fprintf( stderr, ",arg=%p", call->timer.arg );
break; break;
case APC_ASYNC_IO: case APC_ASYNC_IO:
@ -862,7 +846,7 @@ static void dump_init_thread_reply( const struct init_thread_reply *req )
fprintf( stderr, " tid=%04x,", req->tid ); fprintf( stderr, " tid=%04x,", req->tid );
fprintf( stderr, " info_size=%u,", req->info_size ); fprintf( stderr, " info_size=%u,", req->info_size );
fprintf( stderr, " server_start=" ); fprintf( stderr, " server_start=" );
dump_abs_time( &req->server_start ); dump_timeout( &req->server_start );
fprintf( stderr, "," ); fprintf( stderr, "," );
fprintf( stderr, " version=%d", req->version ); fprintf( stderr, " version=%d", req->version );
} }
@ -904,10 +888,10 @@ static void dump_get_process_info_reply( const struct get_process_info_reply *re
fprintf( stderr, " affinity=%d,", req->affinity ); fprintf( stderr, " affinity=%d,", req->affinity );
fprintf( stderr, " peb=%p,", req->peb ); fprintf( stderr, " peb=%p,", req->peb );
fprintf( stderr, " start_time=" ); fprintf( stderr, " start_time=" );
dump_abs_time( &req->start_time ); dump_timeout( &req->start_time );
fprintf( stderr, "," ); fprintf( stderr, "," );
fprintf( stderr, " end_time=" ); fprintf( stderr, " end_time=" );
dump_abs_time( &req->end_time ); dump_timeout( &req->end_time );
} }
static void dump_set_process_info_request( const struct set_process_info_request *req ) static void dump_set_process_info_request( const struct set_process_info_request *req )
@ -933,10 +917,10 @@ static void dump_get_thread_info_reply( const struct get_thread_info_reply *req
fprintf( stderr, " priority=%d,", req->priority ); fprintf( stderr, " priority=%d,", req->priority );
fprintf( stderr, " affinity=%d,", req->affinity ); fprintf( stderr, " affinity=%d,", req->affinity );
fprintf( stderr, " creation_time=" ); fprintf( stderr, " creation_time=" );
dump_abs_time( &req->creation_time ); dump_timeout( &req->creation_time );
fprintf( stderr, "," ); fprintf( stderr, "," );
fprintf( stderr, " exit_time=" ); fprintf( stderr, " exit_time=" );
dump_abs_time( &req->exit_time ); dump_timeout( &req->exit_time );
fprintf( stderr, "," ); fprintf( stderr, "," );
fprintf( stderr, " last=%d", req->last ); fprintf( stderr, " last=%d", req->last );
} }
@ -1105,12 +1089,18 @@ static void dump_select_request( const struct select_request *req )
fprintf( stderr, " cookie=%p,", req->cookie ); fprintf( stderr, " cookie=%p,", req->cookie );
fprintf( stderr, " signal=%p,", req->signal ); fprintf( stderr, " signal=%p,", req->signal );
fprintf( stderr, " timeout=" ); fprintf( stderr, " timeout=" );
dump_abs_time( &req->timeout ); dump_timeout( &req->timeout );
fprintf( stderr, "," ); fprintf( stderr, "," );
fprintf( stderr, " handles=" ); fprintf( stderr, " handles=" );
dump_varargs_handles( cur_size ); dump_varargs_handles( cur_size );
} }
static void dump_select_reply( const struct select_reply *req )
{
fprintf( stderr, " timeout=" );
dump_timeout( &req->timeout );
}
static void dump_create_event_request( const struct create_event_request *req ) static void dump_create_event_request( const struct create_event_request *req )
{ {
fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " access=%08x,", req->access );
@ -2056,7 +2046,7 @@ static void dump_set_timer_request( const struct set_timer_request *req )
{ {
fprintf( stderr, " handle=%p,", req->handle ); fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " expire=" ); fprintf( stderr, " expire=" );
dump_abs_time( &req->expire ); dump_timeout( &req->expire );
fprintf( stderr, "," ); fprintf( stderr, "," );
fprintf( stderr, " period=%d,", req->period ); fprintf( stderr, " period=%d,", req->period );
fprintf( stderr, " callback=%p,", req->callback ); fprintf( stderr, " callback=%p,", req->callback );
@ -2086,7 +2076,7 @@ static void dump_get_timer_info_request( const struct get_timer_info_request *re
static void dump_get_timer_info_reply( const struct get_timer_info_reply *req ) static void dump_get_timer_info_reply( const struct get_timer_info_reply *req )
{ {
fprintf( stderr, " when=" ); fprintf( stderr, " when=" );
dump_abs_time( &req->when ); dump_timeout( &req->when );
fprintf( stderr, "," ); fprintf( stderr, "," );
fprintf( stderr, " signaled=%d", req->signaled ); fprintf( stderr, " signaled=%d", req->signaled );
} }
@ -2257,7 +2247,9 @@ static void dump_send_message_request( const struct send_message_request *req )
fprintf( stderr, " msg=%08x,", req->msg ); fprintf( stderr, " msg=%08x,", req->msg );
fprintf( stderr, " wparam=%lx,", req->wparam ); fprintf( stderr, " wparam=%lx,", req->wparam );
fprintf( stderr, " lparam=%lx,", req->lparam ); fprintf( stderr, " lparam=%lx,", req->lparam );
fprintf( stderr, " timeout=%d,", req->timeout ); fprintf( stderr, " timeout=" );
dump_timeout( &req->timeout );
fprintf( stderr, "," );
fprintf( stderr, " data=" ); fprintf( stderr, " data=" );
dump_varargs_message_data( cur_size ); dump_varargs_message_data( cur_size );
} }
@ -2423,7 +2415,9 @@ static void dump_create_named_pipe_request( const struct create_named_pipe_reque
fprintf( stderr, " maxinstances=%08x,", req->maxinstances ); fprintf( stderr, " maxinstances=%08x,", req->maxinstances );
fprintf( stderr, " outsize=%08x,", req->outsize ); fprintf( stderr, " outsize=%08x,", req->outsize );
fprintf( stderr, " insize=%08x,", req->insize ); fprintf( stderr, " insize=%08x,", req->insize );
fprintf( stderr, " timeout=%08x,", req->timeout ); fprintf( stderr, " timeout=" );
dump_timeout( &req->timeout );
fprintf( stderr, "," );
fprintf( stderr, " name=" ); fprintf( stderr, " name=" );
dump_varargs_unicode_str( cur_size ); dump_varargs_unicode_str( cur_size );
} }
@ -2446,7 +2440,9 @@ static void dump_wait_named_pipe_request( const struct wait_named_pipe_request *
fprintf( stderr, " async=" ); fprintf( stderr, " async=" );
dump_async_data( &req->async ); dump_async_data( &req->async );
fprintf( stderr, "," ); fprintf( stderr, "," );
fprintf( stderr, " timeout=%08x,", req->timeout ); fprintf( stderr, " timeout=" );
dump_timeout( &req->timeout );
fprintf( stderr, "," );
fprintf( stderr, " name=" ); fprintf( stderr, " name=" );
dump_varargs_unicode_str( cur_size ); dump_varargs_unicode_str( cur_size );
} }
@ -3336,7 +3332,9 @@ static void dump_create_mailslot_request( const struct create_mailslot_request *
fprintf( stderr, " attributes=%08x,", req->attributes ); fprintf( stderr, " attributes=%08x,", req->attributes );
fprintf( stderr, " rootdir=%p,", req->rootdir ); fprintf( stderr, " rootdir=%p,", req->rootdir );
fprintf( stderr, " max_msgsize=%08x,", req->max_msgsize ); fprintf( stderr, " max_msgsize=%08x,", req->max_msgsize );
fprintf( stderr, " read_timeout=%d,", req->read_timeout ); fprintf( stderr, " read_timeout=" );
dump_timeout( &req->read_timeout );
fprintf( stderr, "," );
fprintf( stderr, " name=" ); fprintf( stderr, " name=" );
dump_varargs_unicode_str( cur_size ); dump_varargs_unicode_str( cur_size );
} }
@ -3350,13 +3348,15 @@ static void dump_set_mailslot_info_request( const struct set_mailslot_info_reque
{ {
fprintf( stderr, " handle=%p,", req->handle ); fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " flags=%08x,", req->flags ); fprintf( stderr, " flags=%08x,", req->flags );
fprintf( stderr, " read_timeout=%d", req->read_timeout ); fprintf( stderr, " read_timeout=" );
dump_timeout( &req->read_timeout );
} }
static void dump_set_mailslot_info_reply( const struct set_mailslot_info_reply *req ) static void dump_set_mailslot_info_reply( const struct set_mailslot_info_reply *req )
{ {
fprintf( stderr, " max_msgsize=%08x,", req->max_msgsize ); fprintf( stderr, " max_msgsize=%08x,", req->max_msgsize );
fprintf( stderr, " read_timeout=%d", req->read_timeout ); fprintf( stderr, " read_timeout=" );
dump_timeout( &req->read_timeout );
} }
static void dump_create_directory_request( const struct create_directory_request *req ) static void dump_create_directory_request( const struct create_directory_request *req )
@ -3706,7 +3706,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_dup_handle_reply, (dump_func)dump_dup_handle_reply,
(dump_func)dump_open_process_reply, (dump_func)dump_open_process_reply,
(dump_func)dump_open_thread_reply, (dump_func)dump_open_thread_reply,
(dump_func)0, (dump_func)dump_select_reply,
(dump_func)dump_create_event_reply, (dump_func)dump_create_event_reply,
(dump_func)0, (dump_func)0,
(dump_func)dump_open_event_reply, (dump_func)dump_open_event_reply,

View file

@ -363,10 +363,8 @@ void close_process_desktop( struct process *process )
/* if we have one remaining user, it has to be the manager of the desktop window */ /* if we have one remaining user, it has to be the manager of the desktop window */
if (desktop->users == 1 && get_top_window_owner( desktop )) if (desktop->users == 1 && get_top_window_owner( desktop ))
{ {
struct timeval when = current_time;
add_timeout( &when, 1000 );
assert( !desktop->close_timeout ); assert( !desktop->close_timeout );
desktop->close_timeout = add_timeout_user( &when, close_desktop_timeout, desktop ); desktop->close_timeout = add_timeout_user( -TICKS_PER_SEC, close_desktop_timeout, desktop );
} }
release_object( desktop ); release_object( desktop );
} }

View file

@ -39,7 +39,7 @@ my %formats =
"user_handle_t" => "%p", "user_handle_t" => "%p",
"process_id_t" => "%04x", "process_id_t" => "%04x",
"thread_id_t" => "%04x", "thread_id_t" => "%04x",
"abs_time_t" => "&dump_abs_time", "timeout_t" => "&dump_timeout",
"rectangle_t" => "&dump_rectangle", "rectangle_t" => "&dump_rectangle",
"char_info_t" => "&dump_char_info", "char_info_t" => "&dump_char_info",
"apc_call_t" => "&dump_apc_call", "apc_call_t" => "&dump_apc_call",