Commit aaf477f2 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent 31368dec
......@@ -1301,7 +1301,10 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
}
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);
memcpy(pipe_wait->Name, nt_name.Buffer + sizeof(leadin)/sizeof(WCHAR),
pipe_wait->NameLength);
......@@ -1771,8 +1774,12 @@ BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
if( lpMessageCount )
*lpMessageCount = info.MessagesAvailable;
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;
}
......@@ -1798,7 +1805,10 @@ BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD 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,
FileMailslotSetInformation );
if( status != STATUS_SUCCESS )
......
......@@ -430,7 +430,9 @@ static NTSTATUS get_io_timeouts( HANDLE handle, enum server_fd_type type, ULONG
{
req->handle = handle;
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;
}
......@@ -1113,8 +1115,7 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
SERVER_START_REQ(wait_named_pipe)
{
req->handle = handle;
req->timeout = buff->TimeoutSpecified ? buff->Timeout.QuadPart / -10000L
: NMPWAIT_USE_DEFAULT_WAIT;
req->timeout = buff->TimeoutSpecified ? buff->Timeout.QuadPart : 0;
req->async.callback = pipe_completion_wait;
req->async.iosb = io;
req->async.arg = NULL;
......@@ -1467,7 +1468,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
info->MailslotQuota = 0;
info->NextMessageSize = 0;
info->MessagesAvailable = 0;
info->ReadTimeout.QuadPart = reply->read_timeout * -10000;
info->ReadTimeout.QuadPart = reply->read_timeout;
}
}
SERVER_END_REQ;
......@@ -1660,7 +1661,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
{
req->handle = handle;
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 );
}
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,
outbound_quota, timeout);
/* assume we only get relative timeout, and storable in a DWORD as ms */
if (timeout->QuadPart > 0 || (timeout->QuadPart / -10000) >> 32)
/* assume we only get relative timeout */
if (timeout->QuadPart > 0)
FIXME("Wrong time %s\n", wine_dbgstr_longlong(timeout->QuadPart));
SERVER_START_REQ( create_named_pipe )
......@@ -2203,7 +2204,7 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
req->maxinstances = max_inst;
req->outsize = outbound_quota;
req->insize = inbound_quota;
req->timeout = timeout->QuadPart / -10000;
req->timeout = timeout->QuadPart;
wine_server_add_data( req, attr->ObjectName->Buffer,
attr->ObjectName->Length );
status = wine_server_call( req );
......@@ -2306,7 +2307,7 @@ NTSTATUS WINAPI NtCreateMailslotFile(PHANDLE pHandle, ULONG DesiredAccess,
req->attributes = attr->Attributes;
req->rootdir = attr->RootDirectory;
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,
attr->ObjectName->Length );
ret = wine_server_call( req );
......
......@@ -696,7 +696,7 @@ NTSTATUS WINAPI NtQuerySystemInformation(
memset(&sti, 0 , sizeof(sti));
/* liKeSystemTime, liExpTimeZoneBias, uCurrentTimeZoneId */
NTDLL_from_server_abstime( &sti.liKeBootTime, &server_start_time );
sti.liKeBootTime.QuadPart = server_start_time;
if (Length <= sizeof(sti))
{
......
......@@ -40,8 +40,6 @@ extern void set_cpu_context( const CONTEXT *context );
extern LPCSTR debugstr_us( const UNICODE_STRING *str );
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_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags,
const LARGE_INTEGER *timeout, HANDLE signal_object );
......@@ -56,7 +54,7 @@ extern void virtual_init(void);
extern void virtual_init_threading(void);
/* server support */
extern abs_time_t server_start_time;
extern timeout_t server_start_time;
extern void server_init_process(void);
extern NTSTATUS server_init_process_done(void);
extern size_t server_init_thread( int unix_pid, int unix_tid, void *entry_point );
......
......@@ -236,8 +236,8 @@ NTSTATUS WINAPI NtQueryInformationProcess(
req->handle = ProcessHandle;
if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
{
NTDLL_from_server_abstime(&pti.CreateTime, &reply->start_time);
NTDLL_from_server_abstime(&pti.ExitTime, &reply->end_time);
pti.CreateTime.QuadPart = reply->start_time;
pti.ExitTime.QuadPart = reply->end_time;
}
}
SERVER_END_REQ;
......
......@@ -85,7 +85,7 @@ struct cmsg_fd
};
#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;
......
......@@ -478,16 +478,9 @@ NTSTATUS WINAPI NtSetTimer(IN HANDLE handle,
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->period = period;
req->expire = when->QuadPart;
req->callback = callback;
req->arg = callback_arg;
status = wine_server_call( req );
......@@ -564,7 +557,7 @@ NTSTATUS WINAPI NtQueryTimer(
status = wine_server_call(req);
/* 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;
}
SERVER_END_REQ;
......@@ -670,15 +663,9 @@ static BOOL invoke_apc( const apc_call_t *call, apc_result_t *result )
user_apc = TRUE;
break;
case APC_TIMER:
{
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 );
call->timer.func( call->timer.arg, (DWORD)call->timer.time, (DWORD)(call->timer.time >> 32) );
user_apc = TRUE;
break;
}
case APC_ASYNC_IO:
result->type = call->type;
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;
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 (;;)
{
SERVER_START_REQ( select )
......@@ -909,6 +894,7 @@ NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UIN
req->timeout = abs_timeout;
wine_server_add_data( req, handles, count * sizeof(HANDLE) );
ret = wine_server_call( req );
abs_timeout = reply->timeout;
}
SERVER_END_REQ;
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 );
}
if (!timeout) /* sleep forever */
if (!timeout || timeout->QuadPart == TIMEOUT_INFINITE) /* sleep forever */
{
for (;;) select( 0, NULL, NULL, NULL, NULL );
}
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 */
NtYieldExecution();
if (!when) return STATUS_SUCCESS;
for (;;)
{
struct timeval tv;
gettimeofday( &tv, 0 );
tv.tv_sec = when.sec - tv.tv_sec;
if ((tv.tv_usec = when.usec - tv.tv_usec) < 0)
{
tv.tv_usec += 1000000;
tv.tv_sec--;
}
/* if our yield already passed enough time, we're done */
if (tv.tv_sec < 0) break;
NtQuerySystemTime( &now );
diff = (when - now.QuadPart + 9) / 10;
if (diff <= 0) break;
tv.tv_sec = diff / 1000000;
tv.tv_usec = diff % 1000000;
if (select( 0, NULL, NULL, NULL, &tv ) != -1) break;
}
}
......
......@@ -1186,8 +1186,8 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
status = wine_server_call( req );
if (status == STATUS_SUCCESS)
{
NTDLL_from_server_abstime( &kusrt.CreateTime, &reply->creation_time );
NTDLL_from_server_abstime( &kusrt.ExitTime, &reply->exit_time );
kusrt.CreateTime.QuadPart = reply->creation_time;
kusrt.ExitTime.QuadPart = reply->exit_time;
}
}
SERVER_END_REQ;
......
......@@ -446,67 +446,6 @@ static inline int IsLeapYear(int Year)
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.@]
*
......@@ -878,16 +817,15 @@ NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time )
*/
NTSTATUS WINAPI NtQueryPerformanceCounter( PLARGE_INTEGER Counter, PLARGE_INTEGER Frequency )
{
struct timeval now;
LARGE_INTEGER now;
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
* overflow ( will not overflow for 5000 years ) and
* good accuracy ( 105/88 = 1.19318182) */
Counter->QuadPart = (((now.tv_sec - server_start_time.sec) * (ULONGLONG)1000000 +
(now.tv_usec - server_start_time.usec)) * 105) / 88;
* overflow and good accuracy (21/176 = 0.11931818) */
NtQuerySystemTime( &now );
Counter->QuadPart = ((now.QuadPart - server_start_time) * 21) / 176;
if (Frequency) Frequency->QuadPart = 1193182;
return STATUS_SUCCESS;
}
......@@ -899,11 +837,10 @@ NTSTATUS WINAPI NtQueryPerformanceCounter( PLARGE_INTEGER Counter, PLARGE_INTEGE
*/
ULONG WINAPI NtGetTickCount(void)
{
struct timeval current_time;
LARGE_INTEGER now;
gettimeofday(&current_time, NULL);
return (current_time.tv_sec - server_start_time.sec) * 1000 +
(current_time.tv_usec - server_start_time.usec) / 1000;
NtQuerySystemTime( &now );
return (now.QuadPart - server_start_time) / 10000;
}
......
......@@ -1399,7 +1399,7 @@ static BOOL post_dde_message( struct packed_message *data, const struct send_mes
req->msg = info->msg;
req->wparam = info->wparam;
req->lparam = lp;
req->timeout = 0;
req->timeout = TIMEOUT_INFINITE;
for (i = 0; i < data->count; i++)
wine_server_add_data( req, data->data[i], data->size[i] );
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;
message_data_t msg_data;
unsigned int res;
int i, timeout = 0;
int i;
timeout_t timeout = TIMEOUT_INFINITE;
/* Check for INFINITE timeout for compatibility with Win9x,
* 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 &&
info->type != MSG_CALLBACK &&
info->type != MSG_POSTED &&
info->timeout &&
info->timeout != INFINITE)
timeout = info->timeout;
{
/* timeout is signed despite the prototype */
timeout = (timeout_t)max( 0, (int)info->timeout ) * -10000;
}
data.count = 0;
if (info->type == MSG_OTHER_PROCESS)
......
......@@ -133,11 +133,8 @@ struct wake_up_reply
};
typedef struct
{
int sec;
int usec;
} abs_time_t;
typedef __int64 timeout_t;
#define TIMEOUT_INFINITE (((timeout_t)0x7fffffff) << 32 | 0xffffffff)
typedef struct
......@@ -257,7 +254,7 @@ typedef union
{
enum apc_type type;
void (__stdcall *func)(void*, unsigned int, unsigned int);
abs_time_t time;
timeout_t time;
void *arg;
} timer;
struct
......@@ -540,7 +537,7 @@ struct init_thread_reply
process_id_t pid;
thread_id_t tid;
data_size_t info_size;
abs_time_t server_start;
timeout_t server_start;
int version;
};
......@@ -589,8 +586,8 @@ struct get_process_info_reply
int priority;
int affinity;
void* peb;
abs_time_t start_time;
abs_time_t end_time;
timeout_t start_time;
timeout_t end_time;
};
......@@ -627,8 +624,8 @@ struct get_thread_info_reply
int exit_code;
int priority;
int affinity;
abs_time_t creation_time;
abs_time_t exit_time;
timeout_t creation_time;
timeout_t exit_time;
int last;
};
......@@ -856,17 +853,17 @@ struct select_request
int flags;
void* cookie;
obj_handle_t signal;
abs_time_t timeout;
timeout_t timeout;
/* VARARG(handles,handles); */
};
struct select_reply
{
struct reply_header __header;
timeout_t timeout;
};
#define SELECT_ALL 1
#define SELECT_ALERTABLE 2
#define SELECT_INTERRUPTIBLE 4
#define SELECT_TIMEOUT 8
......@@ -2181,7 +2178,7 @@ struct set_timer_request
{
struct request_header __header;
obj_handle_t handle;
abs_time_t expire;
timeout_t expire;
int period;
void* callback;
void* arg;
......@@ -2213,7 +2210,7 @@ struct get_timer_info_request
struct get_timer_info_reply
{
struct reply_header __header;
abs_time_t when;
timeout_t when;
int signaled;
};
......@@ -2442,7 +2439,7 @@ struct send_message_request
unsigned int msg;
unsigned long wparam;
unsigned long lparam;
int timeout;
timeout_t timeout;
/* VARARG(data,message_data); */
};
struct send_message_reply
......@@ -2694,7 +2691,7 @@ struct create_named_pipe_request
unsigned int maxinstances;
unsigned int outsize;
unsigned int insize;
unsigned int timeout;
timeout_t timeout;
/* VARARG(name,unicode_str); */
};
struct create_named_pipe_reply
......@@ -2728,7 +2725,7 @@ struct wait_named_pipe_request
struct request_header __header;
obj_handle_t handle;
async_data_t async;
unsigned int timeout;
timeout_t timeout;
/* VARARG(name,unicode_str); */
};
struct wait_named_pipe_reply
......@@ -3853,7 +3850,7 @@ struct create_mailslot_request
unsigned int attributes;
obj_handle_t rootdir;
unsigned int max_msgsize;
int read_timeout;
timeout_t read_timeout;
/* VARARG(name,unicode_str); */
};
struct create_mailslot_reply
......@@ -3869,13 +3866,13 @@ struct set_mailslot_info_request
struct request_header __header;
obj_handle_t handle;
unsigned int flags;
int read_timeout;
timeout_t read_timeout;
};
struct set_mailslot_info_reply
{
struct reply_header __header;
unsigned int max_msgsize;
int read_timeout;
timeout_t read_timeout;
};
#define MAILSLOT_SET_READ_TIMEOUT 1
......@@ -4660,6 +4657,6 @@ union generic_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 */
......@@ -214,10 +214,10 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
}
/* 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 (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;
async->timeout_status = status;
}
......
......@@ -322,23 +322,30 @@ static file_pos_t max_unix_offset = OFF_T_MAX;
struct timeout_user
{
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 */
void *private; /* callback private data */
};
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 */
struct timeout_user *add_timeout_user( const struct timeval *when, timeout_callback func,
void *private )
struct timeout_user *add_timeout_user( timeout_t when, timeout_callback func, void *private )
{
struct timeout_user *user;
struct list *ptr;
if (!(user = mem_alloc( sizeof(*user) ))) return NULL;
user->when = *when;
user->when = (when > 0) ? when : current_time - when;
user->callback = func;
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 )
{
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 );
return user;
......@@ -360,19 +367,39 @@ void remove_timeout_user( struct timeout_user *user )
free( user );
}
/* add a timeout in milliseconds to an absolute time */
void add_timeout( struct timeval *when, int timeout )
/* return a text description of a timeout for debugging purposes */
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 */
{
secs = -timeout / TICKS_PER_SEC;
nsecs = -timeout % TICKS_PER_SEC;
sprintf( buffer, "+%ld.%07ld", secs, nsecs );
}
else /* absolute */
{
long sec = timeout / 1000;
if ((when->tv_usec += (timeout - 1000*sec) * 1000) >= 1000000)
secs = (timeout - current_time) / TICKS_PER_SEC;
nsecs = (timeout - current_time) % TICKS_PER_SEC;
if (nsecs < 0)
{
when->tv_usec -= 1000000;
when->tv_sec++;
nsecs += TICKS_PER_SEC;
secs--;
}
when->tv_sec += sec;
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 */
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 */
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 );
gettimeofday( &current_time, NULL );
set_current_time();
/* put the events into the pollfd array first, like poll does */
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 );
if (!time_before( &current_time, &timeout->when ))
if (timeout->when <= current_time)
{
list_remove( &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)
{
struct timeout_user *timeout = LIST_ENTRY( ptr, struct timeout_user, entry );
int diff = (timeout->when.tv_sec - current_time.tv_sec) * 1000
+ (timeout->when.tv_usec - current_time.tv_usec + 999) / 1000;
int diff = (timeout->when - current_time + 9999) / 10000;
if (diff < 0) diff = 0;
return diff;
}
......@@ -714,7 +740,8 @@ void main_loop(void)
{
int i, ret, timeout;
gettimeofday( &current_time, NULL );
set_current_time();
server_start_time = current_time;
main_loop_epoll();
/* fall through to normal poll loop */
......@@ -726,7 +753,7 @@ void main_loop(void)
if (!active_users) break; /* last user removed by a timeout */
ret = poll( pollfd, nb_users, timeout );
gettimeofday( &current_time, NULL );
set_current_time();
if (ret > 0)
{
......
......@@ -91,20 +91,15 @@ static inline struct fd *get_obj_fd( struct object *obj ) { return obj->ops->get
/* timeout functions */
struct timeout_user;
extern struct timeval current_time;
extern timeout_t current_time;
#define TICKS_PER_SEC 10000000
typedef void (*timeout_callback)( void *private );
extern struct timeout_user *add_timeout_user( const struct timeval *when,
timeout_callback func, void *private );
extern struct timeout_user *add_timeout_user( timeout_t when, timeout_callback func, void *private );
extern void remove_timeout_user( struct timeout_user *user );
extern void add_timeout( struct timeval *when, int 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)));
}
extern const char *get_timeout_str( timeout_t timeout );
/* 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 struct async *create_async( struct thread *thread, struct async_queue *queue,
const async_data_t *data );
extern void async_set_timeout( struct async *async, const struct timeval *timeout,
unsigned int status );
extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );
extern void async_set_result( struct object *obj, unsigned int status );
extern int async_waiting( struct async_queue *queue );
extern void async_wake_up( struct async_queue *queue, unsigned int status );
......
......@@ -58,7 +58,7 @@ struct mailslot
struct fd *fd;
int write_fd;
unsigned int max_msgsize;
int read_timeout;
timeout_t read_timeout;
struct list writers;
};
......@@ -214,8 +214,8 @@ static void mailslot_dump( struct object *obj, int verbose )
struct mailslot *mailslot = (struct mailslot *) obj;
assert( obj->ops == &mailslot_ops );
fprintf( stderr, "Mailslot max_msgsize=%d read_timeout=%d\n",
mailslot->max_msgsize, mailslot->read_timeout );
fprintf( stderr, "Mailslot max_msgsize=%d read_timeout=%s\n",
mailslot->max_msgsize, get_timeout_str(mailslot->read_timeout) );
}
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 (mailslot->read_timeout != -1)
{
struct timeval when = current_time;
add_timeout( &when, max(1,mailslot->read_timeout) );
async_set_timeout( async, &when, STATUS_IO_TIMEOUT );
}
async_set_timeout( async, mailslot->read_timeout ? mailslot->read_timeout : -1,
STATUS_IO_TIMEOUT );
release_object( async );
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,
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 unicode_str new_name;
......
......@@ -36,8 +36,8 @@
/* command-line options */
int debug_level = 0;
int master_socket_timeout = 3; /* master socket timeout in seconds, default is 3 s */
int foreground = 0;
timeout_t master_socket_timeout = 3 * -TICKS_PER_SEC; /* master socket timeout, default is 3 seconds */
const char *server_argv0;
/* parse-line args */
......@@ -84,8 +84,10 @@ static void parse_args( int argc, char *argv[] )
else ret = kill_lock_owner(-1);
exit( !ret );
case 'p':
if (isdigit(argv[i][2])) master_socket_timeout = atoi( argv[i] + 2 );
else master_socket_timeout = -1;
if (isdigit(argv[i][2]))
master_socket_timeout = (timeout_t)atoi( argv[i] + 2 ) * -TICKS_PER_SEC;
else
master_socket_timeout = TIMEOUT_INFINITE;
break;
case 'v':
fprintf( stderr, "%s\n", PACKAGE_STRING );
......
......@@ -94,8 +94,8 @@ struct named_pipe
unsigned int maxinstances;
unsigned int outsize;
unsigned int insize;
unsigned int timeout;
unsigned int instances;
timeout_t timeout;
struct list servers; /* list of servers using this pipe */
struct async_queue *waiters; /* list of clients waiting to connect */
};
......@@ -512,9 +512,7 @@ static void check_flushed( void *arg )
assert( server->event );
if (pipe_data_remaining( server ))
{
struct timeval tv = current_time;
add_timeout( &tv, 100 );
server->flush_poll = add_timeout_user( &tv, check_flushed, server );
server->flush_poll = add_timeout_user( -TICKS_PER_SEC / 10, check_flushed, server );
}
else
{
......@@ -538,14 +536,11 @@ static void pipe_server_flush( struct fd *fd, struct event **event )
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 */
server->event = create_event( NULL, NULL, 0, 0, 0 );
if (!server->event) return;
add_timeout( &tv, 100 );
server->flush_poll = add_timeout_user( &tv, check_flushed, server );
server->flush_poll = add_timeout_user( -TICKS_PER_SEC / 10, check_flushed, server );
*event = server->event;
}
}
......@@ -901,13 +896,7 @@ DECL_HANDLER(wait_named_pipe)
if ((async = create_async( current, pipe->waiters, &req->async )))
{
if (req->timeout != NMPWAIT_WAIT_FOREVER)
{
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 );
}
async_set_timeout( async, req->timeout ? req->timeout : pipe->timeout, STATUS_TIMEOUT );
release_object( async );
set_error( STATUS_PENDING );
}
......
......@@ -214,11 +214,11 @@ extern void create_mailslot_device( struct directory *root, const struct unicode
/* command-line options */
extern int debug_level;
extern int master_socket_timeout;
extern int foreground;
extern timeout_t master_socket_timeout;
extern const char *server_argv0;
/* server start time used for GetTickCount() */
extern struct timeval server_start_time;
extern timeout_t server_start_time;
#endif /* __WINE_SERVER_OBJECT_H */
......@@ -244,13 +244,9 @@ static void start_sigkill_timer( struct process *process )
{
grab_object( process );
if (process->unix_pid != -1 && process->msg_fd)
{
struct timeval when = current_time;
add_timeout( &when, 1000 );
process->sigkill_timeout = add_timeout_user( &when, process_sigkill, process );
}
else process_died( process );
process->sigkill_timeout = add_timeout_user( -TICKS_PER_SEC, process_sigkill, process );
else
process_died( process );
}
/* 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 );
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 );
if (!(process->id = process->group_id = alloc_ptid( process )))
......@@ -1013,10 +1009,8 @@ DECL_HANDLER(get_process_info)
reply->priority = process->priority;
reply->affinity = process->affinity;
reply->peb = process->peb;
reply->start_time.sec = process->start_time.tv_sec;
reply->start_time.usec = process->start_time.tv_usec;
reply->end_time.sec = process->end_time.tv_sec;
reply->end_time.usec = process->end_time.tv_usec;
reply->start_time = process->start_time;
reply->end_time = process->end_time;
release_object( process );
}
}
......
......@@ -61,8 +61,8 @@ struct process
int unix_pid; /* Unix pid for final SIGKILL */
int exit_code; /* process exit code */
int running_threads; /* number of threads running in this process */
struct timeval start_time; /* absolute time at process start */
struct timeval end_time; /* absolute time at process end */
timeout_t start_time; /* absolute time at process start */
timeout_t end_time; /* absolute time at process end */
int priority; /* priority class */
int affinity; /* process affinity mask */
int suspend; /* global process suspend count */
......
......@@ -148,12 +148,9 @@ struct wake_up_reply
int signaled; /* wait result */
};
/* structure for absolute timeouts */
typedef struct
{
int sec; /* seconds since Unix epoch */
int usec; /* microseconds */
} abs_time_t;
/* NT-style timeout, in 100ns units, negative means relative timeout */
typedef __int64 timeout_t;
#define TIMEOUT_INFINITE (((timeout_t)0x7fffffff) << 32 | 0xffffffff)
/* structure returned in the list of window properties */
typedef struct
......@@ -273,7 +270,7 @@ typedef union
{
enum apc_type type; /* APC_TIMER */
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 */
} timer;
struct
......@@ -525,7 +522,7 @@ typedef union
process_id_t pid; /* process id of the new thread's process */
thread_id_t tid; /* thread id of the new thread */
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 */
@END
......@@ -559,8 +556,8 @@ typedef union
int priority; /* priority class */
int affinity; /* process affinity mask */
void* peb; /* PEB address in process address space */
abs_time_t start_time; /* process start time */
abs_time_t end_time; /* process end time */
timeout_t start_time; /* process start time */
timeout_t end_time; /* process end time */
@END
......@@ -586,8 +583,8 @@ typedef union
int exit_code; /* thread exit code */
int priority; /* thread priority level */
int affinity; /* thread affinity mask */
abs_time_t creation_time; /* thread creation time */
abs_time_t exit_time; /* thread exit time */
timeout_t creation_time; /* thread creation time */
timeout_t exit_time; /* thread exit time */
int last; /* last thread in process */
@END
......@@ -739,13 +736,14 @@ typedef union
int flags; /* wait flags (see below) */
void* cookie; /* magic cookie to return to client */
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 */
@REPLY
timeout_t timeout; /* timeout converted to absolute */
@END
#define SELECT_ALL 1
#define SELECT_ALERTABLE 2
#define SELECT_INTERRUPTIBLE 4
#define SELECT_TIMEOUT 8
/* Create an event */
......@@ -1647,7 +1645,7 @@ enum char_info_mode
/* Set a waitable timer */
@REQ(set_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 */
void* callback; /* callback function */
void* arg; /* callback argument */
......@@ -1666,7 +1664,7 @@ enum char_info_mode
@REQ(get_timer_info)
obj_handle_t handle; /* handle to the timer */
@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? */
@END
......@@ -1814,7 +1812,7 @@ enum char_info_mode
unsigned int msg; /* message code */
unsigned long wparam; /* 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 */
@END
......@@ -1987,7 +1985,7 @@ enum message_type
unsigned int maxinstances;
unsigned int outsize;
unsigned int insize;
unsigned int timeout;
timeout_t timeout;
VARARG(name,unicode_str); /* pipe name */
@REPLY
obj_handle_t handle; /* handle to the pipe */
......@@ -2010,7 +2008,7 @@ enum message_type
@REQ(wait_named_pipe)
obj_handle_t handle;
async_data_t async; /* async I/O parameters */
unsigned int timeout;
timeout_t timeout;
VARARG(name,unicode_str); /* pipe name */
@END
......@@ -2774,7 +2772,7 @@ enum message_type
unsigned int attributes; /* object attributes */
obj_handle_t rootdir; /* root directory */
unsigned int max_msgsize;
int read_timeout;
timeout_t read_timeout;
VARARG(name,unicode_str); /* mailslot name */
@REPLY
obj_handle_t handle; /* handle to the mailslot */
......@@ -2785,10 +2783,10 @@ enum message_type
@REQ(set_mailslot_info)
obj_handle_t handle; /* handle to the mailslot */
unsigned int flags;
int read_timeout;
timeout_t read_timeout;
@REPLY
unsigned int max_msgsize;
int read_timeout;
timeout_t read_timeout;
@END
#define MAILSLOT_SET_READ_TIMEOUT 1
......
......@@ -85,7 +85,7 @@ struct message
struct timer
{
struct list entry; /* entry in timer list */
struct timeval when; /* next expiration */
timeout_t when; /* next expiration */
unsigned int rate; /* timer rate in ms */
user_handle_t win; /* window handle */
unsigned int msg; /* message to post */
......@@ -131,7 +131,7 @@ struct msg_queue
struct timeout_user *timeout; /* timeout for next timer to expire */
struct thread_input *input; /* thread input descriptor */
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 );
......@@ -536,7 +536,7 @@ static void result_timeout( void *private )
/* allocate and fill a message result structure */
static struct message_result *alloc_message_result( struct msg_queue *send_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) );
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 );
}
if (timeout)
{
struct timeval when = current_time;
add_timeout( &when, timeout );
result->timeout = add_timeout_user( &when, result_timeout, result );
}
if (timeout != TIMEOUT_INFINITE)
result->timeout = add_timeout_user( timeout, result_timeout, result );
}
return result;
}
......@@ -766,7 +762,7 @@ static int is_queue_hung( struct msg_queue *queue )
{
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 */
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 )))
{
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 */
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)
{
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 );
}
......@@ -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 )
{
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 );
set_next_timer( queue );
}
......@@ -1098,8 +1094,7 @@ static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
if (timer)
{
timer->rate = max( rate, 1 );
timer->when = current_time;
add_timeout( &timer->when, rate );
timer->when = current_time + (timeout_t)timer->rate * 10000;
link_timer( queue, timer );
/* check if we replaced the next timer */
if (list_head( &queue->pending_timers ) == &timer->entry) set_next_timer( queue );
......
......@@ -103,7 +103,7 @@ struct key_value
/* the root of the registry tree */
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 void set_periodic_save_timer(void);
......@@ -1683,11 +1683,8 @@ static void periodic_save( void *arg )
/* start the periodic save timer */
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 );
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 */
......
......@@ -117,7 +117,7 @@ static const struct fd_ops master_socket_fd_ops =
struct thread *current = NULL; /* thread handling the current request */
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 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 */
unsigned int get_tick_count(void)
{
return ((current_time.tv_sec - server_start_time.tv_sec) * 1000) +
((current_time.tv_usec - server_start_time.tv_usec) / 1000);
return (current_time - server_start_time) / 10000;
}
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_iovlen = 1;
/* init startup time */
gettimeofday( &server_start_time, NULL );
/* init the process 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 */
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)
{
struct timeval when = current_time;
add_timeout( &when, master_socket_timeout * 1000 );
master_socket->timeout = add_timeout_user( &when, close_socket_timeout, NULL );
}
else close_socket_timeout( NULL ); /* close it right away */
master_socket->timeout = add_timeout_user( master_socket_timeout, close_socket_timeout, NULL );
else
close_socket_timeout( NULL ); /* close it right away */
}
/* forced shutdown, used for wineserver -k */
......
......@@ -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 )
{
struct serial *serial = get_fd_user( fd );
int timeout = 0;
timeout_t timeout = 0;
struct async *async;
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)
{
case ASYNC_TYPE_READ:
timeout = serial->readconst + serial->readmult*count;
timeout = serial->readconst + (timeout_t)serial->readmult*count;
break;
case ASYNC_TYPE_WRITE:
timeout = serial->writeconst + serial->writemult*count;
timeout = serial->writeconst + (timeout_t)serial->writemult*count;
break;
}
if ((async = fd_queue_async( fd, data, type, count )))
{
if (timeout)
{
struct timeval when = current_time;
add_timeout( &when, timeout );
async_set_timeout( async, &when, STATUS_TIMEOUT );
}
if (timeout) async_set_timeout( async, timeout * -10000, STATUS_TIMEOUT );
release_object( async );
set_error( STATUS_PENDING );
}
......
......@@ -59,7 +59,7 @@ struct thread_wait
int count; /* count of objects */
int flags;
void *cookie; /* magic cookie to return to client */
struct timeval timeout;
timeout_t timeout;
struct timeout_user *user;
struct wait_queue_entry queues[1];
};
......@@ -171,7 +171,7 @@ static inline void init_thread_structure( struct thread *thread )
thread->token = NULL;
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->system_apc );
......@@ -461,24 +461,20 @@ static void end_wait( struct thread *thread )
}
/* 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 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->thread = current;
wait->count = count;
wait->flags = flags;
wait->user = NULL;
wait->timeout = timeout;
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++)
{
......@@ -541,10 +537,7 @@ static int check_wait( struct thread *thread )
other_checks:
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_TIMEOUT)
{
if (!time_before( &current_time, &wait->timeout )) return STATUS_TIMEOUT;
}
if (wait->timeout <= current_time) return STATUS_TIMEOUT;
return -1;
}
......@@ -623,16 +616,19 @@ static int signal_object( obj_handle_t handle )
}
/* select on a list of handles */
static void select_on( int count, void *cookie, const obj_handle_t *handles,
int flags, const abs_time_t *timeout, obj_handle_t signal_obj )
static timeout_t select_on( unsigned int count, void *cookie, const obj_handle_t *handles,
int flags, timeout_t timeout, obj_handle_t signal_obj )
{
int ret, i;
int ret;
unsigned int i;
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 );
return;
return 0;
}
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 */
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 )))
{
end_wait( current );
......@@ -677,7 +673,8 @@ static void select_on( int count, void *cookie, const obj_handle_t *handles,
set_error( STATUS_PENDING );
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 */
......@@ -1035,8 +1032,7 @@ DECL_HANDLER(init_thread)
reply->pid = get_process_id( process );
reply->tid = get_thread_id( current );
reply->version = SERVER_PROTOCOL_VERSION;
reply->server_start.sec = server_start_time.tv_sec;
reply->server_start.usec = server_start_time.tv_usec;
reply->server_start = server_start_time;
return;
error:
......@@ -1094,10 +1090,8 @@ DECL_HANDLER(get_thread_info)
reply->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STATUS_PENDING;
reply->priority = thread->priority;
reply->affinity = thread->affinity;
reply->creation_time.sec = thread->creation_time.tv_sec;
reply->creation_time.usec = thread->creation_time.tv_usec;
reply->exit_time.sec = thread->exit_time.tv_sec;
reply->exit_time.usec = thread->exit_time.tv_usec;
reply->creation_time = thread->creation_time;
reply->exit_time = thread->exit_time;
reply->last = thread->process->running_threads == 1;
release_object( thread );
......@@ -1145,8 +1139,8 @@ DECL_HANDLER(resume_thread)
/* select on a handle list */
DECL_HANDLER(select)
{
int count = get_req_data_size() / sizeof(obj_handle_t);
select_on( count, req->cookie, get_req_data(), req->flags, &req->timeout, req->signal );
unsigned int count = get_req_data_size() / sizeof(obj_handle_t);
reply->timeout = select_on( count, req->cookie, get_req_data(), req->flags, req->timeout, req->signal );
}
/* queue an APC for a thread or process */
......
......@@ -84,8 +84,8 @@ struct thread
int suspend; /* suspend count */
obj_handle_t desktop; /* desktop handle */
int desktop_users; /* number of objects using the thread desktop */
struct timeval creation_time; /* Thread creation time */
struct timeval exit_time; /* Thread exit time */
timeout_t creation_time; /* Thread creation time */
timeout_t exit_time; /* Thread exit time */
struct token *token; /* security token associated with this thread */
};
......
......@@ -42,8 +42,8 @@ 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 */
unsigned int period; /* timer period in ms */
timeout_t when; /* next expiration */
struct timeout_user *timeout; /* timeout user */
struct thread *thread; /* thread that set the 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)
{
/* 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;
timer->thread = NULL;
timer->manual = manual;
timer->signaled = 0;
timer->when = 0;
timer->period = 0;
timer->timeout = NULL;
timer->thread = NULL;
}
}
return timer;
......@@ -110,11 +109,10 @@ static void timer_callback( void *private )
memset( &data, 0, sizeof(data) );
if (timer->callback)
{
data.type = APC_TIMER;
data.timer.func = timer->callback;
data.timer.time.sec = timer->when.tv_sec;
data.timer.time.usec = timer->when.tv_usec;
data.timer.arg = timer->arg;
data.type = APC_TIMER;
data.timer.func = timer->callback;
data.timer.time = timer->when;
data.timer.arg = timer->arg;
}
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 */
{
add_timeout( &timer->when, timer->period );
timer->timeout = add_timeout_user( &timer->when, timer_callback, timer );
timer->when += (timeout_t)timer->period * 10000;
timer->timeout = add_timeout_user( timer->when, timer_callback, timer );
}
else timer->timeout = NULL;
......@@ -157,7 +155,7 @@ static int cancel_timer( struct timer *timer )
}
/* 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 )
{
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 */
timer->signaled = 0;
}
if (!expire->sec && !expire->usec)
{
/* special case: use now + period as first expiration */
timer->when = current_time;
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;
timer->period = period;
timer->callback = callback;
timer->arg = arg;
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;
}
......@@ -189,8 +177,8 @@ 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.%06u period=%d ",
timer->manual, timer->when.tv_sec, (unsigned int)timer->when.tv_usec, timer->period );
fprintf( stderr, "Timer manual=%d when=%s period=%u ",
timer->manual, get_timeout_str(timer->when), timer->period );
dump_object_name( &timer->obj );
fputc( '\n', stderr );
}
......@@ -277,7 +265,7 @@ DECL_HANDLER(set_timer)
if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
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 );
}
}
......@@ -303,8 +291,7 @@ DECL_HANDLER(get_timer_info)
if ((timer = (struct timer *)get_handle_obj( current->process, req->handle,
TIMER_QUERY_STATE, &timer_ops )))
{
reply->when.sec = timer->when.tv_sec;
reply->when.usec = timer->when.tv_usec;
reply->when = timer->when;
reply->signaled = timer->signaled;
release_object( timer );
}
......
......@@ -64,25 +64,9 @@ static void dump_uints( const int *ptr, int len )
fputc( '}', stderr );
}
static void dump_abs_time( const abs_time_t *time )
static void dump_timeout( const timeout_t *time )
{
int secs, usecs;
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 );
fprintf( stderr, get_timeout_str(*time) );
}
static void dump_rectangle( const rectangle_t *rect )
......@@ -112,7 +96,7 @@ static void dump_apc_call( const apc_call_t *call )
break;
case APC_TIMER:
fprintf( stderr, "APC_TIMER,time=" );
dump_abs_time( &call->timer.time );
dump_timeout( &call->timer.time );
fprintf( stderr, ",arg=%p", call->timer.arg );
break;
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, " info_size=%u,", req->info_size );
fprintf( stderr, " server_start=" );
dump_abs_time( &req->server_start );
dump_timeout( &req->server_start );
fprintf( stderr, "," );
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, " peb=%p,", req->peb );
fprintf( stderr, " start_time=" );
dump_abs_time( &req->start_time );
dump_timeout( &req->start_time );
fprintf( stderr, "," );
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 )
......@@ -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, " affinity=%d,", req->affinity );
fprintf( stderr, " creation_time=" );
dump_abs_time( &req->creation_time );
dump_timeout( &req->creation_time );
fprintf( stderr, "," );
fprintf( stderr, " exit_time=" );
dump_abs_time( &req->exit_time );
dump_timeout( &req->exit_time );
fprintf( stderr, "," );
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, " signal=%p,", req->signal );
fprintf( stderr, " timeout=" );
dump_abs_time( &req->timeout );
dump_timeout( &req->timeout );
fprintf( stderr, "," );
fprintf( stderr, " handles=" );
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 )
{
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, " expire=" );
dump_abs_time( &req->expire );
dump_timeout( &req->expire );
fprintf( stderr, "," );
fprintf( stderr, " period=%d,", req->period );
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 )
{
fprintf( stderr, " when=" );
dump_abs_time( &req->when );
dump_timeout( &req->when );
fprintf( stderr, "," );
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, " wparam=%lx,", req->wparam );
fprintf( stderr, " lparam=%lx,", req->lparam );
fprintf( stderr, " timeout=%d,", req->timeout );
fprintf( stderr, " timeout=" );
dump_timeout( &req->timeout );
fprintf( stderr, "," );
fprintf( stderr, " data=" );
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, " outsize=%08x,", req->outsize );
fprintf( stderr, " insize=%08x,", req->insize );
fprintf( stderr, " timeout=%08x,", req->timeout );
fprintf( stderr, " timeout=" );
dump_timeout( &req->timeout );
fprintf( stderr, "," );
fprintf( stderr, " name=" );
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=" );
dump_async_data( &req->async );
fprintf( stderr, "," );
fprintf( stderr, " timeout=%08x,", req->timeout );
fprintf( stderr, " timeout=" );
dump_timeout( &req->timeout );
fprintf( stderr, "," );
fprintf( stderr, " name=" );
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, " rootdir=%p,", req->rootdir );
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=" );
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, " 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 )
{
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 )
......@@ -3706,7 +3706,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_dup_handle_reply,
(dump_func)dump_open_process_reply,
(dump_func)dump_open_thread_reply,
(dump_func)0,
(dump_func)dump_select_reply,
(dump_func)dump_create_event_reply,
(dump_func)0,
(dump_func)dump_open_event_reply,
......
......@@ -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 (desktop->users == 1 && get_top_window_owner( desktop ))
{
struct timeval when = current_time;
add_timeout( &when, 1000 );
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 );
}
......
......@@ -39,7 +39,7 @@ my %formats =
"user_handle_t" => "%p",
"process_id_t" => "%04x",
"thread_id_t" => "%04x",
"abs_time_t" => "&dump_abs_time",
"timeout_t" => "&dump_timeout",
"rectangle_t" => "&dump_rectangle",
"char_info_t" => "&dump_char_info",
"apc_call_t" => "&dump_apc_call",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment