Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47375 Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- v3 -> v4: Add dummy UnrealizedChore definition.
dlls/concrt140/concrt140.spec | 2 +- dlls/msvcr100/msvcr100.spec | 2 +- dlls/msvcr110/msvcr110.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/concurrency.c | 25 +++++++++++++++++++++++++ 6 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/dlls/concrt140/concrt140.spec b/dlls/concrt140/concrt140.spec index 50db9348327..ab57c736672 100644 --- a/dlls/concrt140/concrt140.spec +++ b/dlls/concrt140/concrt140.spec @@ -596,7 +596,7 @@ @ stub -arch=win64 ?_RunAndWait@_TaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z @ stub -arch=arm ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z(ptr ptr) StructuredTaskCollection__Schedule @ stub -arch=arm ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@PAVlocation@3@@Z @ stub -arch=i386 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@PAVlocation@3@@Z @ stub -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@PEAVlocation@3@@Z diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index 19b4cbe96d7..68a78a6aa16 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -364,7 +364,7 @@ @ stub -arch=win32 ?_RunAndWait@_TaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=win64 ?_RunAndWait@_TaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z @ stub -arch=win32 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z(ptr ptr) StructuredTaskCollection__Schedule @ stub -arch=win32 ?_Schedule@_TaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@@Z @ stub -arch=win64 ?_Schedule@_TaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z @ thiscall -arch=win32 ?_SetSpinCount@?$_SpinWait@$00@details@Concurrency@@QAEXI@Z(ptr long) SpinWait__SetSpinCount diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 23840f85eda..0f5eaf9ac51 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -616,7 +616,7 @@ @ stub -arch=win64 ?_RunAndWait@_TaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z @ stub -arch=arm ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z(ptr ptr) StructuredTaskCollection__Schedule @ stub -arch=arm ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@PAVlocation@3@@Z @ stub -arch=i386 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@PAVlocation@3@@Z @ stub -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@PEAVlocation@3@@Z diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 64ddeed42f4..332a617932e 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -598,7 +598,7 @@ @ stub -arch=win64 ?_RunAndWait@_TaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z @ stub -arch=arm ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z(ptr ptr) StructuredTaskCollection__Schedule @ stub -arch=arm ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@PAVlocation@3@@Z @ stub -arch=i386 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@PAVlocation@3@@Z @ stub -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@PEAVlocation@3@@Z diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index 05f408d6884..ee2ee2c42a1 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -594,7 +594,7 @@ @ stub -arch=win64 ?_RunAndWait@_TaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z @ stub -arch=arm ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z(ptr ptr) msvcr120.?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z @ stub -arch=arm ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@PAVlocation@3@@Z @ stub -arch=i386 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@PAVlocation@3@@Z @ stub -arch=win64 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@PEAVlocation@3@@Z diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 2ca6421b0e7..b884952b314 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -174,6 +174,20 @@ typedef struct cs_queue #endif } cs_queue;
+#if _MSVCR_VER >= 100 + +typedef struct +{ + char dummy; +} UnrealizedChore; + +typedef struct +{ + char dummy; +} StructuredTaskCollection; + +#endif /* _MSVCR_VER >= 100 */ + typedef struct { ULONG_PTR unk_thread_id; @@ -1741,6 +1755,17 @@ bool __thiscall SpinWait__SpinOnce(SpinWait *this) } }
+#if _MSVCR_VER >= 100 + +/* ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z */ +DEFINE_THISCALL_WRAPPER(StructuredTaskCollection__Schedule, 8) +void __thiscall StructuredTaskCollection__Schedule(StructuredTaskCollection *this, UnrealizedChore *chore) +{ + FIXME("(%p %p): stub!\n", this, chore); +} + +#endif /* _MSVCR_VER >= 100 */ + /* ??0critical_section@Concurrency@@QAE@XZ */ /* ??0critical_section@Concurrency@@QEAA@XZ */ DEFINE_THISCALL_WRAPPER(critical_section_ctor, 4)
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- v3 -> v4: Implemented execution of the chores in a thread pool.
dlls/concrt140/concrt140.spec | 2 +- dlls/msvcr100/msvcr100.spec | 2 +- dlls/msvcr110/msvcr110.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/concurrency.c | 151 +++++++++++++++++++++++++++- 6 files changed, 151 insertions(+), 10 deletions(-)
diff --git a/dlls/concrt140/concrt140.spec b/dlls/concrt140/concrt140.spec index ab57c736672..6b5ab7a5511 100644 --- a/dlls/concrt140/concrt140.spec +++ b/dlls/concrt140/concrt140.spec @@ -590,7 +590,7 @@ @ cdecl -arch=win64 ?_Reset@?$_SpinWait@$0A@@details@Concurrency@@IEAAXXZ(ptr) SpinWait__Reset @ stub -arch=arm ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z(ptr ptr) StructuredTaskCollection__RunAndWait @ stub -arch=arm ?_RunAndWait@_TaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_RunAndWait@_TaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=win64 ?_RunAndWait@_TaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index 68a78a6aa16..4b6308193a5 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -360,7 +360,7 @@ @ thiscall -arch=win32 ?_Reset@?$_SpinWait@$0A@@details@Concurrency@@IAEXXZ(ptr) SpinWait__Reset @ cdecl -arch=win64 ?_Reset@?$_SpinWait@$0A@@details@Concurrency@@IEAAXXZ(ptr) SpinWait__Reset @ stub -arch=win32 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z(ptr ptr) StructuredTaskCollection__RunAndWait @ stub -arch=win32 ?_RunAndWait@_TaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=win64 ?_RunAndWait@_TaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z @ stub -arch=win32 ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@@Z diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 0f5eaf9ac51..64c015b8ab6 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -610,7 +610,7 @@ @ cdecl -arch=win64 ?_Reset@?$_SpinWait@$0A@@details@Concurrency@@IEAAXXZ(ptr) SpinWait__Reset @ stub -arch=arm ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z(ptr ptr) StructuredTaskCollection__RunAndWait @ stub -arch=arm ?_RunAndWait@_TaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_RunAndWait@_TaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=win64 ?_RunAndWait@_TaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 332a617932e..46e16257b5d 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -592,7 +592,7 @@ @ cdecl -arch=win64 ?_Reset@?$_SpinWait@$0A@@details@Concurrency@@IEAAXXZ(ptr) SpinWait__Reset @ stub -arch=arm ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z(ptr ptr) StructuredTaskCollection__RunAndWait @ stub -arch=arm ?_RunAndWait@_TaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_RunAndWait@_TaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=win64 ?_RunAndWait@_TaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index ee2ee2c42a1..2bf4a5010f8 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -588,7 +588,7 @@ @ cdecl -arch=win64 ?_Reset@?$_SpinWait@$0A@@details@Concurrency@@IEAAXXZ(ptr) msvcr120.?_Reset@?$_SpinWait@$0A@@details@Concurrency@@IEAAXXZ @ stub -arch=arm ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z(ptr ptr) msvcr120.?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z @ stub -arch=arm ?_RunAndWait@_TaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=i386 ?_RunAndWait@_TaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z @ stub -arch=win64 ?_RunAndWait@_TaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index b884952b314..2da39745f93 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -22,8 +22,10 @@ #include <stdbool.h>
#include "windef.h" +#include "winbase.h" #include "winternl.h" #include "wine/debug.h" +#include "wine/exception.h" #include "msvcrt.h" #include "cxx.h"
@@ -176,14 +178,39 @@ typedef struct cs_queue
#if _MSVCR_VER >= 100
-typedef struct -{ - char dummy; +/* This class seems to be 80 bytes big on x86-64, judging by the addresses passed in to + StructuredTaskCollection__RunAndWait */ +typedef struct UnrealizedChore +{ + void *unk1; + void (__cdecl *callback)(struct UnrealizedChore *this, void *unk); + void *unk2; + void *unk3; + void *unk4; + void *unk5; + void *unk6; + void *unk7; + void *unk8; + void *unk9; } UnrealizedChore;
+typedef struct StructuredTaskCollectionChoresEntry +{ + struct StructuredTaskCollectionChoresEntry *next; + UnrealizedChore *chore; + TP_WORK *work; + volatile LONG *waiting_on_ptr; +} StructuredTaskCollectionChoresEntry; + typedef struct { - char dummy; + void *unk1; + unsigned int unk2; + void *unk3; + StructuredTaskCollectionChoresEntry *volatile unk_chores; + unsigned int count; + unsigned int unk5; + void *unk6; } StructuredTaskCollection;
#endif /* _MSVCR_VER >= 100 */ @@ -1757,11 +1784,125 @@ bool __thiscall SpinWait__SpinOnce(SpinWait *this)
#if _MSVCR_VER >= 100
+static void CALLBACK StructuredTaskCollection_threadpool_cb_finally(BOOL normal, void *data) +{ + StructuredTaskCollectionChoresEntry *entry = data; + + TRACE("(%u %p)\n", normal, data); + + if (entry->waiting_on_ptr && InterlockedDecrement(entry->waiting_on_ptr) == 0) + RtlWakeAddressSingle((void*)entry->waiting_on_ptr); +} + +static inline void StructuredTaskCollection_run_chore(UnrealizedChore *chore, void* unk) +{ + if (chore->callback) + chore->callback(chore, unk); +} + +static void WINAPI StructuredTaskCollection_threadpool_cb(TP_CALLBACK_INSTANCE *inst, void *data, TP_WORK *work) +{ + StructuredTaskCollectionChoresEntry *entry = data; + + TRACE("(%p %p)\n", inst, data); + + __TRY + { + StructuredTaskCollection_run_chore(entry->chore, NULL); + } + __FINALLY_CTX(StructuredTaskCollection_threadpool_cb_finally, data) +} + +/* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z */ +DEFINE_THISCALL_WRAPPER(StructuredTaskCollection__RunAndWait, 8) +/*enum Concurrency::details::_TaskCollectionStatus*/int __thiscall StructuredTaskCollection__RunAndWait(StructuredTaskCollection *this, UnrealizedChore *chore) +{ + StructuredTaskCollectionChoresEntry *chores, *entry, *next; + LONG total_count = 0, created_count = 0; + TP_POOL *tpool = NULL; + TP_CALLBACK_ENVIRON cbenv; + volatile LONG waiting_on = 0; + int ret = 1; + LONG val; + + TRACE("(%p %p)\n", this, chore); + + chores = InterlockedExchangePointer((void *volatile *)&this->unk_chores, NULL); + this->count = 0; + + if (!chores) + return ret; + + for (entry = chores; entry; entry = entry->next) + total_count++; + + tpool = CreateThreadpool(NULL); + if (!tpool || !SetThreadpoolThreadMinimum(tpool, total_count)) + goto done; + SetThreadpoolThreadMaximum(tpool, total_count); + + memset(&cbenv, 0, sizeof(cbenv)); + cbenv.Version = 1; + cbenv.Pool = tpool; + + for (entry = chores; entry; entry = entry->next) + { + entry->waiting_on_ptr = &waiting_on; + entry->work = CreateThreadpoolWork(StructuredTaskCollection_threadpool_cb, entry, &cbenv); + if (!entry->work) + { + ret = 0; + goto done; + } + created_count++; + } + + InterlockedExchange(&waiting_on, created_count); + for (entry = chores; entry; entry = entry->next) + SubmitThreadpoolWork(entry->work); + + if (chore) + StructuredTaskCollection_run_chore(chore, NULL); + + TRACE("waiting on %u workers\n", created_count); + + while ((val = InterlockedCompareExchange(&waiting_on, 0, 0))) + RtlWaitOnAddress((void*)&waiting_on, (void*)&val, sizeof(waiting_on), NULL); + +done: + for (entry = chores; entry; entry = next) + { + if (created_count > 0) + { + CloseThreadpoolWork(entry->work); + created_count--; + } + next = entry->next; + operator_delete(entry); + } + + if (tpool) CloseThreadpool(tpool); + + return ret; +} + /* ?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z */ DEFINE_THISCALL_WRAPPER(StructuredTaskCollection__Schedule, 8) void __thiscall StructuredTaskCollection__Schedule(StructuredTaskCollection *this, UnrealizedChore *chore) { - FIXME("(%p %p): stub!\n", this, chore); + StructuredTaskCollectionChoresEntry *entry, *next; + + TRACE("(%p %p)\n", this, chore); + + entry = operator_new(sizeof(StructuredTaskCollectionChoresEntry)); + entry->chore = chore; + do + { + next = this->unk_chores; + entry->next = next; + } + while (InterlockedCompareExchangePointer((void *volatile *)&this->unk_chores, entry, next) != next); + this->count++; }
#endif /* _MSVCR_VER >= 100 */
Hi Torge,
On 4/11/22 16:30, Torge Matthies wrote: ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z
@ stub -arch=i386 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z -@ stub -arch=win64 ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z +@ thiscall -arch=win64
Please also add arm and i386 exports.
+DEFINE_THISCALL_WRAPPER(StructuredTaskCollection__RunAndWait, 8) +/*enum Concurrency::details::_TaskCollectionStatus*/int __thiscall StructuredTaskCollection__RunAndWait(StructuredTaskCollection *this, UnrealizedChore *chore) +{
- StructuredTaskCollectionChoresEntry *chores, *entry, *next;
- LONG total_count = 0, created_count = 0;
- TP_POOL *tpool = NULL;
- TP_CALLBACK_ENVIRON cbenv;
- volatile LONG waiting_on = 0;
- int ret = 1;
- LONG val;
- TRACE("(%p %p)\n", this, chore);
- chores = InterlockedExchangePointer((void *volatile *)&this->unk_chores, NULL);
- this->count = 0;
- if (!chores)
return ret;
- for (entry = chores; entry; entry = entry->next)
total_count++;
- tpool = CreateThreadpool(NULL);
- if (!tpool || !SetThreadpoolThreadMinimum(tpool, total_count))
goto done;
- SetThreadpoolThreadMaximum(tpool, total_count);
- memset(&cbenv, 0, sizeof(cbenv));
- cbenv.Version = 1;
- cbenv.Pool = tpool;
- for (entry = chores; entry; entry = entry->next)
- {
entry->waiting_on_ptr = &waiting_on;
entry->work = CreateThreadpoolWork(StructuredTaskCollection_threadpool_cb, entry, &cbenv);
if (!entry->work)
{
ret = 0;
goto done;
}
created_count++;
- }
- InterlockedExchange(&waiting_on, created_count);
- for (entry = chores; entry; entry = entry->next)
SubmitThreadpoolWork(entry->work);
- if (chore)
StructuredTaskCollection_run_chore(chore, NULL);
- TRACE("waiting on %u workers\n", created_count);
- while ((val = InterlockedCompareExchange(&waiting_on, 0, 0)))
RtlWaitOnAddress((void*)&waiting_on, (void*)&val, sizeof(waiting_on), NULL);
+done:
- for (entry = chores; entry; entry = next)
- {
if (created_count > 0)
{
CloseThreadpoolWork(entry->work);
created_count--;
}
next = entry->next;
operator_delete(entry);
- }
- if (tpool) CloseThreadpool(tpool);
- return ret;
+}Please add tests - it's not really possible to implement it correctly
(or review the patch) without them. AFAICS the chores should be executed in LIFO order (waiting for previous task to complete).
Thanks, Piotr
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- v3 -> v4: Added freeing of the chore list.
dlls/concrt140/concrt140.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcrt/concurrency.c | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/dlls/concrt140/concrt140.spec b/dlls/concrt140/concrt140.spec index 6b5ab7a5511..431d6406d37 100644 --- a/dlls/concrt140/concrt140.spec +++ b/dlls/concrt140/concrt140.spec @@ -269,7 +269,7 @@ @ stub -arch=win64 ??1_SpinLock@details@Concurrency@@QEAA@XZ @ stub -arch=arm ??1_StructuredTaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??1_StructuredTaskCollection@details@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1_StructuredTaskCollection@details@Concurrency@@QEAA@XZ +@ thiscall -arch=win64 ??1_StructuredTaskCollection@details@Concurrency@@QEAA@XZ(ptr) StructuredTaskCollection_dtor @ stub -arch=arm ??1_TaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??1_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??1_TaskCollection@details@Concurrency@@QEAA@XZ diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 46e16257b5d..8a5d20036ec 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -291,7 +291,7 @@ @ stub -arch=i386 ??1_SpinLock@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??1_SpinLock@details@Concurrency@@QEAA@XZ @ stub -arch=i386 ??1_StructuredTaskCollection@details@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1_StructuredTaskCollection@details@Concurrency@@QEAA@XZ +@ thiscall -arch=win64 ??1_StructuredTaskCollection@details@Concurrency@@QEAA@XZ(ptr) StructuredTaskCollection_dtor @ stub -arch=arm ??1_TaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??1_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??1_TaskCollection@details@Concurrency@@QEAA@XZ diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 2da39745f93..98baf253adf 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -1782,6 +1782,25 @@ bool __thiscall SpinWait__SpinOnce(SpinWait *this) } }
+#if _MSVCR_VER >= 120 + +/* ??1_StructuredTaskCollection@details@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(StructuredTaskCollection_dtor, 4) +void __thiscall StructuredTaskCollection_dtor(StructuredTaskCollection *this) +{ + StructuredTaskCollectionChoresEntry *entry, *next; + + TRACE("(%p)\n", this); + + for (entry = this->unk_chores; entry; entry = next) + { + next = entry->next; + operator_delete(entry); + } +} + +#endif /* _MSVCR_VER >= 120 */ + #if _MSVCR_VER >= 100
static void CALLBACK StructuredTaskCollection_threadpool_cb_finally(BOOL normal, void *data)