[PATCH v4 2/3] msvcr100: Implement _StructuredTaskCollection::_RunAndWait and _Schedule.
Torge Matthies
tmatthies at codeweavers.com
Mon Apr 11 09:30:07 CDT 2022
Signed-off-by: Torge Matthies <tmatthies at 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 at Concurrency@@IEAAXXZ(ptr) SpinWait__Reset
@ stub -arch=arm ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QAA?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=i386 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QAG?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
-@ stub -arch=win64 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z
+@ thiscall -arch=win64 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z(ptr ptr) StructuredTaskCollection__RunAndWait
@ stub -arch=arm ?_RunAndWait at _TaskCollection@details at Concurrency@@QAA?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=i386 ?_RunAndWait at _TaskCollection@details at Concurrency@@QAG?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=win64 ?_RunAndWait at _TaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 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 at Concurrency@@IAEXXZ(ptr) SpinWait__Reset
@ cdecl -arch=win64 ?_Reset@?$_SpinWait@$0A@@details at Concurrency@@IEAAXXZ(ptr) SpinWait__Reset
@ stub -arch=win32 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QAG?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
-@ stub -arch=win64 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z
+@ thiscall -arch=win64 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z(ptr ptr) StructuredTaskCollection__RunAndWait
@ stub -arch=win32 ?_RunAndWait at _TaskCollection@details at Concurrency@@QAG?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=win64 ?_RunAndWait at _TaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z
@ stub -arch=win32 ?_Schedule at _StructuredTaskCollection@details at Concurrency@@QAEXPAV_UnrealizedChore at 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 at Concurrency@@IEAAXXZ(ptr) SpinWait__Reset
@ stub -arch=arm ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QAA?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=i386 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QAG?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
-@ stub -arch=win64 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z
+@ thiscall -arch=win64 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z(ptr ptr) StructuredTaskCollection__RunAndWait
@ stub -arch=arm ?_RunAndWait at _TaskCollection@details at Concurrency@@QAA?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=i386 ?_RunAndWait at _TaskCollection@details at Concurrency@@QAG?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=win64 ?_RunAndWait at _TaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 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 at Concurrency@@IEAAXXZ(ptr) SpinWait__Reset
@ stub -arch=arm ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QAA?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=i386 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QAG?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
-@ stub -arch=win64 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z
+@ thiscall -arch=win64 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z(ptr ptr) StructuredTaskCollection__RunAndWait
@ stub -arch=arm ?_RunAndWait at _TaskCollection@details at Concurrency@@QAA?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=i386 ?_RunAndWait at _TaskCollection@details at Concurrency@@QAG?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=win64 ?_RunAndWait at _TaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 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 at Concurrency@@IEAAXXZ(ptr) msvcr120.?_Reset@?$_SpinWait@$0A@@details at Concurrency@@IEAAXXZ
@ stub -arch=arm ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QAA?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=i386 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QAG?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
-@ stub -arch=win64 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z
+@ thiscall -arch=win64 ?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z(ptr ptr) msvcr120.?_RunAndWait at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 23@@Z
@ stub -arch=arm ?_RunAndWait at _TaskCollection@details at Concurrency@@QAA?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=i386 ?_RunAndWait at _TaskCollection@details at Concurrency@@QAG?AW4_TaskCollectionStatus at 23@PAV_UnrealizedChore at 23@@Z
@ stub -arch=win64 ?_RunAndWait at _TaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 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 at _StructuredTaskCollection@details at Concurrency@@QEAA?AW4_TaskCollectionStatus at 23@PEAV_UnrealizedChore at 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 at _StructuredTaskCollection@details at Concurrency@@QEAAXPEAV_UnrealizedChore at 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 */
--
2.35.1
More information about the wine-devel
mailing list