From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/msvcrt/concurrency.c | 50 +++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 7 deletions(-)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index f7f7adb86ed..9b066230a54 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -1900,6 +1900,15 @@ static ThreadScheduler *get_thread_scheduler_from_context(Context *context) return NULL; }
+static void execute_chore(_UnrealizedChore *chore, + _StructuredTaskCollection *task_collection) +{ + TRACE("(%p %p)\n", chore, task_collection); + + if (chore->chore_proc) + chore->chore_proc(chore); +} + static void CALLBACK chore_wrapper_finally(BOOL normal, void *data) { _UnrealizedChore *chore = data; @@ -1921,23 +1930,20 @@ static void CALLBACK chore_wrapper_finally(BOOL normal, void *data) new_finished = prev_finished + 1; } while (InterlockedCompareExchange(ptr, new_finished, prev_finished) != prev_finished); + RtlWakeAddressAll((LONG*)ptr); }
static void __cdecl chore_wrapper(_UnrealizedChore *chore) { - TRACE("(%p)\n", chore); - __TRY { - if (chore->chore_proc) - chore->chore_proc(chore); + execute_chore(chore, chore->task_collection); } __FINALLY_CTX(chore_wrapper_finally, chore) }
-static void __cdecl _StructuredTaskCollection_scheduler_cb(void *data) +static void pick_and_execute_chore(ThreadScheduler *scheduler) { - ThreadScheduler *scheduler = (ThreadScheduler*)get_current_scheduler(); struct list *entry; struct scheduled_chore *sc; _UnrealizedChore *chore; @@ -1965,6 +1971,11 @@ static void __cdecl _StructuredTaskCollection_scheduler_cb(void *data) chore->chore_wrapper(chore); }
+static void __cdecl _StructuredTaskCollection_scheduler_cb(void *data) +{ + pick_and_execute_chore((ThreadScheduler*)get_current_scheduler()); +} + static bool schedule_chore(_StructuredTaskCollection *this, _UnrealizedChore *chore, Scheduler **pscheduler) { @@ -2048,7 +2059,32 @@ void __thiscall _StructuredTaskCollection__Schedule( _StructuredTaskCollection__RunAndWait( _StructuredTaskCollection *this, _UnrealizedChore *chore) { - FIXME("(%p %p): stub!\n", this, chore); + LONG expected, val; + + TRACE("(%p %p)\n", this, chore); + + if (this->context) + { + ThreadScheduler *scheduler = get_thread_scheduler_from_context(this->context); + if (scheduler) + pick_and_execute_chore(scheduler); + } + + if (chore) { + if (chore->task_collection) { + invalid_multiple_scheduling e; + invalid_multiple_scheduling_ctor_str(&e, "Chore scheduled multiple times"); + _CxxThrowException(&e, &invalid_multiple_scheduling_exception_type); + } + execute_chore(chore, this); + } + + expected = this->count ? this->count : FINISHED_INITIAL; + while ((val = this->finished) != expected) + RtlWaitOnAddress((LONG*)&this->finished, &val, sizeof(val), NULL); + + this->finished = 0; + this->count = 0; return 1; }