Moved idle event handling to the server.
diff --git a/server/Makefile.in b/server/Makefile.in
index 0db09e5..2416736 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -22,6 +22,7 @@
pipe.c \
process.c \
ptrace.c \
+ queue.c \
registry.c \
request.c \
select.c \
diff --git a/server/object.h b/server/object.h
index 8869504..66ce781 100644
--- a/server/object.h
+++ b/server/object.h
@@ -72,6 +72,14 @@
#endif
};
+struct wait_queue_entry
+{
+ struct wait_queue_entry *next;
+ struct wait_queue_entry *prev;
+ struct object *obj;
+ struct thread *thread;
+};
+
extern void *mem_alloc( size_t size ); /* malloc wrapper */
extern void *memdup( const void *data, size_t len );
extern void *alloc_object( const struct object_ops *ops, int fd );
diff --git a/server/process.c b/server/process.c
index 733b693..987bdd8 100644
--- a/server/process.c
+++ b/server/process.c
@@ -137,6 +137,8 @@
req->hstderr = alloc_handle( process, process->console_out,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
}
+ /* some handles above may have been invalid; this is not an error */
+ if (get_error() == STATUS_INVALID_HANDLE) clear_error();
return 1;
}
@@ -165,6 +167,8 @@
process->console_in = NULL;
process->console_out = NULL;
process->init_event = NULL;
+ process->idle_event = NULL;
+ process->queue = NULL;
process->ldt_copy = NULL;
process->ldt_flags = NULL;
process->exe.next = NULL;
@@ -282,6 +286,8 @@
if (process->prev) process->prev->next = process->next;
else first_process = process->next;
if (process->init_event) release_object( process->init_event );
+ if (process->idle_event) release_object( process->idle_event );
+ if (process->queue) release_object( process->queue );
if (process->exe.file) release_object( process->exe.file );
}
@@ -813,6 +819,7 @@
set_event( process->init_event );
release_object( process->init_event );
process->init_event = NULL;
+ if (req->gui) process->idle_event = create_event( NULL, 0, 1, 0 );
if (current->suspend + current->process->suspend > 0) stop_thread( current );
req->debugged = (current->process->debugger != 0);
}
@@ -919,3 +926,19 @@
{
process_unload_dll( current->process, req->base );
}
+
+/* wait for a process to start waiting on input */
+/* FIXME: only returns event for now, wait is done in the client */
+DECL_HANDLER(wait_input_idle)
+{
+ struct process *process;
+
+ req->event = -1;
+ if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
+ {
+ if (process->idle_event && process != current->process && process->queue != current->queue)
+ req->event = alloc_handle( current->process, process->idle_event,
+ EVENT_ALL_ACCESS, 0 );
+ release_object( process );
+ }
+}
diff --git a/server/process.h b/server/process.h
index ae606a5..2b7a699 100644
--- a/server/process.h
+++ b/server/process.h
@@ -13,6 +13,8 @@
#include "object.h"
+struct msg_queue;
+
/* process structures */
struct process_dll
@@ -45,6 +47,8 @@
struct object *console_in; /* console input */
struct object *console_out; /* console output */
struct event *init_event; /* event for init done */
+ struct event *idle_event; /* event for input idle */
+ struct msg_queue *queue; /* main message queue */
struct process_dll exe; /* main exe file */
void *ldt_copy; /* pointer to LDT copy in client addr space */
void *ldt_flags; /* pointer to LDT flags in client addr space */
diff --git a/server/queue.c b/server/queue.c
new file mode 100644
index 0000000..80cfda6
--- /dev/null
+++ b/server/queue.c
@@ -0,0 +1,130 @@
+/*
+ * Server-side message queues
+ *
+ * Copyright (C) 2000 Alexandre Julliard
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "handle.h"
+#include "thread.h"
+#include "process.h"
+#include "request.h"
+
+struct msg_queue
+{
+ struct object obj; /* object header */
+ struct thread *thread; /* thread owning this queue */
+ int signaled; /* queue has been signaled */
+};
+
+static void msg_queue_dump( struct object *obj, int verbose );
+static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry );
+static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
+static int msg_queue_signaled( struct object *obj, struct thread *thread );
+static int msg_queue_satisfied( struct object *obj, struct thread *thread );
+
+static const struct object_ops msg_queue_ops =
+{
+ sizeof(struct msg_queue), /* size */
+ msg_queue_dump, /* dump */
+ msg_queue_add_queue, /* add_queue */
+ msg_queue_remove_queue, /* remove_queue */
+ msg_queue_signaled, /* signaled */
+ msg_queue_satisfied, /* satisfied */
+ NULL, /* get_poll_events */
+ NULL, /* poll_event */
+ no_read_fd, /* get_read_fd */
+ no_write_fd, /* get_write_fd */
+ no_flush, /* flush */
+ no_get_file_info, /* get_file_info */
+ no_destroy /* destroy */
+};
+
+
+static struct msg_queue *create_msg_queue( struct thread *thread )
+{
+ struct msg_queue *queue;
+
+ if ((queue = alloc_object( &msg_queue_ops, -1 )))
+ {
+ queue->signaled = 0;
+ queue->thread = thread;
+ thread->queue = queue;
+ if (!thread->process->queue)
+ thread->process->queue = (struct msg_queue *)grab_object( queue );
+ }
+ return queue;
+}
+
+static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
+{
+ struct msg_queue *queue = (struct msg_queue *)obj;
+ struct process *process = entry->thread->process;
+
+ /* if waiting on the main process queue, set the idle event */
+ if (entry->thread == queue->thread && process->queue == queue)
+ {
+ if (process->idle_event) set_event( process->idle_event );
+ }
+ add_queue( obj, entry );
+ return 1;
+}
+
+static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *entry )
+{
+ struct msg_queue *queue = (struct msg_queue *)obj;
+ struct process *process = entry->thread->process;
+
+ remove_queue( obj, entry );
+
+ /* if waiting on the main process queue, reset the idle event */
+ if (entry->thread == queue->thread && process->queue == queue)
+ {
+ if (process->idle_event) reset_event( process->idle_event );
+ }
+}
+
+static void msg_queue_dump( struct object *obj, int verbose )
+{
+ struct msg_queue *queue = (struct msg_queue *)obj;
+ fprintf( stderr, "Msg queue signaled=%d owner=%p\n", queue->signaled, queue->thread );
+}
+
+static int msg_queue_signaled( struct object *obj, struct thread *thread )
+{
+ struct msg_queue *queue = (struct msg_queue *)obj;
+ return queue->signaled;
+}
+
+static int msg_queue_satisfied( struct object *obj, struct thread *thread )
+{
+ struct msg_queue *queue = (struct msg_queue *)obj;
+ queue->signaled = 0;
+ return 0; /* Not abandoned */
+}
+
+/* get the message queue of the current thread */
+DECL_HANDLER(get_msg_queue)
+{
+ struct msg_queue *queue = current->queue;
+
+ req->handle = -1;
+ if (!queue) queue = create_msg_queue( current );
+ if (queue) req->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
+}
+
+/* wake up a message queue */
+DECL_HANDLER(wake_queue)
+{
+ struct msg_queue *queue = (struct msg_queue *)get_handle_obj( current->process, req->handle,
+ 0, &msg_queue_ops );
+ if (queue)
+ {
+ queue->signaled = 1;
+ wake_up( &queue->obj, 0 );
+ release_object( queue );
+ }
+}
diff --git a/server/request.h b/server/request.h
index f87b4f5..6e3c943 100644
--- a/server/request.h
+++ b/server/request.h
@@ -173,6 +173,9 @@
DECL_HANDLER(delete_atom);
DECL_HANDLER(find_atom);
DECL_HANDLER(get_atom_name);
+DECL_HANDLER(get_msg_queue);
+DECL_HANDLER(wake_queue);
+DECL_HANDLER(wait_input_idle);
#ifdef WANT_REQUEST_HANDLERS
@@ -282,6 +285,9 @@
(req_handler)req_delete_atom,
(req_handler)req_find_atom,
(req_handler)req_get_atom_name,
+ (req_handler)req_get_msg_queue,
+ (req_handler)req_wake_queue,
+ (req_handler)req_wait_input_idle,
};
#endif /* WANT_REQUEST_HANDLERS */
diff --git a/server/thread.c b/server/thread.c
index f98982d..1899132 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -34,14 +34,6 @@
/* thread queues */
-struct wait_queue_entry
-{
- struct wait_queue_entry *next;
- struct wait_queue_entry *prev;
- struct object *obj;
- struct thread *thread;
-};
-
struct thread_wait
{
int count; /* count of objects */
@@ -131,6 +123,7 @@
thread->mutex = NULL;
thread->debug_ctx = NULL;
thread->debug_event = NULL;
+ thread->queue = NULL;
thread->info = NULL;
thread->wait = NULL;
thread->apc = NULL;
@@ -196,6 +189,7 @@
else first_thread = thread->next;
if (thread->apc) free( thread->apc );
if (thread->info) release_object( thread->info );
+ if (thread->queue) release_object( thread->queue );
if (thread->buffer != (void *)-1) munmap( thread->buffer, MAX_REQUEST_LENGTH );
if (thread->pass_fd != -1) close( thread->pass_fd );
}
diff --git a/server/thread.h b/server/thread.h
index 3340d5e..910c330 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -22,6 +22,7 @@
struct debug_ctx;
struct debug_event;
struct startup_info;
+struct msg_queue;
enum run_state
{
@@ -41,6 +42,7 @@
struct mutex *mutex; /* list of currently owned mutexes */
struct debug_ctx *debug_ctx; /* debugger context if this thread is a debugger */
struct debug_event *debug_event; /* debug event being sent to debugger */
+ struct msg_queue *queue; /* message queue */
struct startup_info*info; /* startup info for child process */
struct thread_wait *wait; /* current wait condition if sleeping */
struct thread_apc *apc; /* list of async procedure calls */
diff --git a/server/trace.c b/server/trace.c
index 4ea9319..369fed0 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -284,7 +284,8 @@
static void dump_init_process_done_request( const struct init_process_done_request *req )
{
fprintf( stderr, " module=%p,", req->module );
- fprintf( stderr, " entry=%p", req->entry );
+ fprintf( stderr, " entry=%p,", req->entry );
+ fprintf( stderr, " gui=%d", req->gui );
}
static void dump_init_process_done_reply( const struct init_process_done_request *req )
@@ -1333,6 +1334,32 @@
dump_unicode_string( req, req->name );
}
+static void dump_get_msg_queue_request( const struct get_msg_queue_request *req )
+{
+}
+
+static void dump_get_msg_queue_reply( const struct get_msg_queue_request *req )
+{
+ fprintf( stderr, " handle=%d", req->handle );
+}
+
+static void dump_wake_queue_request( const struct wake_queue_request *req )
+{
+ fprintf( stderr, " handle=%d,", req->handle );
+ fprintf( stderr, " bits=%08x", req->bits );
+}
+
+static void dump_wait_input_idle_request( const struct wait_input_idle_request *req )
+{
+ fprintf( stderr, " handle=%d,", req->handle );
+ fprintf( stderr, " timeout=%d", req->timeout );
+}
+
+static void dump_wait_input_idle_reply( const struct wait_input_idle_request *req )
+{
+ fprintf( stderr, " event=%d", req->event );
+}
+
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request,
(dump_func)dump_wait_process_request,
@@ -1437,6 +1464,9 @@
(dump_func)dump_delete_atom_request,
(dump_func)dump_find_atom_request,
(dump_func)dump_get_atom_name_request,
+ (dump_func)dump_get_msg_queue_request,
+ (dump_func)dump_wake_queue_request,
+ (dump_func)dump_wait_input_idle_request,
};
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -1543,6 +1573,9 @@
(dump_func)0,
(dump_func)dump_find_atom_reply,
(dump_func)dump_get_atom_name_reply,
+ (dump_func)dump_get_msg_queue_reply,
+ (dump_func)0,
+ (dump_func)dump_wait_input_idle_reply,
};
static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -1649,6 +1682,9 @@
"delete_atom",
"find_atom",
"get_atom_name",
+ "get_msg_queue",
+ "wake_queue",
+ "wait_input_idle",
};
/* ### make_requests end ### */