mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
eventfd_synchronization: Abandon esync mutexes on thread exit.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48089
This commit is contained in:
parent
ede44e4e8f
commit
8b2fd051c9
@ -0,0 +1,197 @@
|
||||
From c00917721a5076b90e3e61a7d326ef485c1f9dfb Mon Sep 17 00:00:00 2001
|
||||
From: Zebediah Figura <z.figura12@gmail.com>
|
||||
Date: Mon, 17 Feb 2020 11:28:37 -0600
|
||||
Subject: [PATCH] ntdll, server: Abandon esync mutexes on thread exit.
|
||||
|
||||
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
||||
---
|
||||
dlls/ntdll/esync.c | 31 ++++++++++++++++++++++++++-----
|
||||
server/esync.c | 32 +++++++++++++++++++++++++++++---
|
||||
server/esync.h | 1 +
|
||||
server/thread.c | 2 ++
|
||||
4 files changed, 58 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
|
||||
index 87f303403..c2190f2fd 100644
|
||||
--- a/dlls/ntdll/esync.c
|
||||
+++ b/dlls/ntdll/esync.c
|
||||
@@ -807,7 +807,7 @@ NTSTATUS esync_query_mutex( HANDLE handle, MUTANT_INFORMATION_CLASS class,
|
||||
|
||||
out->CurrentCount = 1 - mutex->count;
|
||||
out->OwnedByCaller = (mutex->tid == GetCurrentThreadId());
|
||||
- out->AbandonedState = FALSE;
|
||||
+ out->AbandonedState = (mutex->tid == ~0);
|
||||
if (ret_len) *ret_len = sizeof(*out);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@@ -857,14 +857,19 @@ static int do_poll( struct pollfd *fds, nfds_t nfds, ULONGLONG *end )
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void update_grabbed_object( struct esync *obj )
|
||||
+/* Return TRUE if abandoned. */
|
||||
+static BOOL update_grabbed_object( struct esync *obj )
|
||||
{
|
||||
+ BOOL ret = FALSE;
|
||||
+
|
||||
if (obj->type == ESYNC_MUTEX)
|
||||
{
|
||||
struct mutex *mutex = obj->shm;
|
||||
/* We don't have to worry about a race between this and read(); the
|
||||
* fact that we grabbed it means the count is now zero, so nobody else
|
||||
* can (and the only thread that can release it is us). */
|
||||
+ if (mutex->tid == ~0)
|
||||
+ ret = TRUE;
|
||||
mutex->tid = GetCurrentThreadId();
|
||||
mutex->count++;
|
||||
}
|
||||
@@ -885,6 +890,8 @@ static void update_grabbed_object( struct esync *obj )
|
||||
* This might already be 0, but that's okay! */
|
||||
event->signaled = 0;
|
||||
}
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we
|
||||
@@ -1018,7 +1025,13 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles,
|
||||
{
|
||||
if ((size = read( obj->fd, &value, sizeof(value) )) == sizeof(value))
|
||||
{
|
||||
- TRACE("Woken up by handle %p [%d].\n", handles[i], i);
|
||||
+ if (mutex->tid == ~0)
|
||||
+ {
|
||||
+ TRACE("Woken up by abandoned mutex %p [%d].\n", handles[i], i);
|
||||
+ i += STATUS_ABANDONED_WAIT_0;
|
||||
+ }
|
||||
+ else
|
||||
+ TRACE("Woken up by handle %p [%d].\n", handles[i], i);
|
||||
mutex->tid = GetCurrentThreadId();
|
||||
mutex->count++;
|
||||
return i;
|
||||
@@ -1136,7 +1149,8 @@ static NTSTATUS __esync_wait_objects( DWORD count, const HANDLE *handles,
|
||||
{
|
||||
/* We found our object. */
|
||||
TRACE("Woken up by handle %p [%d].\n", handles[i], i);
|
||||
- update_grabbed_object( obj );
|
||||
+ if (update_grabbed_object( obj ))
|
||||
+ return STATUS_ABANDONED_WAIT_0 + i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -1255,6 +1269,8 @@ tryagain:
|
||||
ret = poll( fds, pollcount, 0 );
|
||||
if (ret == pollcount)
|
||||
{
|
||||
+ BOOL abandoned = FALSE;
|
||||
+
|
||||
/* Quick, grab everything. */
|
||||
for (i = 0; i < pollcount; i++)
|
||||
{
|
||||
@@ -1295,8 +1311,13 @@ tryagain:
|
||||
/* Make sure to let ourselves know that we grabbed the mutexes
|
||||
* and semaphores. */
|
||||
for (i = 0; i < count; i++)
|
||||
- update_grabbed_object( objs[i] );
|
||||
+ abandoned |= update_grabbed_object( objs[i] );
|
||||
|
||||
+ if (abandoned)
|
||||
+ {
|
||||
+ TRACE("Wait successful, but some object(s) were abandoned.\n");
|
||||
+ return STATUS_ABANDONED;
|
||||
+ }
|
||||
TRACE("Wait successful.\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
diff --git a/server/esync.c b/server/esync.c
|
||||
index 040e24e69..1b035bdb0 100644
|
||||
--- a/server/esync.c
|
||||
+++ b/server/esync.c
|
||||
@@ -104,12 +104,15 @@ void esync_init(void)
|
||||
atexit( shm_cleanup );
|
||||
}
|
||||
|
||||
+static struct list mutex_list = LIST_INIT(mutex_list);
|
||||
+
|
||||
struct esync
|
||||
{
|
||||
- struct object obj; /* object header */
|
||||
- int fd; /* eventfd file descriptor */
|
||||
+ struct object obj; /* object header */
|
||||
+ int fd; /* eventfd file descriptor */
|
||||
enum esync_type type;
|
||||
- unsigned int shm_idx; /* index into the shared memory section */
|
||||
+ unsigned int shm_idx; /* index into the shared memory section */
|
||||
+ struct list mutex_entry; /* entry in the mutex list (if applicable) */
|
||||
};
|
||||
|
||||
static void esync_dump( struct object *obj, int verbose );
|
||||
@@ -168,6 +171,8 @@ static unsigned int esync_map_access( struct object *obj, unsigned int access )
|
||||
static void esync_destroy( struct object *obj )
|
||||
{
|
||||
struct esync *esync = (struct esync *)obj;
|
||||
+ if (esync->type == ESYNC_MUTEX)
|
||||
+ list_remove( &esync->mutex_entry );
|
||||
close( esync->fd );
|
||||
}
|
||||
|
||||
@@ -301,6 +306,7 @@ static struct esync *create_esync( struct object *root, const struct unicode_str
|
||||
struct mutex *mutex = get_shm( esync->shm_idx );
|
||||
mutex->tid = initval ? 0 : current->id;
|
||||
mutex->count = initval ? 0 : 1;
|
||||
+ list_add_tail( &mutex_list, &esync->mutex_entry );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -447,6 +453,26 @@ void esync_reset_event( struct esync *esync )
|
||||
}
|
||||
}
|
||||
|
||||
+void esync_abandon_mutexes( struct thread *thread )
|
||||
+{
|
||||
+ unsigned int index = 0;
|
||||
+ struct esync *esync;
|
||||
+
|
||||
+ LIST_FOR_EACH_ENTRY( esync, &mutex_list, struct esync, mutex_entry )
|
||||
+ {
|
||||
+ struct mutex *mutex = get_shm( esync->shm_idx );
|
||||
+
|
||||
+ if (mutex->tid == thread->id)
|
||||
+ {
|
||||
+ if (debug_level)
|
||||
+ fprintf( stderr, "esync_abandon_mutexes() fd=%d\n", esync->fd );
|
||||
+ mutex->tid = ~0;
|
||||
+ mutex->count = 0;
|
||||
+ esync_wake_fd( esync->fd );
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
DECL_HANDLER(create_esync)
|
||||
{
|
||||
struct esync *esync;
|
||||
diff --git a/server/esync.h b/server/esync.h
|
||||
index cea025d93..125da8e9d 100644
|
||||
--- a/server/esync.h
|
||||
+++ b/server/esync.h
|
||||
@@ -30,3 +30,4 @@ struct esync;
|
||||
extern const struct object_ops esync_ops;
|
||||
void esync_set_event( struct esync *esync );
|
||||
void esync_reset_event( struct esync *esync );
|
||||
+void esync_abandon_mutexes( struct thread *thread );
|
||||
diff --git a/server/thread.c b/server/thread.c
|
||||
index d1923b4e8..1d5bca525 100644
|
||||
--- a/server/thread.c
|
||||
+++ b/server/thread.c
|
||||
@@ -1253,6 +1253,8 @@ void kill_thread( struct thread *thread, int violent_death )
|
||||
kill_console_processes( thread, 0 );
|
||||
debug_exit_thread( thread );
|
||||
abandon_mutexes( thread );
|
||||
+ if (do_esync())
|
||||
+ esync_abandon_mutexes( thread );
|
||||
if (violent_death)
|
||||
{
|
||||
send_thread_signal( thread, SIGQUIT );
|
||||
--
|
||||
2.25.0
|
||||
|
@ -3703,6 +3703,7 @@ if test "$enable_eventfd_synchronization" -eq 1; then
|
||||
patch_apply eventfd_synchronization/0086-ntdll-Check-the-APC-fd-first.patch
|
||||
patch_apply eventfd_synchronization/0087-ntdll-esync-Lock-accessing-the-shm_addrs-array.patch
|
||||
patch_apply eventfd_synchronization/0088-ntdll-Get-rid-of-the-per-event-spinlock-for-auto-res.patch
|
||||
patch_apply eventfd_synchronization/0089-ntdll-server-Abandon-esync-mutexes-on-thread-exit.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Zebediah Figura", "configure: Check for sys/eventfd.h, ppoll(), and shm_open().", 1 },';
|
||||
printf '%s\n' '+ { "Zebediah Figura", "server: Create server objects for eventfd-based synchronization objects.", 1 },';
|
||||
@ -3792,6 +3793,7 @@ if test "$enable_eventfd_synchronization" -eq 1; then
|
||||
printf '%s\n' '+ { "Zebediah Figura", "ntdll: Check the APC fd first.", 1 },';
|
||||
printf '%s\n' '+ { "Zebediah Figura", "ntdll/esync: Lock accessing the shm_addrs array.", 1 },';
|
||||
printf '%s\n' '+ { "Zebediah Figura", "ntdll: Get rid of the per-event spinlock for auto-reset events.", 1 },';
|
||||
printf '%s\n' '+ { "Zebediah Figura", "ntdll, server: Abandon esync mutexes on thread exit.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user