Commit 6267c4b8 authored by Zebediah Figura's avatar Zebediah Figura Committed by Vitaly Lipatov

server, ntdll: Implement message waits.

parent 3153d8d1
...@@ -475,12 +475,13 @@ static void update_grabbed_object( struct esync *obj ) ...@@ -475,12 +475,13 @@ static void update_grabbed_object( struct esync *obj )
/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we /* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we
* need to delegate to server_select(). */ * need to delegate to server_select(). */
NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any, static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) BOOLEAN alertable, const LARGE_INTEGER *timeout )
{ {
struct esync *objs[MAXIMUM_WAIT_OBJECTS]; struct esync *objs[MAXIMUM_WAIT_OBJECTS];
struct pollfd fds[MAXIMUM_WAIT_OBJECTS]; struct pollfd fds[MAXIMUM_WAIT_OBJECTS];
int has_esync = 0, has_server = 0; int has_esync = 0, has_server = 0;
BOOL msgwait = FALSE;
LONGLONG timeleft; LONGLONG timeleft;
LARGE_INTEGER now; LARGE_INTEGER now;
ULONGLONG end; ULONGLONG end;
...@@ -508,6 +509,9 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an ...@@ -508,6 +509,9 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
return ret; return ret;
} }
if (objs[count - 1] && objs[count - 1]->type == ESYNC_QUEUE)
msgwait = TRUE;
if (has_esync && has_server) if (has_esync && has_server)
FIXME("Can't wait on esync and server objects at the same time!\n"); FIXME("Can't wait on esync and server objects at the same time!\n");
else if (has_server) else if (has_server)
...@@ -519,6 +523,9 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an ...@@ -519,6 +523,9 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
TRACE(" %p", handles[i]); TRACE(" %p", handles[i]);
if (msgwait)
TRACE(" or driver events");
if (!timeout) if (!timeout)
TRACE(", timeout = INFINITE.\n"); TRACE(", timeout = INFINITE.\n");
else else
...@@ -558,7 +565,9 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an ...@@ -558,7 +565,9 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
int64_t value; int64_t value;
ssize_t size; ssize_t size;
if (obj->type == ESYNC_MANUAL_EVENT || obj->type == ESYNC_MANUAL_SERVER) if (obj->type == ESYNC_MANUAL_EVENT
|| obj->type == ESYNC_MANUAL_SERVER
|| obj->type == ESYNC_QUEUE)
{ {
/* Don't grab the object, just check if it's signaled. */ /* Don't grab the object, just check if it's signaled. */
if (fds[i].revents & POLLIN) if (fds[i].revents & POLLIN)
...@@ -603,6 +612,44 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an ...@@ -603,6 +612,44 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
} }
} }
/* We need to let the server know when we are doing a message wait, and when we
* are done with one, so that all of the code surrounding hung queues works.
* We also need this for WaitForInputIdle(). */
static void server_set_msgwait( int in_msgwait )
{
SERVER_START_REQ( esync_msgwait )
{
req->in_msgwait = in_msgwait;
wine_server_call( req );
}
SERVER_END_REQ;
}
/* This is a very thin wrapper around the proper implementation above. The
* purpose is to make sure the server knows when we are doing a message wait.
* This is separated into a wrapper function since there are at least a dozen
* exit paths from esync_wait_objects(). */
NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout )
{
BOOL msgwait = FALSE;
struct esync *obj;
NTSTATUS ret;
if (count && !get_object( handles[count - 1], &obj ) && obj->type == ESYNC_QUEUE)
{
msgwait = TRUE;
server_set_msgwait( 1 );
}
ret = __esync_wait_objects( count, handles, wait_any, alertable, timeout );
if (msgwait)
server_set_msgwait( 0 );
return ret;
}
void esync_init(void) void esync_init(void)
{ {
struct stat st; struct stat st;
......
...@@ -5521,6 +5521,17 @@ struct get_esync_fd_reply ...@@ -5521,6 +5521,17 @@ struct get_esync_fd_reply
}; };
struct esync_msgwait_request
{
struct request_header __header;
int in_msgwait;
};
struct esync_msgwait_reply
{
struct reply_header __header;
};
enum request enum request
{ {
REQ_new_process, REQ_new_process,
...@@ -5802,6 +5813,7 @@ enum request ...@@ -5802,6 +5813,7 @@ enum request
REQ_get_next_thread, REQ_get_next_thread,
REQ_create_esync, REQ_create_esync,
REQ_get_esync_fd, REQ_get_esync_fd,
REQ_esync_msgwait,
REQ_NB_REQUESTS REQ_NB_REQUESTS
}; };
...@@ -6088,6 +6100,7 @@ union generic_request ...@@ -6088,6 +6100,7 @@ union generic_request
struct get_next_thread_request get_next_thread_request; struct get_next_thread_request get_next_thread_request;
struct create_esync_request create_esync_request; struct create_esync_request create_esync_request;
struct get_esync_fd_request get_esync_fd_request; struct get_esync_fd_request get_esync_fd_request;
struct esync_msgwait_request esync_msgwait_request;
}; };
union generic_reply union generic_reply
{ {
...@@ -6372,11 +6385,12 @@ union generic_reply ...@@ -6372,11 +6385,12 @@ union generic_reply
struct get_next_thread_reply get_next_thread_reply; struct get_next_thread_reply get_next_thread_reply;
struct create_esync_reply create_esync_reply; struct create_esync_reply create_esync_reply;
struct get_esync_fd_reply get_esync_fd_reply; struct get_esync_fd_reply get_esync_fd_reply;
struct esync_msgwait_reply esync_msgwait_reply;
}; };
/* ### protocol_version begin ### */ /* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 759 #define SERVER_PROTOCOL_VERSION 760
/* ### protocol_version end ### */ /* ### protocol_version end ### */
......
...@@ -3797,3 +3797,8 @@ enum esync_type ...@@ -3797,3 +3797,8 @@ enum esync_type
int type; int type;
unsigned int shm_idx; unsigned int shm_idx;
@END @END
/* Notify the server that we are doing a message wait or done with one. */
@REQ(esync_msgwait)
int in_msgwait; /* are we in a message wait? */
@END
...@@ -144,6 +144,7 @@ struct msg_queue ...@@ -144,6 +144,7 @@ struct msg_queue
int keystate_lock; /* owns an input keystate lock */ int keystate_lock; /* owns an input keystate lock */
unsigned int ignore_post_msg; /* ignore post messages newer than this unique id */ unsigned int ignore_post_msg; /* ignore post messages newer than this unique id */
int esync_fd; /* esync file descriptor (signalled on message) */ int esync_fd; /* esync file descriptor (signalled on message) */
int esync_in_msgwait; /* our thread is currently waiting on us */
}; };
struct hotkey struct hotkey
...@@ -317,6 +318,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ ...@@ -317,6 +318,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
queue->keystate_lock = 0; queue->keystate_lock = 0;
queue->ignore_post_msg = 0; queue->ignore_post_msg = 0;
queue->esync_fd = -1; queue->esync_fd = -1;
queue->esync_in_msgwait = 0;
list_init( &queue->send_result ); list_init( &queue->send_result );
list_init( &queue->callback_result ); list_init( &queue->callback_result );
list_init( &queue->pending_timers ); list_init( &queue->pending_timers );
...@@ -1001,6 +1003,10 @@ static int is_queue_hung( struct msg_queue *queue ) ...@@ -1001,6 +1003,10 @@ static int is_queue_hung( struct msg_queue *queue )
if (get_wait_queue_thread(entry)->queue == queue) if (get_wait_queue_thread(entry)->queue == queue)
return 0; /* thread is waiting on queue -> not hung */ return 0; /* thread is waiting on queue -> not hung */
} }
if (do_esync() && queue->esync_in_msgwait)
return 0; /* thread is waiting on queue in absentia -> not hung */
return 1; return 1;
} }
...@@ -3456,3 +3462,18 @@ DECL_HANDLER(update_rawinput_devices) ...@@ -3456,3 +3462,18 @@ DECL_HANDLER(update_rawinput_devices)
process->rawinput_mouse = find_rawinput_device( process, 1, 2 ); process->rawinput_mouse = find_rawinput_device( process, 1, 2 );
process->rawinput_kbd = find_rawinput_device( process, 1, 6 ); process->rawinput_kbd = find_rawinput_device( process, 1, 6 );
} }
DECL_HANDLER(esync_msgwait)
{
struct msg_queue *queue = get_current_queue();
if (!queue) return;
queue->esync_in_msgwait = req->in_msgwait;
if (current->process->idle_event && !(queue->wake_mask & QS_SMRESULT))
set_event( current->process->idle_event );
/* and start/stop waiting on the driver */
if (queue->fd)
set_fd_events( queue->fd, req->in_msgwait ? POLLIN : 0 );
}
...@@ -398,6 +398,7 @@ DECL_HANDLER(resume_process); ...@@ -398,6 +398,7 @@ DECL_HANDLER(resume_process);
DECL_HANDLER(get_next_thread); DECL_HANDLER(get_next_thread);
DECL_HANDLER(create_esync); DECL_HANDLER(create_esync);
DECL_HANDLER(get_esync_fd); DECL_HANDLER(get_esync_fd);
DECL_HANDLER(esync_msgwait);
#ifdef WANT_REQUEST_HANDLERS #ifdef WANT_REQUEST_HANDLERS
...@@ -683,6 +684,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = ...@@ -683,6 +684,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_next_thread, (req_handler)req_get_next_thread,
(req_handler)req_create_esync, (req_handler)req_create_esync,
(req_handler)req_get_esync_fd, (req_handler)req_get_esync_fd,
(req_handler)req_esync_msgwait,
}; };
C_ASSERT( sizeof(abstime_t) == 8 ); C_ASSERT( sizeof(abstime_t) == 8 );
...@@ -2286,6 +2288,8 @@ C_ASSERT( sizeof(struct get_esync_fd_request) == 16 ); ...@@ -2286,6 +2288,8 @@ C_ASSERT( sizeof(struct get_esync_fd_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_esync_fd_reply, type) == 8 ); C_ASSERT( FIELD_OFFSET(struct get_esync_fd_reply, type) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_esync_fd_reply, shm_idx) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_esync_fd_reply, shm_idx) == 12 );
C_ASSERT( sizeof(struct get_esync_fd_reply) == 16 ); C_ASSERT( sizeof(struct get_esync_fd_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct esync_msgwait_request, in_msgwait) == 12 );
C_ASSERT( sizeof(struct esync_msgwait_request) == 16 );
#endif /* WANT_REQUEST_HANDLERS */ #endif /* WANT_REQUEST_HANDLERS */
......
...@@ -4527,6 +4527,11 @@ static void dump_get_esync_fd_reply( const struct get_esync_fd_reply *req ) ...@@ -4527,6 +4527,11 @@ static void dump_get_esync_fd_reply( const struct get_esync_fd_reply *req )
fprintf( stderr, ", shm_idx=%08x", req->shm_idx ); fprintf( stderr, ", shm_idx=%08x", req->shm_idx );
} }
static void dump_esync_msgwait_request( const struct esync_msgwait_request *req )
{
fprintf( stderr, " in_msgwait=%d", req->in_msgwait );
}
static const dump_func req_dumpers[REQ_NB_REQUESTS] = { static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request, (dump_func)dump_new_process_request,
(dump_func)dump_get_new_process_info_request, (dump_func)dump_get_new_process_info_request,
...@@ -4807,6 +4812,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { ...@@ -4807,6 +4812,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_next_thread_request, (dump_func)dump_get_next_thread_request,
(dump_func)dump_create_esync_request, (dump_func)dump_create_esync_request,
(dump_func)dump_get_esync_fd_request, (dump_func)dump_get_esync_fd_request,
(dump_func)dump_esync_msgwait_request,
}; };
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
...@@ -5089,6 +5095,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { ...@@ -5089,6 +5095,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_next_thread_reply, (dump_func)dump_get_next_thread_reply,
(dump_func)dump_create_esync_reply, (dump_func)dump_create_esync_reply,
(dump_func)dump_get_esync_fd_reply, (dump_func)dump_get_esync_fd_reply,
NULL,
}; };
static const char * const req_names[REQ_NB_REQUESTS] = { static const char * const req_names[REQ_NB_REQUESTS] = {
...@@ -5371,6 +5378,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { ...@@ -5371,6 +5378,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_next_thread", "get_next_thread",
"create_esync", "create_esync",
"get_esync_fd", "get_esync_fd",
"esync_msgwait",
}; };
static const struct static const struct
......
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