From: Elizabeth Figura zfigura@codeweavers.com
--- server/inproc_sync.c | 88 ++++++++++++++++++++++++++++++++++++++++++++ server/object.h | 10 +++++ server/queue.c | 16 +++++--- 3 files changed, 109 insertions(+), 5 deletions(-)
diff --git a/server/inproc_sync.c b/server/inproc_sync.c index 1bef2469e96..4016421ef36 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -51,6 +51,81 @@ int get_inproc_device_fd(void) return fd; }
+struct inproc_sync +{ + struct object obj; /* object header */ + enum inproc_sync_type type; + int fd; +}; + +static void inproc_sync_dump( struct object *obj, int verbose ); +static void inproc_sync_destroy( struct object *obj ); + +static const struct object_ops inproc_sync_ops = +{ + sizeof(struct inproc_sync), /* size */ + &no_type, /* type */ + inproc_sync_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + default_get_sync, /* get_sync */ + default_map_access, /* map_access */ + default_get_sd, /* get_sd */ + default_set_sd, /* set_sd */ + default_get_full_name, /* get_full_name */ + no_lookup_name, /* lookup_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ + no_open_file, /* open_file */ + no_kernel_obj_list, /* get_kernel_obj_list */ + no_close_handle, /* close_handle */ + inproc_sync_destroy, /* destroy */ +}; + +struct inproc_sync *create_inproc_event_sync( int manual, int signaled ) +{ + struct ntsync_event_args args = {.signaled = signaled, .manual = manual}; + struct inproc_sync *event; + + if (!(event = alloc_object( &inproc_sync_ops ))) return NULL; + event->type = INPROC_SYNC_EVENT; + event->fd = ioctl( get_inproc_device_fd(), NTSYNC_IOC_CREATE_EVENT, &args ); + + return event; +} + +static void inproc_sync_dump( struct object *obj, int verbose ) +{ + struct inproc_sync *sync = (struct inproc_sync *)obj; + assert( obj->ops == &inproc_sync_ops ); + fprintf( stderr, "Inproc sync type=%d, fd=%d\n", sync->type, sync->fd ); +} + +void signal_inproc_sync( struct inproc_sync *sync ) +{ + __u32 count; + if (debug_level) fprintf( stderr, "set_inproc_event %d\n", sync->fd ); + ioctl( sync->fd, NTSYNC_IOC_EVENT_SET, &count ); +} + +void reset_inproc_sync( struct inproc_sync *sync ) +{ + __u32 count; + if (debug_level) fprintf( stderr, "reset_inproc_event %d\n", sync->fd ); + ioctl( sync->fd, NTSYNC_IOC_EVENT_RESET, &count ); +} + +static void inproc_sync_destroy( struct object *obj ) +{ + struct inproc_sync *sync = (struct inproc_sync *)obj; + assert( obj->ops == &inproc_sync_ops ); + close( sync->fd ); +} + #else /* NTSYNC_IOC_EVENT_READ */
int get_inproc_device_fd(void) @@ -58,4 +133,17 @@ int get_inproc_device_fd(void) return -1; }
+struct inproc_sync *create_inproc_event_sync( int manual, int signaled ) +{ + return NULL; +} + +void signal_inproc_sync( struct inproc_sync *sync ) +{ +} + +void reset_inproc_sync( struct inproc_sync *sync ) +{ +} + #endif /* NTSYNC_IOC_EVENT_READ */ diff --git a/server/object.h b/server/object.h index fc0bb51f5f5..b609f5f7af9 100644 --- a/server/object.h +++ b/server/object.h @@ -239,7 +239,17 @@ extern void abandon_mutexes( struct thread *thread );
/* in-process synchronization functions */
+enum inproc_sync_type +{ + INPROC_SYNC_UNKNOWN, + INPROC_SYNC_EVENT, +}; + +struct inproc_sync; extern int get_inproc_device_fd(void); +extern struct inproc_sync *create_inproc_event_sync( int manual, int signaled ); +extern void signal_inproc_sync( struct inproc_sync *sync ); +extern void reset_inproc_sync( struct inproc_sync *sync );
/* serial functions */
diff --git a/server/queue.c b/server/queue.c index 3845a86c962..792947c6813 100644 --- a/server/queue.c +++ b/server/queue.c @@ -116,6 +116,7 @@ struct msg_queue { struct object obj; /* object header */ struct fd *fd; /* optional file descriptor to poll */ + struct inproc_sync *inproc_sync; /* inproc sync for client-side waits */ int signaled; /* queue is signaled from fd POLLIN or masks */ int paint_count; /* pending paint messages count */ int hotkey_count; /* pending hotkey messages count */ @@ -306,6 +307,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ if ((queue = alloc_object( &msg_queue_ops ))) { queue->fd = NULL; + queue->inproc_sync = NULL; queue->signaled = 0; queue->paint_count = 0; queue->hotkey_count = 0; @@ -325,11 +327,8 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ list_init( &queue->expired_timers ); for (i = 0; i < NB_MSG_KINDS; i++) list_init( &queue->msg_list[i] );
- if (!(queue->shared = alloc_shared_object())) - { - release_object( queue ); - return NULL; - } + if (get_inproc_device_fd() >= 0 && !(queue->inproc_sync = create_inproc_event_sync( 1, 0 ))) goto error; + if (!(queue->shared = alloc_shared_object())) goto error;
SHARED_WRITE_BEGIN( queue->shared, queue_shm_t ) { @@ -351,6 +350,10 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ } if (new_input) release_object( new_input ); return queue; + +error: + release_object( queue ); + return NULL; }
/* free the message queue of a thread at thread exit */ @@ -714,11 +717,13 @@ static void signal_queue_sync( struct msg_queue *queue ) if (queue->signaled) return; queue->signaled = 1; wake_up( &queue->obj, 0 ); + if (queue->inproc_sync) signal_inproc_sync( queue->inproc_sync ); }
static void reset_queue_sync( struct msg_queue *queue ) { queue->signaled = 0; + if (queue->inproc_sync) reset_inproc_sync( queue->inproc_sync ); }
/* check the queue status */ @@ -1395,6 +1400,7 @@ static void msg_queue_destroy( struct object *obj ) if (queue->hooks) release_object( queue->hooks ); if (queue->fd) release_object( queue->fd ); if (queue->shared) free_shared_object( queue->shared ); + if (queue->inproc_sync) release_object( queue->inproc_sync ); }
static void msg_queue_poll_event( struct fd *fd, int event )