forked from GloriousEggroll/proton-ge-custom
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproton-fsync-spincounts.patch
484 lines (437 loc) · 18.8 KB
/
proton-fsync-spincounts.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
From ecfa1989fe9bd940a7d8b0529eca0766b7aecb47 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <[email protected]>
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" <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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)