From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/concurrency.c | 50 ++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 8 deletions(-)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index eb9e8f9ee32..395188c257d 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -103,6 +103,7 @@ typedef struct { unsigned int id; union allocator_cache_entry *allocator_cache[8]; LONG blocked; + struct _StructuredTaskCollection *task_collection; } ExternalContextBase; extern const vtable_ptr ExternalContextBase_vtable; static void ExternalContextBase_ctor(ExternalContextBase*); @@ -175,7 +176,7 @@ typedef struct } SpinWait;
#define FINISHED_INITIAL 0x80000000 -typedef struct +typedef struct _StructuredTaskCollection { void *unk1; unsigned int unk2; @@ -187,6 +188,8 @@ typedef struct void *event; } _StructuredTaskCollection;
+bool __thiscall _StructuredTaskCollection__IsCanceling(_StructuredTaskCollection*); + typedef enum { TASK_COLLECTION_SUCCESS = 1, @@ -851,7 +854,17 @@ void __cdecl Context__SpinYield(void) /* ?IsCurrentTaskCollectionCanceling@Context@Concurrency@@SA_NXZ */ bool __cdecl Context_IsCurrentTaskCollectionCanceling(void) { - FIXME("()\n"); + ExternalContextBase *ctx = (ExternalContextBase*)try_get_current_context(); + + TRACE("()\n"); + + if (ctx && ctx->context.vtable != &ExternalContextBase_vtable) { + ERR("unknown context set\n"); + return FALSE; + } + + if (ctx && ctx->task_collection) + return _StructuredTaskCollection__IsCanceling(ctx->task_collection); return FALSE; }
@@ -2166,23 +2179,44 @@ static LONG CALLBACK execute_chore_except(EXCEPTION_POINTERS *pexc, void *_data) return EXCEPTION_EXECUTE_HANDLER; }
+static void CALLBACK execute_chore_finally(BOOL normal, void *data) +{ + ExternalContextBase *ctx = (ExternalContextBase*)try_get_current_context(); + _StructuredTaskCollection *old_collection = data; + + if (ctx && ctx->context.vtable == &ExternalContextBase_vtable) + ctx->task_collection = old_collection; +} + static void execute_chore(_UnrealizedChore *chore, _StructuredTaskCollection *task_collection) { + ExternalContextBase *ctx = (ExternalContextBase*)try_get_current_context(); struct execute_chore_data data = { chore, task_collection }; + _StructuredTaskCollection *old_collection;
TRACE("(%p %p)\n", chore, task_collection);
- __TRY + if (ctx && ctx->context.vtable == &ExternalContextBase_vtable) { - if (!((ULONG_PTR)task_collection->exception & ~STRUCTURED_TASK_COLLECTION_STATUS_MASK) && - chore->chore_proc) - chore->chore_proc(chore); + old_collection = ctx->task_collection; + ctx->task_collection = task_collection; } - __EXCEPT_CTX(execute_chore_except, &data) + + __TRY { + __TRY + { + if (!((ULONG_PTR)task_collection->exception & ~STRUCTURED_TASK_COLLECTION_STATUS_MASK) && + chore->chore_proc) + chore->chore_proc(chore); + } + __EXCEPT_CTX(execute_chore_except, &data) + { + } + __ENDTRY } - __ENDTRY + __FINALLY_CTX(execute_chore_finally, old_collection) }
static void CALLBACK chore_wrapper_finally(BOOL normal, void *data)
From: Piotr Caban piotr@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54756 --- dlls/concrt140/concrt140.spec | 12 ++--- dlls/msvcr110/msvcr110.spec | 12 ++--- dlls/msvcr120/msvcr120.spec | 12 ++--- dlls/msvcr120_app/msvcr120_app.spec | 12 ++--- dlls/msvcrt/concurrency.c | 80 +++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 24 deletions(-)
diff --git a/dlls/concrt140/concrt140.spec b/dlls/concrt140/concrt140.spec index 6df2eb20c77..7ce3475df4e 100644 --- a/dlls/concrt140/concrt140.spec +++ b/dlls/concrt140/concrt140.spec @@ -12,9 +12,9 @@ @ cdecl -arch=arm ??0SchedulerPolicy@Concurrency@@QAA@XZ(ptr) SchedulerPolicy_ctor @ thiscall -arch=i386 ??0SchedulerPolicy@Concurrency@@QAE@XZ(ptr) SchedulerPolicy_ctor @ varargs -arch=win64 ??0SchedulerPolicy@Concurrency@@QEAA@_KZZ(ptr long) SchedulerPolicy_ctor_policies -@ stub -arch=arm ??0_Cancellation_beacon@details@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0_Cancellation_beacon@details@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0_Cancellation_beacon@details@Concurrency@@QAA@XZ(ptr) _Cancellation_beacon_ctor +@ thiscall -arch=i386 ??0_Cancellation_beacon@details@Concurrency@@QAE@XZ(ptr) _Cancellation_beacon_ctor +@ cdecl -arch=win64 ??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ(ptr) _Cancellation_beacon_ctor @ stub -arch=arm ??0_Concurrent_queue_base_v4@details@Concurrency@@IAA@I@Z @ thiscall -arch=i386 ??0_Concurrent_queue_base_v4@details@Concurrency@@IAE@I@Z(ptr long) _Concurrent_queue_base_v4_ctor @ cdecl -arch=win64 ??0_Concurrent_queue_base_v4@details@Concurrency@@IEAA@_K@Z(ptr long) _Concurrent_queue_base_v4_ctor @@ -237,9 +237,9 @@ @ cdecl -arch=arm ??1SchedulerPolicy@Concurrency@@QAA@XZ(ptr) SchedulerPolicy_dtor @ thiscall -arch=i386 ??1SchedulerPolicy@Concurrency@@QAE@XZ(ptr) SchedulerPolicy_dtor @ cdecl -arch=win64 ??1SchedulerPolicy@Concurrency@@QEAA@XZ(ptr) SchedulerPolicy_dtor -@ stub -arch=arm ??1_Cancellation_beacon@details@Concurrency@@QAA@XZ -@ stub -arch=i386 ??1_Cancellation_beacon@details@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??1_Cancellation_beacon@details@Concurrency@@QAA@XZ(ptr) _Cancellation_beacon_dtor +@ thiscall -arch=i386 ??1_Cancellation_beacon@details@Concurrency@@QAE@XZ(ptr) _Cancellation_beacon_dtor +@ cdecl -arch=win64 ??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ(ptr) _Cancellation_beacon_dtor @ stub -arch=arm ??1_Concurrent_queue_base_v4@details@Concurrency@@MAA@XZ @ thiscall -arch=i386 ??1_Concurrent_queue_base_v4@details@Concurrency@@MAE@XZ(ptr) _Concurrent_queue_base_v4_dtor @ cdecl -arch=win64 ??1_Concurrent_queue_base_v4@details@Concurrency@@MEAA@XZ(ptr) _Concurrent_queue_base_v4_dtor diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index da4e22960b9..1a216628780 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -17,9 +17,9 @@ @ stub -arch=arm ??0_CancellationTokenState@details@Concurrency@@AAA@XZ @ stub -arch=i386 ??0_CancellationTokenState@details@Concurrency@@AAE@XZ @ stub -arch=win64 ??0_CancellationTokenState@details@Concurrency@@AEAA@XZ -@ stub -arch=arm ??0_Cancellation_beacon@details@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0_Cancellation_beacon@details@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0_Cancellation_beacon@details@Concurrency@@QAA@XZ(ptr) _Cancellation_beacon_ctor +@ thiscall -arch=i386 ??0_Cancellation_beacon@details@Concurrency@@QAE@XZ(ptr) _Cancellation_beacon_ctor +@ cdecl -arch=win64 ??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ(ptr) _Cancellation_beacon_ctor @ cdecl -arch=arm ??0_Condition_variable@details@Concurrency@@QAA@XZ(ptr) _Condition_variable_ctor @ thiscall -arch=i386 ??0_Condition_variable@details@Concurrency@@QAE@XZ(ptr) _Condition_variable_ctor @ cdecl -arch=win64 ??0_Condition_variable@details@Concurrency@@QEAA@XZ(ptr) _Condition_variable_ctor @@ -275,9 +275,9 @@ @ stub -arch=arm ??1_CancellationTokenState@details@Concurrency@@UAA@XZ @ stub -arch=i386 ??1_CancellationTokenState@details@Concurrency@@UAE@XZ @ stub -arch=win64 ??1_CancellationTokenState@details@Concurrency@@UEAA@XZ -@ stub -arch=arm ??1_Cancellation_beacon@details@Concurrency@@QAA@XZ -@ stub -arch=i386 ??1_Cancellation_beacon@details@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??1_Cancellation_beacon@details@Concurrency@@QAA@XZ(ptr) _Cancellation_beacon_dtor +@ thiscall -arch=i386 ??1_Cancellation_beacon@details@Concurrency@@QAE@XZ(ptr) _Cancellation_beacon_dtor +@ cdecl -arch=win64 ??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ(ptr) _Cancellation_beacon_dtor @ cdecl -arch=arm ??1_Condition_variable@details@Concurrency@@QAA@XZ(ptr) _Condition_variable_dtor @ thiscall -arch=i386 ??1_Condition_variable@details@Concurrency@@QAE@XZ(ptr) _Condition_variable_dtor @ cdecl -arch=win64 ??1_Condition_variable@details@Concurrency@@QEAA@XZ(ptr) _Condition_variable_dtor diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 1eff4e82f61..b5707fb8232 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -14,9 +14,9 @@ @ cdecl -arch=arm ??0SchedulerPolicy@Concurrency@@QAA@XZ(ptr) SchedulerPolicy_ctor @ thiscall -arch=i386 ??0SchedulerPolicy@Concurrency@@QAE@XZ(ptr) SchedulerPolicy_ctor @ cdecl -arch=win64 ??0SchedulerPolicy@Concurrency@@QEAA@XZ(ptr) SchedulerPolicy_ctor -@ stub -arch=arm ??0_Cancellation_beacon@details@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0_Cancellation_beacon@details@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0_Cancellation_beacon@details@Concurrency@@QAA@XZ(ptr) _Cancellation_beacon_ctor +@ thiscall -arch=i386 ??0_Cancellation_beacon@details@Concurrency@@QAE@XZ(ptr) _Cancellation_beacon_ctor +@ cdecl -arch=win64 ??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ(ptr) _Cancellation_beacon_ctor @ cdecl -arch=arm ??0_Condition_variable@details@Concurrency@@QAA@XZ(ptr) _Condition_variable_ctor @ thiscall -arch=i386 ??0_Condition_variable@details@Concurrency@@QAE@XZ(ptr) _Condition_variable_ctor @ cdecl -arch=win64 ??0_Condition_variable@details@Concurrency@@QEAA@XZ(ptr) _Condition_variable_ctor @@ -269,9 +269,9 @@ @ cdecl -arch=arm ??1SchedulerPolicy@Concurrency@@QAA@XZ(ptr) SchedulerPolicy_dtor @ thiscall -arch=i386 ??1SchedulerPolicy@Concurrency@@QAE@XZ(ptr) SchedulerPolicy_dtor @ cdecl -arch=win64 ??1SchedulerPolicy@Concurrency@@QEAA@XZ(ptr) SchedulerPolicy_dtor -@ stub -arch=arm ??1_Cancellation_beacon@details@Concurrency@@QAA@XZ -@ stub -arch=i386 ??1_Cancellation_beacon@details@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??1_Cancellation_beacon@details@Concurrency@@QAA@XZ(ptr) _Cancellation_beacon_dtor +@ thiscall -arch=i386 ??1_Cancellation_beacon@details@Concurrency@@QAE@XZ(ptr) _Cancellation_beacon_dtor +@ cdecl -arch=win64 ??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ(ptr) _Cancellation_beacon_dtor @ cdecl -arch=arm ??1_Condition_variable@details@Concurrency@@QAA@XZ(ptr) _Condition_variable_dtor @ thiscall -arch=i386 ??1_Condition_variable@details@Concurrency@@QAE@XZ(ptr) _Condition_variable_dtor @ cdecl -arch=win64 ??1_Condition_variable@details@Concurrency@@QEAA@XZ(ptr) _Condition_variable_dtor diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index bb1d6914c40..74587d2c6db 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -12,9 +12,9 @@ @ cdecl -arch=arm ??0SchedulerPolicy@Concurrency@@QAA@XZ(ptr) msvcr120.??0SchedulerPolicy@Concurrency@@QAA@XZ @ thiscall -arch=i386 ??0SchedulerPolicy@Concurrency@@QAE@XZ(ptr) msvcr120.??0SchedulerPolicy@Concurrency@@QAE@XZ @ cdecl -arch=win64 ??0SchedulerPolicy@Concurrency@@QEAA@XZ(ptr) msvcr120.??0SchedulerPolicy@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0_Cancellation_beacon@details@Concurrency@@QAA@XZ -@ stub -arch=i386 ??0_Cancellation_beacon@details@Concurrency@@QAE@XZ -@ stub -arch=win64 ??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??0_Cancellation_beacon@details@Concurrency@@QAA@XZ(ptr) msvcr120.??0_Cancellation_beacon@details@Concurrency@@QAA@XZ +@ thiscall -arch=i386 ??0_Cancellation_beacon@details@Concurrency@@QAE@XZ(ptr) msvcr120.??0_Cancellation_beacon@details@Concurrency@@QAE@XZ +@ cdecl -arch=win64 ??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ(ptr) msvcr120.??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ @ cdecl -arch=arm ??0_Condition_variable@details@Concurrency@@QAA@XZ(ptr) msvcr120.??0_Condition_variable@details@Concurrency@@QAA@XZ @ thiscall -arch=i386 ??0_Condition_variable@details@Concurrency@@QAE@XZ(ptr) msvcr120.??0_Condition_variable@details@Concurrency@@QAE@XZ @ cdecl -arch=win64 ??0_Condition_variable@details@Concurrency@@QEAA@XZ(ptr) msvcr120.??0_Condition_variable@details@Concurrency@@QEAA@XZ @@ -267,9 +267,9 @@ @ cdecl -arch=arm ??1SchedulerPolicy@Concurrency@@QAA@XZ(ptr) msvcr120.??1SchedulerPolicy@Concurrency@@QAA@XZ @ thiscall -arch=i386 ??1SchedulerPolicy@Concurrency@@QAE@XZ(ptr) msvcr120.??1SchedulerPolicy@Concurrency@@QAE@XZ @ cdecl -arch=win64 ??1SchedulerPolicy@Concurrency@@QEAA@XZ(ptr) msvcr120.??1SchedulerPolicy@Concurrency@@QEAA@XZ -@ stub -arch=arm ??1_Cancellation_beacon@details@Concurrency@@QAA@XZ -@ stub -arch=i386 ??1_Cancellation_beacon@details@Concurrency@@QAE@XZ -@ stub -arch=win64 ??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ +@ cdecl -arch=arm ??1_Cancellation_beacon@details@Concurrency@@QAA@XZ(ptr) msvcr120.??1_Cancellation_beacon@details@Concurrency@@QAA@XZ +@ thiscall -arch=i386 ??1_Cancellation_beacon@details@Concurrency@@QAE@XZ(ptr) msvcr120.??1_Cancellation_beacon@details@Concurrency@@QAE@XZ +@ cdecl -arch=win64 ??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ(ptr) msvcr120.??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ @ cdecl -arch=arm ??1_Condition_variable@details@Concurrency@@QAA@XZ(ptr) msvcr120.??1_Condition_variable@details@Concurrency@@QAA@XZ @ thiscall -arch=i386 ??1_Condition_variable@details@Concurrency@@QAE@XZ(ptr) msvcr120.??1_Condition_variable@details@Concurrency@@QAE@XZ @ cdecl -arch=win64 ??1_Condition_variable@details@Concurrency@@QEAA@XZ(ptr) msvcr120.??1_Condition_variable@details@Concurrency@@QEAA@XZ diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 395188c257d..156789a35d6 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -97,6 +97,12 @@ struct scheduler_list { struct scheduler_list *next; };
+struct beacon { + bool cancelling; + struct list entry; + struct _StructuredTaskCollection *task_collection; +}; + typedef struct { Context context; struct scheduler_list scheduler; @@ -104,6 +110,8 @@ typedef struct { union allocator_cache_entry *allocator_cache[8]; LONG blocked; struct _StructuredTaskCollection *task_collection; + CRITICAL_SECTION beacons_cs; + struct list beacons; } ExternalContextBase; extern const vtable_ptr ExternalContextBase_vtable; static void ExternalContextBase_ctor(ExternalContextBase*); @@ -321,6 +329,10 @@ typedef struct cv_queue { LONG expired; } cv_queue;
+typedef struct { + struct beacon *beacon; +} _Cancellation_beacon; + typedef struct { /* cv_queue structure is not binary compatible */ cv_queue *queue; @@ -1078,6 +1090,10 @@ static void ExternalContextBase_dtor(ExternalContextBase *this) operator_delete(scheduler_cur); } } + + DeleteCriticalSection(&this->beacons_cs); + if (!list_empty(&this->beacons)) + ERR("beacons list is not empty - expect crash\n"); }
DEFINE_THISCALL_WRAPPER(ExternalContextBase_vector_dtor, 8) @@ -1107,6 +1123,8 @@ static void ExternalContextBase_ctor(ExternalContextBase *this) memset(this, 0, sizeof(*this)); this->context.vtable = &ExternalContextBase_vtable; this->id = InterlockedIncrement(&context_id); + InitializeCriticalSection(&this->beacons_cs); + list_init(&this->beacons);
create_default_scheduler(); this->scheduler.scheduler = &default_scheduler->scheduler; @@ -2100,6 +2118,7 @@ void __thiscall _StructuredTaskCollection__Cancel( ThreadScheduler *scheduler; void *prev_exception, *new_exception; struct scheduled_chore *sc, *next; + struct beacon *beacon; LONG removed = 0; LONG prev_finished, new_finished;
@@ -2122,6 +2141,13 @@ void __thiscall _StructuredTaskCollection__Cancel( &this->exception, new_exception, prev_exception)) != prev_exception);
+ EnterCriticalSection(&((ExternalContextBase*)this->context)->beacons_cs); + LIST_FOR_EACH_ENTRY(beacon, &((ExternalContextBase*)this->context)->beacons, struct beacon, entry) { + if (beacon->task_collection == this) + beacon->cancelling = TRUE; + } + LeaveCriticalSection(&((ExternalContextBase*)this->context)->beacons_cs); + EnterCriticalSection(&scheduler->cs); LIST_FOR_EACH_ENTRY_SAFE(sc, next, &scheduler->scheduled_chores, struct scheduled_chore, entry) { @@ -3036,6 +3062,60 @@ int __cdecl event_wait_for_multiple(event **events, size_t count, bool wait_all,
#if _MSVCR_VER >= 110
+/* ??0_Cancellation_beacon@details@Concurrency@@QAE@XZ */ +/* ??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(_Cancellation_beacon_ctor, 4) +_Cancellation_beacon* __thiscall _Cancellation_beacon_ctor(_Cancellation_beacon *this) +{ + ExternalContextBase *ctx = (ExternalContextBase*)get_current_context(); + _StructuredTaskCollection *task_collection = NULL; + struct beacon *beacon; + + TRACE("(%p)\n", this); + + if (ctx->context.vtable == &ExternalContextBase_vtable) { + task_collection = ctx->task_collection; + if (task_collection) + ctx = (ExternalContextBase*)task_collection->context; + } + + if (ctx->context.vtable != &ExternalContextBase_vtable) { + ERR("unknown context\n"); + return NULL; + } + + beacon = malloc(sizeof(*beacon)); + beacon->cancelling = Context_IsCurrentTaskCollectionCanceling(); + beacon->task_collection = task_collection; + + if (task_collection) { + EnterCriticalSection(&ctx->beacons_cs); + list_add_head(&ctx->beacons, &beacon->entry); + LeaveCriticalSection(&ctx->beacons_cs); + } + + this->beacon = beacon; + return this; +} + +/* ??1_Cancellation_beacon@details@Concurrency@@QAE@XZ */ +/* ??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(_Cancellation_beacon_dtor, 4) +void __thiscall _Cancellation_beacon_dtor(_Cancellation_beacon *this) +{ + TRACE("(%p)\n", this); + + if (this->beacon->task_collection) { + ExternalContextBase *ctx = (ExternalContextBase*)this->beacon->task_collection->context; + + EnterCriticalSection(&ctx->beacons_cs); + list_remove(&this->beacon->entry); + LeaveCriticalSection(&ctx->beacons_cs); + } + + free(this->beacon); +} + /* ??0_Condition_variable@details@Concurrency@@QAE@XZ */ /* ??0_Condition_variable@details@Concurrency@@QEAA@XZ */ DEFINE_THISCALL_WRAPPER(_Condition_variable_ctor, 4)
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcr120/tests/msvcr120.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index 838338c83f8..11a8594e749 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -1436,11 +1436,7 @@ static void test_StructuredTaskCollection(void) context = p_Context_CurrentContext();
memset(&task_coll, 0x55, sizeof(task_coll)); - if (!call_func2(p__StructuredTaskCollection_ctor, &task_coll, NULL)) - { - skip("_StructuredTaskCollection constructor not implemented\n"); - return; - } + call_func2(p__StructuredTaskCollection_ctor, &task_coll, NULL); todo_wine ok(task_coll.unk2 == 0x1fffffff, "_StructuredTaskCollection ctor set wrong unk2: 0x%x != 0x1fffffff\n", task_coll.unk2); ok(task_coll.unk3 == NULL,
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcr120/tests/msvcr120.c | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index 11a8594e749..d21e73244c2 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -183,6 +183,10 @@ typedef struct _UnrealizedChore void *unk[6]; } _UnrealizedChore;
+typedef struct { + MSVCRT_bool *cancelling; +} _Cancellation_beacon; + static char* (CDECL *p_setlocale)(int category, const char* locale); static struct MSVCRT_lconv* (CDECL *p_localeconv)(void); static size_t (CDECL *p_wcstombs_s)(size_t *ret, char* dest, size_t sz, const wchar_t* src, size_t max); @@ -255,6 +259,9 @@ static int (__stdcall *p__StructuredTaskCollection__RunAndWait)(_StructuredTaskC static void (__thiscall *p__StructuredTaskCollection__Cancel)(_StructuredTaskCollection*); static MSVCRT_bool (__thiscall *p__StructuredTaskCollection__IsCanceling)(_StructuredTaskCollection*);
+static _Cancellation_beacon* (__thiscall *p__Cancellation_beacon_ctor)(_Cancellation_beacon*); +static void (__thiscall *p__Cancellation_beacon_dtor)(_Cancellation_beacon*); + #define SETNOFAIL(x,y) x = (void*)GetProcAddress(module,y) #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
@@ -355,6 +362,10 @@ static BOOL init(void) "?notify_all@_Condition_variable@details@Concurrency@@QEAAXXZ"); SET(p_Context_CurrentContext, "?CurrentContext@Context@Concurrency@@SAPEAV12@XZ"); + SET(p__Cancellation_beacon_ctor, + "??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ"); + SET(p__Cancellation_beacon_dtor, + "??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ"); } else { #ifdef __arm__ SET(p__StructuredTaskCollection_ctor, @@ -399,6 +410,10 @@ static BOOL init(void) "?notify_one@_Condition_variable@details@Concurrency@@QAAXXZ"); SET(p__Condition_variable_notify_all, "?notify_all@_Condition_variable@details@Concurrency@@QAAXXZ"); + SET(p__Cancellation_beacon_ctor, + "??0_Cancellation_beacon@details@Concurrency@@QAA@XZ"); + SET(p__Cancellation_beacon_dtor, + "??1_Cancellation_beacon@details@Concurrency@@QAA@XZ"); #else SET(p__StructuredTaskCollection_ctor, "??0_StructuredTaskCollection@details@Concurrency@@QAE@PAV_CancellationTokenState@12@@Z"); @@ -442,6 +457,10 @@ static BOOL init(void) "?notify_one@_Condition_variable@details@Concurrency@@QAEXXZ"); SET(p__Condition_variable_notify_all, "?notify_all@_Condition_variable@details@Concurrency@@QAEXXZ"); + SET(p__Cancellation_beacon_ctor, + "??0_Cancellation_beacon@details@Concurrency@@QAE@XZ"); + SET(p__Cancellation_beacon_dtor, + "??1_Cancellation_beacon@details@Concurrency@@QAE@XZ"); #endif SET(p_Context_CurrentContext, "?CurrentContext@Context@Concurrency@@SAPAV12@XZ"); @@ -1366,6 +1385,7 @@ struct chore static void __cdecl chore_proc(_UnrealizedChore *_this) { struct chore *chore = CONTAINING_RECORD(_this, struct chore, chore); + _Cancellation_beacon beacon, beacon2;
if (chore->start_event) { @@ -1388,6 +1408,13 @@ static void __cdecl chore_proc(_UnrealizedChore *_this) p__StructuredTaskCollection__IsCanceling, chore->chore.task_collection); ok(!canceling, "Task is already canceling\n"); + + call_func1(p__Cancellation_beacon_ctor, &beacon); + ok(!*beacon.cancelling, "beacon signalled %x\n", *beacon.cancelling); + + call_func1(p__Cancellation_beacon_ctor, &beacon2); + ok(beacon.cancelling != beacon2.cancelling, "beacons point to the same data\n"); + ok(!*beacon.cancelling, "beacon signalled %x\n", *beacon.cancelling); }
if (!chore->wait_event) @@ -1412,6 +1439,15 @@ static void __cdecl chore_proc(_UnrealizedChore *_this) p__StructuredTaskCollection__IsCanceling, chore->chore.task_collection); ok(canceling, "Task is not canceling\n"); + + ok(*beacon.cancelling == 1, "beacon not signalled (%x)\n", *beacon.cancelling); + call_func1(p__Cancellation_beacon_dtor, &beacon); + ok(*beacon2.cancelling == 1, "beacon not signalled (%x)\n", *beacon2.cancelling); + call_func1(p__Cancellation_beacon_dtor, &beacon2); + + call_func1(p__Cancellation_beacon_ctor, &beacon); + ok(*beacon.cancelling == 1, "beacon not signalled (%x)\n", *beacon.cancelling); + call_func1(p__Cancellation_beacon_dtor, &beacon); } }
@@ -1426,6 +1462,7 @@ static void test_StructuredTaskCollection(void) HANDLE chore_start_evt, chore_evt1, chore_evt2; _StructuredTaskCollection task_coll; struct chore chore1, chore2; + _Cancellation_beacon beacon; DWORD main_thread_id; Context *context; int status; @@ -1585,13 +1622,20 @@ static void test_StructuredTaskCollection(void) ret = WaitForSingleObject(chore_evt1, 5000); ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", ret);
+ call_func1(p__Cancellation_beacon_ctor, &beacon); + ok(!*beacon.cancelling, "beacon signalled\n"); + call_func1(p__StructuredTaskCollection__Cancel, &task_coll); + ok(!*beacon.cancelling, "beacon signalled\n");
b = SetEvent(chore_evt2); ok(b, "SetEvent failed\n"); + ok(!*beacon.cancelling, "beacon signalled\n");
status = p__StructuredTaskCollection__RunAndWait(&task_coll, NULL); ok(status == 2, "_StructuredTaskCollection::_RunAndWait failed: %d\n", status); + ok(!*beacon.cancelling, "beacon signalled\n"); + call_func1(p__Cancellation_beacon_dtor, &beacon); call_func1(p__StructuredTaskCollection_dtor, &task_coll);
/* cancel task collection without scheduled tasks */
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcr120/tests/msvcr120.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index d21e73244c2..672be695c3d 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -251,6 +251,7 @@ static void (__thiscall *p__Condition_variable_notify_all)(_Condition_variable*)
static Context* (__cdecl *p_Context_CurrentContext)(void); static _Context* (__cdecl *p__Context__CurrentContext)(_Context*); +static MSVCRT_bool (__cdecl *p_Context_IsCurrentTaskCollectionCanceling)(void);
static _StructuredTaskCollection* (__thiscall *p__StructuredTaskCollection_ctor)(_StructuredTaskCollection*, void*); static void (__thiscall *p__StructuredTaskCollection_dtor)(_StructuredTaskCollection*); @@ -317,6 +318,7 @@ static BOOL init(void) SET(p__Context__CurrentContext, "?_CurrentContext@_Context@details@Concurrency@@SA?AV123@XZ"); SET(p_strcmp, "strcmp"); SET(p_strncmp, "strncmp"); + SET(p_Context_IsCurrentTaskCollectionCanceling, "?IsCurrentTaskCollectionCanceling@Context@Concurrency@@SA_NXZ"); if(sizeof(void*) == 8) { /* 64-bit initialization */ SET(p__StructuredTaskCollection_ctor, "??0_StructuredTaskCollection@details@Concurrency@@QEAA@PEAV_CancellationTokenState@12@@Z"); @@ -1409,6 +1411,9 @@ static void __cdecl chore_proc(_UnrealizedChore *_this) chore->chore.task_collection); ok(!canceling, "Task is already canceling\n");
+ ok(!p_Context_IsCurrentTaskCollectionCanceling(), + "IsCurrentTaskCollectionCanceling returned TRUE\n"); + call_func1(p__Cancellation_beacon_ctor, &beacon); ok(!*beacon.cancelling, "beacon signalled %x\n", *beacon.cancelling);
@@ -1440,6 +1445,9 @@ static void __cdecl chore_proc(_UnrealizedChore *_this) chore->chore.task_collection); ok(canceling, "Task is not canceling\n");
+ ok(p_Context_IsCurrentTaskCollectionCanceling(), + "IsCurrentTaskCollectionCanceling returned FALSE\n"); + ok(*beacon.cancelling == 1, "beacon not signalled (%x)\n", *beacon.cancelling); call_func1(p__Cancellation_beacon_dtor, &beacon); ok(*beacon2.cancelling == 1, "beacon not signalled (%x)\n", *beacon2.cancelling); @@ -1622,10 +1630,14 @@ static void test_StructuredTaskCollection(void) ret = WaitForSingleObject(chore_evt1, 5000); ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", ret);
+ ok(!p_Context_IsCurrentTaskCollectionCanceling(), + "IsCurrentTaskCollectionCanceling returned TRUE\n"); call_func1(p__Cancellation_beacon_ctor, &beacon); ok(!*beacon.cancelling, "beacon signalled\n");
call_func1(p__StructuredTaskCollection__Cancel, &task_coll); + ok(!p_Context_IsCurrentTaskCollectionCanceling(), + "IsCurrentTaskCollectionCanceling returned TRUE\n"); ok(!*beacon.cancelling, "beacon signalled\n");
b = SetEvent(chore_evt2);