From: Rémi Bernon rbernon@codeweavers.com
--- dlls/ntdll/unix/sync.c | 30 ++++++++++++++++++++++++++++++ dlls/ntdll/unix/thread.c | 1 + dlls/ntdll/unix/unix_private.h | 1 + dlls/ntdll/unix/virtual.c | 1 + server/inproc_sync.c | 17 ++++++++++++++--- server/object.h | 1 + server/protocol.def | 7 +++++++ server/thread.c | 14 ++++++++++++++ 8 files changed, 69 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index d8d8406f211..7095aef30f2 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -478,6 +478,33 @@ static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *inf return ret; }
+static int get_inproc_alert_fd(void) +{ + struct ntdll_thread_data *data = ntdll_get_thread_data(); + obj_handle_t token; + sigset_t sigset; + int fd; + + if ((fd = data->alert_fd) < 0) + { + server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); + + SERVER_START_REQ( get_inproc_alert_fd ) + { + if (!server_call_unlocked( req )) + { + data->alert_fd = fd = wine_server_receive_fd( &token ); + assert( token == reply->handle ); + } + } + SERVER_END_REQ; + + server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); + } + + return fd; +} + static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { @@ -497,6 +524,8 @@ static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_an syncs[i] = stack + i; }
+ if (alertable) get_inproc_alert_fd(); + while (count--) release_inproc_sync( syncs[count] ); return STATUS_NOT_IMPLEMENTED; } @@ -514,6 +543,7 @@ static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait,
if ((ret = get_inproc_sync( wait, INPROC_SYNC_UNKNOWN, SYNCHRONIZE, wait_sync ))) goto done;
+ if (alertable) get_inproc_alert_fd(); ret = STATUS_NOT_IMPLEMENTED;
release_inproc_sync( wait_sync ); diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 8f3fb701a38..10ccfe9eba2 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1104,6 +1104,7 @@ static void contexts_from_server( CONTEXT *context, struct context_data server_c */ static DECLSPEC_NORETURN void pthread_exit_wrapper( int status ) { + close( ntdll_get_thread_data()->alert_fd ); close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 75c04e5ec15..67cd3aede42 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -108,6 +108,7 @@ struct ntdll_thread_data int request_fd; /* fd for sending server requests */ int reply_fd; /* fd for receiving server replies */ int wait_fd[2]; /* fd for sleeping server requests */ + int alert_fd; /* inproc sync fd for user apc alerts */ BOOL allow_writes; /* ThreadAllowWrites flags */ pthread_t pthread_id; /* pthread thread id */ void *kernel_stack; /* stack for thread startup and kernel syscalls */ diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 994f76fb72a..126bd915e8d 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -4026,6 +4026,7 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) thread_data->reply_fd = -1; thread_data->wait_fd[0] = -1; thread_data->wait_fd[1] = -1; + thread_data->alert_fd = -1; list_add_head( &teb_list, &thread_data->entry ); return teb; } diff --git a/server/inproc_sync.c b/server/inproc_sync.c index 8cfd3b1e1e8..46222d56a45 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -88,6 +88,12 @@ static const struct object_ops inproc_sync_ops = inproc_sync_destroy, /* destroy */ };
+int get_inproc_sync_fd( struct inproc_sync *sync ) +{ + if (!sync) return -1; + return sync->fd; +} + struct inproc_sync *create_inproc_internal_sync( int manual, int signaled ) { struct ntsync_event_args args = {.signaled = signaled, .manual = manual}; @@ -147,7 +153,7 @@ static void inproc_sync_destroy( struct object *obj ) close( sync->fd ); }
-static int get_inproc_sync_fd( struct object *obj, int *type ) +static int get_obj_inproc_sync( struct object *obj, int *type ) { struct object *sync; int fd = -1; @@ -171,6 +177,11 @@ int get_inproc_device_fd(void) return -1; }
+int get_inproc_sync_fd( struct inproc_sync *sync ) +{ + return -1; +} + struct inproc_sync *create_inproc_internal_sync( int manual, int signaled ) { return NULL; @@ -184,7 +195,7 @@ void reset_inproc_sync( struct inproc_sync *sync ) { }
-static int get_inproc_sync_fd( struct object *obj, int *type ) +static int get_obj_inproc_sync( struct object *obj, int *type ) { return -1; } @@ -200,7 +211,7 @@ DECL_HANDLER(get_inproc_sync_fd)
reply->access = get_handle_access( current->process, req->handle );
- if ((fd = get_inproc_sync_fd( obj, &reply->type )) < 0) set_error( STATUS_NOT_IMPLEMENTED ); + if ((fd = get_obj_inproc_sync( obj, &reply->type )) < 0) set_error( STATUS_NOT_IMPLEMENTED ); else send_client_fd( current->process, fd, req->handle );
release_object( obj ); diff --git a/server/object.h b/server/object.h index 939b18f0036..bf242d0ad6d 100644 --- a/server/object.h +++ b/server/object.h @@ -245,6 +245,7 @@ extern void abandon_mutexes( struct thread *thread );
struct inproc_sync; extern int get_inproc_device_fd(void); +extern int get_inproc_sync_fd( struct inproc_sync *sync ); extern struct inproc_sync *create_inproc_internal_sync( int manual, int signaled ); extern void signal_inproc_sync( struct inproc_sync *sync ); extern void reset_inproc_sync( struct inproc_sync *sync ); diff --git a/server/protocol.def b/server/protocol.def index 3b2f6c497cf..14704f79b30 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4158,6 +4158,13 @@ enum inproc_sync_type @END
+/* Get the in-process synchronization fd for the current thread user APC alerts */ +@REQ(get_inproc_alert_fd) +@REPLY + obj_handle_t handle; /* alert fd is in flight with this handle */ +@END + + /* Create a global d3dkmt object */ @REQ(d3dkmt_object_create) unsigned int type; /* d3dkmt object type */ diff --git a/server/thread.c b/server/thread.c index b990907648f..bb16fa9331f 100644 --- a/server/thread.c +++ b/server/thread.c @@ -2370,3 +2370,17 @@ DECL_HANDLER(get_next_thread) set_error( STATUS_NO_MORE_ENTRIES ); release_object( process ); } + + +/* Get the in-process synchronization fd for the current thread user APC alerts */ +DECL_HANDLER(get_inproc_alert_fd) +{ + int fd; + + if ((fd = get_inproc_sync_fd( current->alert_sync )) < 0) set_error( STATUS_INVALID_PARAMETER ); + else + { + reply->handle = get_thread_id( current ) | 1; /* arbitrary token */ + send_client_fd( current->process, fd, reply->handle ); + } +}