Based on !2524.
This adds the remaining stubs needed for Crazy Machines 3 to work and decode preview images correctly in online mode.
-- v3: msvcr110: Implement _Context::_IsSynchronouslyBlocked. msvcr110: Add _Context::_IsSynchronouslyBlocked stub. msvcr110: Add _Cancellation_beacon::_Cancellation_beacon_dtor stub. msvcr110: Add _Cancellation_beacon::_Cancellation_beacon_ctor stub.
From: Torge Matthies tmatthies@codeweavers.com
The pointer is needed for Crazy Machines 3 to not crash.
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/msvcr110/msvcr110.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/concurrency.c | 19 +++++++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 1032c9e4c7a..7d8b32da0ab 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -19,7 +19,7 @@ @ 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=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 diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index ca11ea4b49d..6e2bda818a7 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -16,7 +16,7 @@ @ 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=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 diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index aad6ece8acc..e715076eb4f 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -14,7 +14,7 @@ @ 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=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 diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index d148aadd13a..a88ca7feda9 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -309,6 +309,10 @@ typedef struct cv_queue { LONG expired; } cv_queue;
+typedef struct { + void *unknown; +} _Cancellation_beacon; + typedef struct { /* cv_queue structure is not binary compatible */ cv_queue *queue; @@ -2860,6 +2864,21 @@ int __cdecl event_wait_for_multiple(event **events, size_t count, bool wait_all,
#if _MSVCR_VER >= 110
+struct { + void *unk; +} _Cancellation_beacon_unknown = { + 0x0 +}; + +/* ??0_Cancellation_beacon@details@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(_Cancellation_beacon_ctor, 4) +_Cancellation_beacon* __thiscall _Cancellation_beacon_ctor(_Cancellation_beacon *this) +{ + FIXME("(%p): stub!\n", this); + this->unknown = &_Cancellation_beacon_unknown; + return this; +} + /* ??0_Condition_variable@details@Concurrency@@QAE@XZ */ /* ??0_Condition_variable@details@Concurrency@@QEAA@XZ */ DEFINE_THISCALL_WRAPPER(_Condition_variable_ctor, 4)
From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/msvcr110/msvcr110.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr120_app/msvcr120_app.spec | 2 +- dlls/msvcrt/concurrency.c | 7 +++++++ 4 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 7d8b32da0ab..9589f5bfb95 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -277,7 +277,7 @@ @ 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=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 6e2bda818a7..5b7ab406206 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -271,7 +271,7 @@ @ 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=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 e715076eb4f..b59f78cbde2 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -269,7 +269,7 @@ @ 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=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 a88ca7feda9..da29f478b1a 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -2879,6 +2879,13 @@ _Cancellation_beacon* __thiscall _Cancellation_beacon_ctor(_Cancellation_beacon return this; }
+/* ??1_Cancellation_beacon@details@Concurrency@@QEAA@XZ */ +DEFINE_THISCALL_WRAPPER(_Cancellation_beacon_dtor, 4) +void __thiscall _Cancellation_beacon_dtor(_Cancellation_beacon *this) +{ + FIXME("(%p): stub!\n", this); +} + /* ??0_Condition_variable@details@Concurrency@@QAE@XZ */ /* ??0_Condition_variable@details@Concurrency@@QEAA@XZ */ DEFINE_THISCALL_WRAPPER(_Condition_variable_ctor, 4)
From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/msvcr110/msvcr110.spec | 6 +++--- dlls/msvcr120/msvcr120.spec | 6 +++--- dlls/msvcr120_app/msvcr120_app.spec | 6 +++--- dlls/msvcrt/concurrency.c | 7 +++++++ 4 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 9589f5bfb95..f9f4a2dc9a7 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -550,9 +550,9 @@ @ stub -arch=arm ?_IsCanceling@_TaskCollection@details@Concurrency@@QAA_NXZ @ stub -arch=i386 ?_IsCanceling@_TaskCollection@details@Concurrency@@QAE_NXZ @ stub -arch=win64 ?_IsCanceling@_TaskCollection@details@Concurrency@@QEAA_NXZ -@ stub -arch=arm ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBA_NXZ -@ stub -arch=i386 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBE_NXZ -@ stub -arch=win64 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QEBA_NXZ +@ cdecl -arch=arm ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBA_NXZ(ptr) _Context_IsSynchronouslyBlocked +@ thiscall -arch=i386 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBE_NXZ(ptr) _Context_IsSynchronouslyBlocked +@ cdecl -arch=win64 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QEBA_NXZ(ptr) _Context_IsSynchronouslyBlocked @ stub -arch=win32 ?_Name_base@type_info@@CAPBDPBV1@PAU__type_info_node@@@Z @ stub -arch=win64 ?_Name_base@type_info@@CAPEBDPEBV1@PEAU__type_info_node@@@Z @ stub -arch=win32 ?_Name_base_internal@type_info@@CAPBDPBV1@PAU__type_info_node@@@Z diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 5b7ab406206..768eca16d3c 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -541,9 +541,9 @@ @ stub -arch=arm ?_IsCanceling@_TaskCollection@details@Concurrency@@QAA_NXZ @ stub -arch=i386 ?_IsCanceling@_TaskCollection@details@Concurrency@@QAE_NXZ @ stub -arch=win64 ?_IsCanceling@_TaskCollection@details@Concurrency@@QEAA_NXZ -@ stub -arch=arm ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBA_NXZ -@ stub -arch=i386 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBE_NXZ -@ stub -arch=win64 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QEBA_NXZ +@ cdecl -arch=arm ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBA_NXZ(ptr) _Context_IsSynchronouslyBlocked +@ thiscall -arch=i386 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBE_NXZ(ptr) _Context_IsSynchronouslyBlocked +@ cdecl -arch=win64 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QEBA_NXZ(ptr) _Context_IsSynchronouslyBlocked @ stub -arch=win32 ?_Name_base@type_info@@CAPBDPBV1@PAU__type_info_node@@@Z @ stub -arch=win64 ?_Name_base@type_info@@CAPEBDPEBV1@PEAU__type_info_node@@@Z @ stub -arch=win32 ?_Name_base_internal@type_info@@CAPBDPBV1@PAU__type_info_node@@@Z diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index b59f78cbde2..641612af822 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -538,9 +538,9 @@ @ stub -arch=arm ?_IsCanceling@_TaskCollection@details@Concurrency@@QAA_NXZ @ stub -arch=i386 ?_IsCanceling@_TaskCollection@details@Concurrency@@QAE_NXZ @ stub -arch=win64 ?_IsCanceling@_TaskCollection@details@Concurrency@@QEAA_NXZ -@ stub -arch=arm ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBA_NXZ -@ stub -arch=i386 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBE_NXZ -@ stub -arch=win64 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QEBA_NXZ +@ cdecl -arch=arm ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBA_NXZ(ptr) msvcr120.?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBA_NXZ +@ thiscall -arch=i386 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBE_NXZ(ptr) msvcr120.?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QBE_NXZ +@ cdecl -arch=win64 ?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QEBA_NXZ(ptr) msvcr120.?_IsSynchronouslyBlocked@_Context@details@Concurrency@@QEBA_NXZ @ stub -arch=win32 ?_Name_base@type_info@@CAPBDPBV1@PAU__type_info_node@@@Z @ stub -arch=win64 ?_Name_base@type_info@@CAPEBDPEBV1@PEAU__type_info_node@@@Z @ stub -arch=win32 ?_Name_base_internal@type_info@@CAPBDPBV1@PAU__type_info_node@@@Z diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index da29f478b1a..8388150e6f7 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -879,6 +879,13 @@ _Context *__cdecl _Context__CurrentContext(_Context *ret) ret->context = Context_CurrentContext(); return ret; } + +DEFINE_THISCALL_WRAPPER(_Context_IsSynchronouslyBlocked, 4) +BOOL __thiscall _Context_IsSynchronouslyBlocked(const _Context *this) +{ + TRACE("(%p)\n", this); + return FALSE; +} #endif
DEFINE_THISCALL_WRAPPER(ExternalContextBase_GetId, 4)
From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/msvcrt/concurrency.c | 225 +++++++++++++++++++++++++------------- 1 file changed, 150 insertions(+), 75 deletions(-)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 8388150e6f7..65ec5813f43 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -68,6 +68,8 @@ typedef struct { unsigned int, (const Context*), (this)) #define call_Context_GetScheduleGroupId(this) CALL_VTBL_FUNC(this, 8, \ unsigned int, (const Context*), (this)) +#define call_Context_IsSynchronouslyBlocked(this) CALL_VTBL_FUNC(this, 12, \ + bool, (const Context*), (this)) #define call_Context_dtor(this, flags) CALL_VTBL_FUNC(this, 20, \ Context*, (Context*, unsigned int), (this, flags))
@@ -96,6 +98,7 @@ typedef struct { struct scheduler_list scheduler; unsigned int id; union allocator_cache_entry *allocator_cache[8]; + BOOL sync_blocked; } ExternalContextBase; extern const vtable_ptr ExternalContextBase_vtable; static void ExternalContextBase_ctor(ExternalContextBase*); @@ -884,7 +887,7 @@ DEFINE_THISCALL_WRAPPER(_Context_IsSynchronouslyBlocked, 4) BOOL __thiscall _Context_IsSynchronouslyBlocked(const _Context *this) { TRACE("(%p)\n", this); - return FALSE; + return call_Context_IsSynchronouslyBlocked(this->context); } #endif
@@ -919,7 +922,7 @@ DEFINE_THISCALL_WRAPPER(ExternalContextBase_IsSynchronouslyBlocked, 4) bool __thiscall ExternalContextBase_IsSynchronouslyBlocked(const ExternalContextBase *this) { FIXME("(%p)->() stub\n", this); - return FALSE; + return this->sync_blocked; }
static void remove_scheduled_chores(Scheduler *scheduler, const ExternalContextBase *context) @@ -995,6 +998,7 @@ static void ExternalContextBase_ctor(ExternalContextBase *this) memset(this, 0, sizeof(*this)); this->context.vtable = &ExternalContextBase_vtable; this->id = InterlockedIncrement(&context_id); + this->sync_blocked = FALSE;
create_default_scheduler(); this->scheduler.scheduler = &default_scheduler->scheduler; @@ -2232,6 +2236,31 @@ void __thiscall _StructuredTaskCollection__Schedule( } }
+static inline void context_sync_block(Context *ctx) +{ + ExternalContextBase *context = (ExternalContextBase*)ctx; + if (context->context.vtable == &ExternalContextBase_vtable) + context->sync_blocked = TRUE; +} + +static void CALLBACK context_sync_unblock(BOOL normal, void *data) +{ + ExternalContextBase *context = data; + if (context->context.vtable == &ExternalContextBase_vtable) + context->sync_blocked = FALSE; +} + +#define SYNCHRONOUSLY_BLOCKED_START(ctx) \ + do { Context *__ctx = (Context*)(ctx); \ + __TRY { \ + context_sync_block(__ctx); \ + do { + +#define SYNCHRONOUSLY_BLOCKED_END() \ + } while (0); \ + } __FINALLY_CTX(context_sync_unblock, __ctx) \ + } while (0) + static void CALLBACK exception_ptr_rethrow_finally(BOOL normal, void *data) { exception_ptr *ep = data; @@ -2270,9 +2299,11 @@ _TaskCollectionStatus __stdcall _StructuredTaskCollection__RunAndWait( } }
- expected = this->count ? this->count : FINISHED_INITIAL; - while ((val = this->finished) != expected) - RtlWaitOnAddress((LONG*)&this->finished, &val, sizeof(val), NULL); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + expected = this->count ? this->count : FINISHED_INITIAL; + while ((val = this->finished) != expected) + RtlWaitOnAddress((LONG*)&this->finished, &val, sizeof(val), NULL); + } SYNCHRONOUSLY_BLOCKED_END();
this->finished = 0; this->count = 0; @@ -2378,12 +2409,16 @@ static inline void cs_lock(critical_section *cs, cs_queue *q) last = InterlockedExchangePointer(&cs->tail, q); if(last) { last->next = q; - NtWaitForKeyedEvent(keyed_event, q, 0, NULL); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + NtWaitForKeyedEvent(keyed_event, q, 0, NULL); + } SYNCHRONOUSLY_BLOCKED_END(); }
cs_set_head(cs, q); if(InterlockedCompareExchangePointer(&cs->tail, &cs->unk_active, q) != q) { - spin_wait_for_next_cs(q); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + spin_wait_for_next_cs(q); + } SYNCHRONOUSLY_BLOCKED_END(); cs->unk_active.next = q->next; } } @@ -2415,7 +2450,9 @@ bool __thiscall critical_section_try_lock(critical_section *this) if(!InterlockedCompareExchangePointer(&this->tail, &q, NULL)) { cs_set_head(this, &q); if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, &q) != &q) { - spin_wait_for_next_cs(&q); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + spin_wait_for_next_cs(&q); + } SYNCHRONOUSLY_BLOCKED_END(); this->unk_active.next = q.next; } return TRUE; @@ -2428,34 +2465,40 @@ bool __thiscall critical_section_try_lock(critical_section *this) DEFINE_THISCALL_WRAPPER(critical_section_unlock, 4) void __thiscall critical_section_unlock(critical_section *this) { + BOOL skip_release = FALSE; + TRACE("(%p)\n", this);
this->unk_thread_id = 0; this->head = NULL; if(InterlockedCompareExchangePointer(&this->tail, NULL, &this->unk_active) == &this->unk_active) return; - spin_wait_for_next_cs(&this->unk_active); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + spin_wait_for_next_cs(&this->unk_active);
#if _MSVCR_VER >= 110 - while(1) { - cs_queue *next; + while(1) { + cs_queue *next;
- if(!InterlockedExchange(&this->unk_active.next->free, TRUE)) - break; + if(!InterlockedExchange(&this->unk_active.next->free, TRUE)) + break; + + next = this->unk_active.next; + if(InterlockedCompareExchangePointer(&this->tail, NULL, next) == next) { + HeapFree(GetProcessHeap(), 0, next); + skip_release = TRUE; + break; + } + spin_wait_for_next_cs(next);
- next = this->unk_active.next; - if(InterlockedCompareExchangePointer(&this->tail, NULL, next) == next) { + this->unk_active.next = next->next; HeapFree(GetProcessHeap(), 0, next); - return; } - spin_wait_for_next_cs(next); - - this->unk_active.next = next->next; - HeapFree(GetProcessHeap(), 0, next); - } #endif + } SYNCHRONOUSLY_BLOCKED_END();
- NtReleaseKeyedEvent(keyed_event, this->unk_active.next, 0, NULL); + if (!skip_release) + NtReleaseKeyedEvent(keyed_event, this->unk_active.next, 0, NULL); }
/* ?native_handle@critical_section@Concurrency@@QAEAAV12@XZ */ @@ -2475,6 +2518,7 @@ bool __thiscall critical_section_try_lock_for( critical_section *this, unsigned int timeout) { cs_queue *q, *last; + BOOL timed_out = FALSE;
TRACE("(%p %d)\n", this, timeout);
@@ -2487,32 +2531,39 @@ bool __thiscall critical_section_try_lock_for( if(!(q = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*q)))) return critical_section_try_lock(this);
- last = InterlockedExchangePointer(&this->tail, q); - if(last) { - LARGE_INTEGER to; - NTSTATUS status; - FILETIME ft; - - last->next = q; - GetSystemTimeAsFileTime(&ft); - to.QuadPart = ((LONGLONG)ft.dwHighDateTime << 32) + - ft.dwLowDateTime + (LONGLONG)timeout * TICKSPERMSEC; - status = NtWaitForKeyedEvent(keyed_event, q, 0, &to); - if(status == STATUS_TIMEOUT) { - if(!InterlockedExchange(&q->free, TRUE)) - return FALSE; - /* A thread has signaled the event and is block waiting. */ - /* We need to catch the event to wake the thread. */ - NtWaitForKeyedEvent(keyed_event, q, 0, NULL); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + last = InterlockedExchangePointer(&this->tail, q); + if(last) { + LARGE_INTEGER to; + NTSTATUS status; + FILETIME ft; + + last->next = q; + GetSystemTimeAsFileTime(&ft); + to.QuadPart = ((LONGLONG)ft.dwHighDateTime << 32) + + ft.dwLowDateTime + (LONGLONG)timeout * TICKSPERMSEC; + status = NtWaitForKeyedEvent(keyed_event, q, 0, &to); + if(status == STATUS_TIMEOUT) { + if(!InterlockedExchange(&q->free, TRUE)) { + timed_out = TRUE; + goto end; + } + /* A thread has signaled the event and is block waiting. */ + /* We need to catch the event to wake the thread. */ + NtWaitForKeyedEvent(keyed_event, q, 0, NULL); + } } - }
- cs_set_head(this, q); - if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, q) != q) { - spin_wait_for_next_cs(q); - this->unk_active.next = q->next; - } + cs_set_head(this, q); + if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, q) != q) { + spin_wait_for_next_cs(q); + this->unk_active.next = q->next; + } + end: + } SYNCHRONOUSLY_BLOCKED_END();
+ if (timed_out) + return FALSE; HeapFree(GetProcessHeap(), 0, q); return TRUE; } @@ -2749,10 +2800,11 @@ static size_t evt_wait(thread_wait *wait, event **events, int count, bool wait_a if(!evt_transition(&wait->signaled, EVT_RUNNING, EVT_WAITING)) return evt_end_wait(wait, events, count);
- status = NtWaitForKeyedEvent(keyed_event, wait, 0, evt_timeout(&ntto, timeout)); - - if(status && !evt_transition(&wait->signaled, EVT_WAITING, EVT_RUNNING)) - NtWaitForKeyedEvent(keyed_event, wait, 0, NULL); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + status = NtWaitForKeyedEvent(keyed_event, wait, 0, evt_timeout(&ntto, timeout)); + if(status && !evt_transition(&wait->signaled, EVT_WAITING, EVT_RUNNING)) + NtWaitForKeyedEvent(keyed_event, wait, 0, NULL); + } SYNCHRONOUSLY_BLOCKED_END();
return evt_end_wait(wait, events, count); } @@ -2939,8 +2991,10 @@ void __thiscall _Condition_variable_wait(_Condition_variable *this, critical_sec critical_section_unlock(&this->lock);
critical_section_unlock(cs); - while (q.next != CV_WAKE) - RtlWaitOnAddress(&q.next, &next, sizeof(next), NULL); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + while (q.next != CV_WAKE) + RtlWaitOnAddress(&q.next, &next, sizeof(next), NULL); + } SYNCHRONOUSLY_BLOCKED_END(); critical_section_lock(cs); }
@@ -2954,6 +3008,7 @@ bool __thiscall _Condition_variable_wait_for(_Condition_variable *this, NTSTATUS status; FILETIME ft; cv_queue *q, *next; + BOOL result = TRUE;
TRACE("(%p %p %d)\n", this, cs, timeout);
@@ -2967,23 +3022,24 @@ bool __thiscall _Condition_variable_wait_for(_Condition_variable *this,
critical_section_unlock(cs);
- GetSystemTimeAsFileTime(&ft); - to.QuadPart = ((LONGLONG)ft.dwHighDateTime << 32) + - ft.dwLowDateTime + (LONGLONG)timeout * TICKSPERMSEC; - while (q->next != CV_WAKE) { - status = RtlWaitOnAddress(&q->next, &next, sizeof(next), &to); - if(status == STATUS_TIMEOUT) { - if(!InterlockedExchange(&q->expired, TRUE)) { - critical_section_lock(cs); - return FALSE; + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + GetSystemTimeAsFileTime(&ft); + to.QuadPart = ((LONGLONG)ft.dwHighDateTime << 32) + + ft.dwLowDateTime + (LONGLONG)timeout * TICKSPERMSEC; + while (q->next != CV_WAKE) { + status = RtlWaitOnAddress(&q->next, &next, sizeof(next), &to); + if(status == STATUS_TIMEOUT) { + if(!InterlockedExchange(&q->expired, TRUE)) + result = FALSE; + break; } - break; } - } + } SYNCHRONOUSLY_BLOCKED_END();
- operator_delete(q); + if (result) + operator_delete(q); critical_section_lock(cs); - return TRUE; + return result; }
/* ?notify_one@_Condition_variable@details@Concurrency@@QAEXXZ */ @@ -3109,18 +3165,25 @@ void __thiscall reader_writer_lock_lock(reader_writer_lock *this) last = InterlockedExchangePointer((void**)&this->writer_tail, &q); if (last) { last->next = &q; - NtWaitForKeyedEvent(keyed_event, &q, 0, NULL); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + NtWaitForKeyedEvent(keyed_event, &q, 0, NULL); + } SYNCHRONOUSLY_BLOCKED_END(); } else { this->writer_head = &q; - if (InterlockedOr(&this->count, WRITER_WAITING)) - NtWaitForKeyedEvent(keyed_event, &q, 0, NULL); + if (InterlockedOr(&this->count, WRITER_WAITING)) { + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + NtWaitForKeyedEvent(keyed_event, &q, 0, NULL); + } SYNCHRONOUSLY_BLOCKED_END(); + } }
this->thread_id = GetCurrentThreadId(); this->writer_head = &this->active; this->active.next = NULL; if (InterlockedCompareExchangePointer((void**)&this->writer_tail, &this->active, &q) != &q) { - spin_wait_for_next_rwl(&q); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + spin_wait_for_next_rwl(&q); + } SYNCHRONOUSLY_BLOCKED_END(); this->active.next = q.next; } } @@ -3151,8 +3214,10 @@ void __thiscall reader_writer_lock_lock_read(reader_writer_lock *this) while (!((count = this->count) & WRITER_WAITING)) if (InterlockedCompareExchange(&this->count, count+1, count) == count) break;
- if (count & WRITER_WAITING) - NtWaitForKeyedEvent(keyed_event, &q, 0, NULL); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + if (count & WRITER_WAITING) + NtWaitForKeyedEvent(keyed_event, &q, 0, NULL); + } SYNCHRONOUSLY_BLOCKED_END();
head = InterlockedExchangePointer((void**)&this->reader_head, NULL); while(head && head != &q) { @@ -3162,7 +3227,9 @@ void __thiscall reader_writer_lock_lock_read(reader_writer_lock *this) head = next; } } else { - NtWaitForKeyedEvent(keyed_event, &q, 0, NULL); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + NtWaitForKeyedEvent(keyed_event, &q, 0, NULL); + } SYNCHRONOUSLY_BLOCKED_END(); } }
@@ -3186,7 +3253,9 @@ bool __thiscall reader_writer_lock_try_lock(reader_writer_lock *this) this->writer_head = &this->active; this->active.next = NULL; if (InterlockedCompareExchangePointer((void**)&this->writer_tail, &this->active, &q) != &q) { - spin_wait_for_next_rwl(&q); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + spin_wait_for_next_rwl(&q); + } SYNCHRONOUSLY_BLOCKED_END(); this->active.next = q.next; } return TRUE; @@ -3194,7 +3263,9 @@ bool __thiscall reader_writer_lock_try_lock(reader_writer_lock *this)
if (InterlockedCompareExchangePointer((void**)&this->writer_tail, NULL, &q) == &q) return FALSE; - spin_wait_for_next_rwl(&q); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + spin_wait_for_next_rwl(&q); + } SYNCHRONOUSLY_BLOCKED_END(); this->writer_head = q.next; if (!InterlockedOr(&this->count, WRITER_WAITING)) { this->thread_id = GetCurrentThreadId(); @@ -3330,7 +3401,9 @@ DEFINE_THISCALL_WRAPPER(_ReentrantBlockingLock__Acquire, 4) void __thiscall _ReentrantBlockingLock__Acquire(_ReentrantBlockingLock *this) { TRACE("(%p)\n", this); - EnterCriticalSection(&this->cs); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + EnterCriticalSection(&this->cs); + } SYNCHRONOUSLY_BLOCKED_END(); }
/* ?_Release@_ReentrantBlockingLock@details@Concurrency@@QAEXXZ */ @@ -3358,7 +3431,9 @@ void __cdecl Concurrency_wait(unsigned int time)
if (!once++) FIXME("(%d) stub!\n", time);
- Sleep(time); + SYNCHRONOUSLY_BLOCKED_START(get_current_context()) { + Sleep(time); + } SYNCHRONOUSLY_BLOCKED_END(); }
#if _MSVCR_VER>=110
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=131820
Your paranoid android.
=== debian11 (build log) ===
../wine/dlls/msvcrt/concurrency.c:2562:5: error: label at end of compound statement ../wine/dlls/msvcrt/concurrency.c:2562:5: error: label at end of compound statement ../wine/dlls/msvcrt/concurrency.c:2562:5: error: label at end of compound statement Task: The win32 Wine build failed
=== debian11b (build log) ===
../wine/dlls/msvcrt/concurrency.c:2562:5: error: label at end of compound statement ../wine/dlls/msvcrt/concurrency.c:2562:5: error: label at end of compound statement ../wine/dlls/msvcrt/concurrency.c:2562:5: error: label at end of compound statement Task: The wow64 Wine build failed
On Tue Mar 28 16:29:48 2023 +0000, Torge Matthies wrote:
That means I'll have to find all the places where out ConcRT implementations block and add code before and after that mark the context as blocked / not blocked. Not impossible but takes a while, is this really needed? What is this function used for, and can its use-cases be satisfied with a different stub implementation?
@piotr I added a commit that implements `_IsSynchronouslyBlocked` by marking the context as blocked wherever there is a blocking syscall that isn't expected to return quickly (as well as around some spinlocks if appropriate).