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)