Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:X0F:HSF
wine
fsync-spincounts.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File fsync-spincounts.patch of Package wine
From ecfa1989fe9bd940a7d8b0529eca0766b7aecb47 Mon Sep 17 00:00:00 2001 From: Zebediah Figura <zfigura@codeweavers.com> Date: Mon, 19 Aug 2019 18:25:42 -0500 Subject: [PATCH] ntdll/fsync: Introduce a configurable spin count. --- dlls/ntdll/fsync.c | 56 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/dlls/ntdll/fsync.c b/dlls/ntdll/fsync.c index bcb927fd581..20de45bc595 100644 --- a/dlls/ntdll/fsync.c +++ b/dlls/ntdll/fsync.c @@ -64,6 +64,15 @@ struct futex_wait_block }; #include "poppack.h" +static inline void small_pause(void) +{ +#if defined(__i386__) || defined(__x86_64__) + __asm__ __volatile__( "rep;nop" : : : "memory" ); +#else + __asm__ __volatile__( "" : : : "memory" ); +#endif +} + static inline int futex_wait_multiple( const struct futex_wait_block *futexes, int count, const struct timespec *timeout ) { @@ -80,6 +89,8 @@ static inline int futex_wait( int *addr, int val, struct timespec *timeout ) return syscall( __NR_futex, addr, 0, val, timeout, 0, 0 ); } +static unsigned int spincount; + int do_fsync(void) { #ifdef __linux__ @@ -90,6 +101,8 @@ int do_fsync(void) static const struct timespec zero; futex_wait_multiple( NULL, 0, &zero ); do_fsync_cached = getenv("WINEFSYNC") && atoi(getenv("WINEFSYNC")) && errno != ENOSYS; + if (getenv("WINEFSYNC_SPINCOUNT")) + spincount = atoi(getenv("WINEFSYNC_SPINCOUNT")); } return do_fsync_cached; @@ -735,6 +748,7 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, int has_fsync = 0, has_server = 0; BOOL msgwait = FALSE; int dummy_futex = 0; + unsigned int spin; LONGLONG timeleft; LARGE_INTEGER now; DWORD waitcount; @@ -844,10 +858,14 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, struct semaphore *semaphore = obj->shm; int current; - do + for (spin = 0; spin < spincount + 1; ++spin) { - if (!(current = semaphore->count)) break; - } while (__sync_val_compare_and_swap( &semaphore->count, current, current - 1 ) != current); + do + { + if (!(current = semaphore->count)) break; + } while (__sync_val_compare_and_swap( &semaphore->count, current, current - 1 ) != current); + small_pause(); + } if (current) { @@ -871,11 +889,15 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, return i; } - if (!(tid = __sync_val_compare_and_swap( &mutex->tid, 0, GetCurrentThreadId() ))) + for (spin = 0; spin < spincount + 1; ++spin) { - TRACE("Woken up by handle %p [%d].\n", handles[i], i); - mutex->count = 1; - return i; + if (!(tid = __sync_val_compare_and_swap( &mutex->tid, 0, GetCurrentThreadId() ))) + { + TRACE("Woken up by handle %p [%d].\n", handles[i], i); + mutex->count = 1; + return i; + } + small_pause(); } futexes[i].addr = &mutex->tid; @@ -887,10 +909,14 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, { struct event *event = obj->shm; - if (__sync_val_compare_and_swap( &event->signaled, 1, 0 )) + for (spin = 0; spin < spincount + 1; ++spin) { - TRACE("Woken up by handle %p [%d].\n", handles[i], i); - return i; + if (__sync_val_compare_and_swap( &event->signaled, 1, 0 )) + { + TRACE("Woken up by handle %p [%d].\n", handles[i], i); + return i; + } + small_pause(); } futexes[i].addr = &event->signaled; @@ -903,10 +929,14 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, { struct event *event = obj->shm; - if (__atomic_load_n( &event->signaled, __ATOMIC_SEQ_CST )) + for (spin = 0; spin < spincount + 1; ++spin) { - TRACE("Woken up by handle %p [%d].\n", handles[i], i); - return i; + if (__atomic_load_n( &event->signaled, __ATOMIC_SEQ_CST )) + { + TRACE("Woken up by handle %p [%d].\n", handles[i], i); + return i; + } + small_pause(); } futexes[i].addr = &event->signaled; From 9b714d4047bf136b87b94fa27dac38bbbb7d68ac Mon Sep 17 00:00:00 2001 From: "Pierre-Loup A. Griffais" <pgriffais@valvesoftware.com> Date: Tue, 10 Sep 2019 11:49:05 -0700 Subject: [PATCH] ntdll: fix spin count for fsync semaphores --- dlls/ntdll/fsync.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/fsync.c b/dlls/ntdll/fsync.c index 20de45bc595..b3871ad3834 100644 --- a/dlls/ntdll/fsync.c +++ b/dlls/ntdll/fsync.c @@ -862,11 +862,11 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, { do { - if (!(current = semaphore->count)) break; + if (!(current = semaphore->count)) goto out; } while (__sync_val_compare_and_swap( &semaphore->count, current, current - 1 ) != current); small_pause(); } - +out: if (current) { TRACE("Woken up by handle %p [%d].\n", handles[i], i); From 455786a3e6750ae502376da06e41424d012d52bf Mon Sep 17 00:00:00 2001 From: Zebediah Figura <zfigura@codeweavers.com> Date: Mon, 16 Sep 2019 12:11:36 -0500 Subject: [PATCH] ntdll: fix for spincounts --- dlls/ntdll/fsync.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/dlls/ntdll/fsync.c b/dlls/ntdll/fsync.c index b3871ad3834..2c4c656d276 100644 --- a/dlls/ntdll/fsync.c +++ b/dlls/ntdll/fsync.c @@ -860,18 +860,14 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, for (spin = 0; spin < spincount + 1; ++spin) { - do + if ((current = __atomic_load_n( &semaphore->count, __ATOMIC_SEQ_CST )) + && __sync_val_compare_and_swap( &semaphore->count, current, current - 1) == current) { - if (!(current = semaphore->count)) goto out; - } while (__sync_val_compare_and_swap( &semaphore->count, current, current - 1 ) != current); + TRACE("Woken up by handle %p [%d].\n", handles[i], i); + return i; + } small_pause(); } -out: - if (current) - { - TRACE("Woken up by handle %p [%d].\n", handles[i], i); - return i; - } futexes[i].addr = &semaphore->count; futexes[i].val = current; From 367e8f9e04164299c175ade7a77915d1698d4770 Mon Sep 17 00:00:00 2001 From: Zebediah Figura <z.figura12@gmail.com> Date: Tue, 29 Oct 2019 19:09:17 -0500 Subject: [PATCH] ntdll/fsync: Fix spincounts for semaphores, again. --- dlls/ntdll/fsync.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dlls/ntdll/fsync.c b/dlls/ntdll/fsync.c index 2c4c656d276..16bd38e7c8f 100644 --- a/dlls/ntdll/fsync.c +++ b/dlls/ntdll/fsync.c @@ -858,10 +858,14 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, struct semaphore *semaphore = obj->shm; int current; - for (spin = 0; spin < spincount + 1; ++spin) + /* It would be a little clearer (and less error-prone) + * to use a dedicated interlocked_dec_if_nonzero() + * helper, but nesting loops like that is probably not + * great for performance... */ + for (spin = 0; spin < spincount + 1 || current; ++spin) { if ((current = __atomic_load_n( &semaphore->count, __ATOMIC_SEQ_CST )) - && __sync_val_compare_and_swap( &semaphore->count, current, current - 1) == current) + && __sync_val_compare_and_swap( &semaphore->count, current, current - 1 ) == current) { TRACE("Woken up by handle %p [%d].\n", handles[i], i); return i; @@ -870,7 +874,7 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, } futexes[i].addr = &semaphore->count; - futexes[i].val = current; + futexes[i].val = 0; break; } case FSYNC_MUTEX: From 7a046421705a207e1e2c9bbfdcae77260c18401e Mon Sep 17 00:00:00 2001 From: Zebediah Figura <z.figura12@gmail.com> Date: Mon, 17 Feb 2020 11:57:40 -0600 Subject: [PATCH] ntdll, server: Abandon fsync mutexes on thread exit. --- dlls/ntdll/fsync.c | 35 ++++++++++++++++++++++++++++------- server/fsync.c | 34 ++++++++++++++++++++++++++++++++++ server/fsync.h | 1 + server/thread.c | 2 ++ 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/dlls/ntdll/fsync.c b/dlls/ntdll/fsync.c index 19aacc6a090..e16c3142bd3 100644 --- a/dlls/ntdll/fsync.c +++ b/dlls/ntdll/fsync.c @@ -662,7 +662,7 @@ NTSTATUS fsync_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; @@ -897,6 +897,12 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, mutex->count = 1; return i; } + else if (tid == ~0 && (tid = __sync_val_compare_and_swap( &mutex->tid, ~0, GetCurrentThreadId() )) == ~0) + { + TRACE("Woken up by abandoned mutex %p [%d].\n", handles[i], i); + mutex->count = 1; + return STATUS_ABANDONED_WAIT_0 + i; + } small_pause(); } @@ -1034,7 +1040,11 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, while (1) { + BOOL abandoned; + tryagain: + abandoned = FALSE; + /* First step: try to wait on each object in sequence. */ for (i = 0; i < count; i++) @@ -1086,11 +1096,9 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, if (obj && obj->type == FSYNC_MUTEX) { struct mutex *mutex = obj->shm; + int tid = __atomic_load_n( &mutex->tid, __ATOMIC_SEQ_CST ); - if (mutex->tid == GetCurrentThreadId()) - continue; /* ok */ - - if (__atomic_load_n( &mutex->tid, __ATOMIC_SEQ_CST )) + if (tid && tid != ~0 && tid != GetCurrentThreadId()) goto tryagain; } else if (obj) @@ -1111,10 +1119,15 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, case FSYNC_MUTEX: { struct mutex *mutex = obj->shm; - if (mutex->tid == GetCurrentThreadId()) + int tid = __atomic_load_n( &mutex->tid, __ATOMIC_SEQ_CST ); + if (tid == GetCurrentThreadId()) break; - if (__sync_val_compare_and_swap( &mutex->tid, 0, GetCurrentThreadId() )) + if (tid && tid != ~0) + goto tooslow; + if (__sync_val_compare_and_swap( &mutex->tid, tid, GetCurrentThreadId() ) != tid) goto tooslow; + if (tid == ~0) + abandoned = TRUE; break; } case FSYNC_SEMAPHORE: @@ -1150,6 +1163,11 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, } } + if (abandoned) + { + TRACE("Wait successful, but some object(s) were abandoned.\n"); + return STATUS_ABANDONED; + } TRACE("Wait successful.\n"); return STATUS_SUCCESS; @@ -1162,6 +1180,9 @@ static NTSTATUS __fsync_wait_objects( DWORD count, const HANDLE *handles, case FSYNC_MUTEX: { struct mutex *mutex = obj->shm; + /* HACK: This won't do the right thing with abandoned + * mutexes, but fixing it is probably more trouble than + * it's worth. */ __atomic_store_n( &mutex->tid, 0, __ATOMIC_SEQ_CST ); break; } diff --git a/server/fsync.c b/server/fsync.c index 346f7492a51..0d60565455d 100644 --- a/server/fsync.c +++ b/server/fsync.c @@ -132,11 +132,14 @@ void fsync_init(void) atexit( shm_cleanup ); } +static struct list mutex_list = LIST_INIT(mutex_list); + struct fsync { struct object obj; unsigned int shm_idx; enum fsync_type type; + struct list mutex_entry; }; static void fsync_dump( struct object *obj, int verbose ); @@ -195,6 +198,9 @@ static unsigned int fsync_map_access( struct object *obj, unsigned int access ) static void fsync_destroy( struct object *obj ) { + struct fsync *fsync = (struct fsync *)obj; + if (fsync->type == FSYNC_MUTEX) + list_remove( &fsync->mutex_entry ); } static void *get_shm( unsigned int idx ) @@ -297,6 +303,8 @@ struct fsync *create_fsync( struct object *root, const struct unicode_str *name, fsync->shm_idx = fsync_alloc_shm( low, high ); fsync->type = type; + if (type == FSYNC_MUTEX) + list_add_tail( &mutex_list, &fsync->mutex_entry ); } else { @@ -397,6 +405,32 @@ void fsync_reset_event( struct fsync *fsync ) __atomic_store_n( &event->signaled, 0, __ATOMIC_SEQ_CST ); } +struct mutex +{ + int tid; + int count; /* recursion count */ +}; + +void fsync_abandon_mutexes( struct thread *thread ) +{ + unsigned int index = 0; + struct fsync *fsync; + + LIST_FOR_EACH_ENTRY( fsync, &mutex_list, struct fsync, mutex_entry ) + { + struct mutex *mutex = get_shm( fsync->shm_idx ); + + if (mutex->tid == thread->id) + { + if (debug_level) + fprintf( stderr, "fsync_abandon_mutexes() idx=%d\n", fsync->shm_idx ); + mutex->tid = ~0; + mutex->count = 0; + futex_wake( &mutex->tid, INT_MAX ); + } + } +} + DECL_HANDLER(create_fsync) { struct fsync *fsync; diff --git a/server/fsync.h b/server/fsync.h index f6f1a48b31e..a91939b7f0a 100644 --- a/server/fsync.h +++ b/server/fsync.h @@ -31,3 +31,4 @@ struct fsync; extern const struct object_ops fsync_ops; extern void fsync_set_event( struct fsync *fsync ); extern void fsync_reset_event( struct fsync *fsync ); +extern void fsync_abandon_mutexes( struct thread *thread ); diff --git a/server/thread.c b/server/thread.c index 4d33f357bf8..c8c44ecf51e 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1250,6 +1250,8 @@ void kill_thread( struct thread *thread, int violent_death ) kill_console_processes( thread, 0 ); debug_exit_thread( thread ); abandon_mutexes( thread ); + if (do_fsync()) + fsync_abandon_mutexes( thread ); if (do_esync()) esync_abandon_mutexes( thread ); wake_up( &thread->obj, 0 ); From 9756774948ed5364b52e3e797b92c40bbdd8aa07 Mon Sep 17 00:00:00 2001 From: Zebediah Figura <z.figura12@gmail.com> Date: Mon, 17 Feb 2020 14:33:20 -0600 Subject: [PATCH] kernel32/tests: Add a test for mutex abandonment. --- dlls/kernel32/tests/sync.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index b4f5d1f1f0b..492cb1f72f2 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -193,6 +193,13 @@ static DWORD WINAPI mutex_thread( void *param ) return 0; } +static DWORD WINAPI abandon_mutex_thread( void *param ) +{ + DWORD ret = WaitForSingleObject( mutex, 0 ); + ok(!ret, "got %u\n", ret); + return 0; +} + static void test_mutex(void) { HANDLE thread; @@ -379,12 +386,24 @@ todo_wine_if(getenv("WINEESYNC")) /* XFAIL: due to the above */ ret = ReleaseMutex( mutex2 ); ok(ret, "got error %u\n", GetLastError()); + thread = CreateThread( NULL, 0, abandon_mutex_thread, NULL, 0, NULL ); + ret = WaitForSingleObject( thread, 2000 ); + ok(ret == 0, "wait failed: %u\n", ret); + + ret = WaitForSingleObject( mutex, 0 ); + ok(ret == WAIT_ABANDONED, "got %u\n", ret); + + ret = ReleaseMutex( mutex ); + ok(ret, "got error %u\n", GetLastError()); + + ret = WaitForSingleObject( mutex, 0 ); + ok(!ret, "got %u\n", ret); + ret = CloseHandle( mutex ); ok(ret, "got error %u\n", GetLastError()); ret = CloseHandle( mutex2 ); ok(ret, "got error %u\n", GetLastError()); - } static void test_slist(void)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor