From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/concurrency.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 156789a35d6..6f2a9a414cf 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -2120,7 +2120,6 @@ void __thiscall _StructuredTaskCollection__Cancel( struct scheduled_chore *sc, *next; struct beacon *beacon; LONG removed = 0; - LONG prev_finished, new_finished;
TRACE("(%p)\n", this);
@@ -2162,15 +2161,8 @@ void __thiscall _StructuredTaskCollection__Cancel( if (!removed) return;
- new_finished = this->finished; - do { - prev_finished = new_finished; - if (prev_finished == FINISHED_INITIAL) - new_finished = removed; - else - new_finished = prev_finished + removed; - } while ((new_finished = InterlockedCompareExchange(&this->finished, - new_finished, prev_finished)) != prev_finished); + if (InterlockedCompareExchange(&this->finished, removed, FINISHED_INITIAL) != FINISHED_INITIAL) + InterlockedAdd(&this->finished, removed); RtlWakeAddressAll((LONG*)&this->finished); }
@@ -2248,7 +2240,7 @@ static void execute_chore(_UnrealizedChore *chore, static void CALLBACK chore_wrapper_finally(BOOL normal, void *data) { _UnrealizedChore *chore = data; - LONG count, prev_finished, new_finished; + LONG count; volatile LONG *ptr;
TRACE("(%u %p)\n", normal, data); @@ -2259,15 +2251,9 @@ static void CALLBACK chore_wrapper_finally(BOOL normal, void *data) count = chore->task_collection->count; chore->task_collection = NULL;
- do { - prev_finished = *ptr; - if (prev_finished == FINISHED_INITIAL) - new_finished = 1; - else - new_finished = prev_finished + 1; - } while (InterlockedCompareExchange(ptr, new_finished, prev_finished) - != prev_finished); - if (new_finished >= count) + if (InterlockedCompareExchange(ptr, 1, FINISHED_INITIAL) != FINISHED_INITIAL) + InterlockedIncrement(ptr); + if (*ptr >= count) RtlWakeAddressSingle((LONG*)ptr); }
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/concurrency.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 6f2a9a414cf..fa21a206e79 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -193,7 +193,7 @@ typedef struct _StructuredTaskCollection volatile LONG count; volatile LONG finished; void *exception; - void *event; + Context *event; } _StructuredTaskCollection;
bool __thiscall _StructuredTaskCollection__IsCanceling(_StructuredTaskCollection*); @@ -2118,8 +2118,8 @@ void __thiscall _StructuredTaskCollection__Cancel( ThreadScheduler *scheduler; void *prev_exception, *new_exception; struct scheduled_chore *sc, *next; + LONG removed = 0, finished = 1; struct beacon *beacon; - LONG removed = 0;
TRACE("(%p)\n", this);
@@ -2162,8 +2162,9 @@ void __thiscall _StructuredTaskCollection__Cancel( return;
if (InterlockedCompareExchange(&this->finished, removed, FINISHED_INITIAL) != FINISHED_INITIAL) - InterlockedAdd(&this->finished, removed); - RtlWakeAddressAll((LONG*)&this->finished); + finished = InterlockedAdd(&this->finished, removed); + if (!finished) + call_Context_Unblock(this->event); }
static LONG CALLBACK execute_chore_except(EXCEPTION_POINTERS *pexc, void *_data) @@ -2240,21 +2241,20 @@ static void execute_chore(_UnrealizedChore *chore, static void CALLBACK chore_wrapper_finally(BOOL normal, void *data) { _UnrealizedChore *chore = data; - LONG count; volatile LONG *ptr; + LONG finished = 1;
TRACE("(%u %p)\n", normal, data);
if (!chore->task_collection) return; ptr = &chore->task_collection->finished; - count = chore->task_collection->count; - chore->task_collection = NULL;
if (InterlockedCompareExchange(ptr, 1, FINISHED_INITIAL) != FINISHED_INITIAL) - InterlockedIncrement(ptr); - if (*ptr >= count) - RtlWakeAddressSingle((LONG*)ptr); + finished = InterlockedIncrement(ptr); + if (!finished) + call_Context_Unblock(chore->task_collection->event); + chore->task_collection = NULL; }
static void __cdecl chore_wrapper(_UnrealizedChore *chore) @@ -2393,9 +2393,9 @@ static void CALLBACK exception_ptr_rethrow_finally(BOOL normal, void *data) _TaskCollectionStatus __stdcall _StructuredTaskCollection__RunAndWait( _StructuredTaskCollection *this, _UnrealizedChore *chore) { - LONG expected, val; ULONG_PTR exception; exception_ptr *ep; + LONG count;
TRACE("(%p %p)\n", this, chore);
@@ -2415,12 +2415,17 @@ _TaskCollectionStatus __stdcall _StructuredTaskCollection__RunAndWait( } }
- expected = this->count ? this->count : FINISHED_INITIAL; - while ((val = this->finished) != expected) - RtlWaitOnAddress((LONG*)&this->finished, &val, sizeof(val), NULL); + this->event = get_current_context(); + InterlockedCompareExchange(&this->finished, 0, FINISHED_INITIAL);
- this->finished = 0; - this->count = 0; + while (this->count != 0) { + count = this->count; + InterlockedAdd(&this->count, -count); + count = InterlockedAdd(&this->finished, -count); + + if (count < 0) + call_Context_Block(this->event); + }
exception = (ULONG_PTR)this->exception; ep = (exception_ptr*)(exception & ~STRUCTURED_TASK_COLLECTION_STATUS_MASK);