From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcp90/msvcp90.h | 2 +- dlls/msvcrt/concurrency.c | 64 ++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 26 deletions(-)
diff --git a/dlls/msvcp90/msvcp90.h b/dlls/msvcp90/msvcp90.h index 5b77a8164e8..c9e8e05566c 100644 --- a/dlls/msvcp90/msvcp90.h +++ b/dlls/msvcp90/msvcp90.h @@ -47,7 +47,7 @@ typedef struct cs_queue { void *ctx; struct cs_queue *next; - LONG status; + LONG free; int unknown; } cs_queue;
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 66adef1fa6d..190d1f31c31 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -214,14 +214,12 @@ struct scheduled_chore { };
/* keep in sync with msvcp90/msvcp90.h */ -#define CS_UNLOCK 1 -#define CS_TIMEOUT 2 typedef struct cs_queue { Context *ctx; struct cs_queue *next; #if _MSVCR_VER >= 110 - LONG status; + LONG free; int unknown; #endif } cs_queue; @@ -2533,7 +2531,7 @@ void __thiscall critical_section_unlock(critical_section *this) while(1) { cs_queue *next;
- if(!InterlockedCompareExchange(&this->unk_active.next->status, CS_UNLOCK, 0)) + if(!InterlockedExchange(&this->unk_active.next->free, TRUE)) break;
next = this->unk_active.next; @@ -2572,12 +2570,40 @@ static void set_timeout(FILETIME *ft, unsigned int timeout) }
#if _MSVCR_VER >= 110 +struct timeout_unlock +{ + Context *ctx; + BOOL timed_out; +}; + static void WINAPI timeout_unlock(TP_CALLBACK_INSTANCE *instance, void *ctx, TP_TIMER *timer) { - cs_queue *q = ctx; + struct timeout_unlock *tu = ctx; + tu->timed_out = TRUE; + call_Context_Unblock(tu->ctx); +} + +/* returns TRUE if wait has timed out */ +static BOOL block_context_for(Context *ctx, unsigned int timeout) +{ + struct timeout_unlock tu = { ctx }; + TP_TIMER *tp_timer; + FILETIME ft; + + tp_timer = CreateThreadpoolTimer(timeout_unlock, &tu, NULL); + if(!tp_timer) { + FIXME("throw exception?\n"); + return TRUE; + } + set_timeout(&ft, timeout); + SetThreadpoolTimer(tp_timer, &ft, 0, 0); + + call_Context_Block(ctx);
- if(!InterlockedCompareExchange(&q->status, CS_TIMEOUT, 0)) - call_Context_Unblock(q->ctx); + SetThreadpoolTimer(tp_timer, NULL, 0, 0); + WaitForThreadpoolTimerCallbacks(tp_timer, TRUE); + CloseThreadpoolTimer(tp_timer); + return tu.timed_out; }
/* ?try_lock_for@critical_section@Concurrency@@QAE_NI@Z */ @@ -2603,27 +2629,15 @@ bool __thiscall critical_section_try_lock_for(
last = InterlockedExchangePointer(&this->tail, q); if(last) { - TP_TIMER *tp_timer; - FILETIME ft; - last->next = q;
- tp_timer = CreateThreadpoolTimer(timeout_unlock, q, NULL); - if(!tp_timer) { - FIXME("throw exception?\n"); - return FALSE; + if(block_context_for(q->ctx, timeout)) + { + if(!InterlockedExchange(&q->free, TRUE)) + return FALSE; + /* Context was unblocked because of timeout and unlock operation */ + call_Context_Block(ctx); } - set_timeout(&ft, timeout); - SetThreadpoolTimer(tp_timer, &ft, 0, 0); - - call_Context_Block(q->ctx); - - SetThreadpoolTimer(tp_timer, NULL, 0, 0); - WaitForThreadpoolTimerCallbacks(tp_timer, TRUE); - CloseThreadpoolTimer(tp_timer); - - if(q->status == CS_TIMEOUT) - return FALSE; }
cs_set_head(this, q);
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/concurrency.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 190d1f31c31..560159ee00d 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -2590,6 +2590,11 @@ static BOOL block_context_for(Context *ctx, unsigned int timeout) TP_TIMER *tp_timer; FILETIME ft;
+ if(timeout == COOPERATIVE_TIMEOUT_INFINITE) { + call_Context_Block(ctx); + return FALSE; + } + tp_timer = CreateThreadpoolTimer(timeout_unlock, &tu, NULL); if(!tp_timer) { FIXME("throw exception?\n");
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/concurrency.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 560159ee00d..aed911a52a3 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -2569,7 +2569,6 @@ static void set_timeout(FILETIME *ft, unsigned int timeout) ft->dwLowDateTime = to.QuadPart; }
-#if _MSVCR_VER >= 110 struct timeout_unlock { Context *ctx; @@ -2611,6 +2610,7 @@ static BOOL block_context_for(Context *ctx, unsigned int timeout) return tu.timed_out; }
+#if _MSVCR_VER >= 110 /* ?try_lock_for@critical_section@Concurrency@@QAE_NI@Z */ /* ?try_lock_for@critical_section@Concurrency@@QEAA_NI@Z */ DEFINE_THISCALL_WRAPPER(critical_section_try_lock_for, 8) @@ -3478,33 +3478,11 @@ bool __thiscall _ReentrantBlockingLock__TryAcquire(_ReentrantBlockingLock *this) return TryEnterCriticalSection(&this->cs); }
-static void WINAPI wait_timeout(TP_CALLBACK_INSTANCE *instance, void *arg, TP_TIMER *timer) -{ - Context *ctx = arg; - - call_Context_Unblock(ctx); -} - /* ?wait@Concurrency@@YAXI@Z */ void __cdecl Concurrency_wait(unsigned int time) { - Context *ctx = get_current_context(); - TP_TIMER *tp_timer; - FILETIME ft; - TRACE("(%d)\n", time); - - tp_timer = CreateThreadpoolTimer(wait_timeout, ctx, NULL); - if(!tp_timer) { - FIXME("throw exception?\n"); - Sleep(time); - return; - } - set_timeout(&ft, time); - SetThreadpoolTimer(tp_timer, &ft, 0, 0); - - call_Context_Block(ctx); - CloseThreadpoolTimer(tp_timer); + block_context_for(get_current_context(), time); }
#if _MSVCR_VER>=110
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/concurrency.c | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index aed911a52a3..b96e0cbda6f 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -2850,17 +2850,8 @@ static inline int evt_transition(void **state, void *from, void *to) return InterlockedCompareExchangePointer(state, to, from) == from; }
-static void WINAPI evt_timeout(TP_CALLBACK_INSTANCE *instance, void *ctx, TP_TIMER *timer) -{ - thread_wait *wait = ctx; - - if(evt_transition(&wait->signaled, EVT_WAITING, EVT_RUNNING)) - call_Context_Unblock(wait->ctx); -} - static size_t evt_wait(thread_wait *wait, event **events, int count, bool wait_all, unsigned int timeout) { - TP_TIMER *tp_timer = NULL; int i;
wait->signaled = EVT_RUNNING; @@ -2884,30 +2875,12 @@ static size_t evt_wait(thread_wait *wait, event **events, int count, bool wait_a if(!timeout) return evt_end_wait(wait, events, count);
- if (timeout != COOPERATIVE_TIMEOUT_INFINITE) - { - FILETIME ft; - - tp_timer = CreateThreadpoolTimer(evt_timeout, wait, NULL); - if(!tp_timer) { - FIXME("throw exception?\n"); - return COOPERATIVE_WAIT_TIMEOUT; - } - set_timeout(&ft, timeout); - SetThreadpoolTimer(tp_timer, &ft, 0, 0); - } - if(!evt_transition(&wait->signaled, EVT_RUNNING, EVT_WAITING)) return evt_end_wait(wait, events, count);
- call_Context_Block(wait->ctx); - - if (tp_timer) - { - SetThreadpoolTimer(tp_timer, NULL, 0, 0); - WaitForThreadpoolTimerCallbacks(tp_timer, TRUE); - CloseThreadpoolTimer(tp_timer); - } + if(block_context_for(wait->ctx, timeout) && + !evt_transition(&wait->signaled, EVT_WAITING, EVT_RUNNING)) + call_Context_Block(wait->ctx);
return evt_end_wait(wait, events, count); }
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/concurrency.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-)
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index b96e0cbda6f..eb9e8f9ee32 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -313,6 +313,7 @@ typedef struct #if _MSVCR_VER >= 110 #define CV_WAKE (void*)1 typedef struct cv_queue { + Context *ctx; struct cv_queue *next; LONG expired; } cv_queue; @@ -3035,20 +3036,19 @@ void __thiscall _Condition_variable_dtor(_Condition_variable *this) DEFINE_THISCALL_WRAPPER(_Condition_variable_wait, 8) void __thiscall _Condition_variable_wait(_Condition_variable *this, critical_section *cs) { - cv_queue q, *next; + cv_queue q;
TRACE("(%p, %p)\n", this, cs);
+ q.ctx = get_current_context(); + q.expired = FALSE; critical_section_lock(&this->lock); q.next = this->queue; - q.expired = FALSE; - next = q.next; this->queue = &q; critical_section_unlock(&this->lock);
critical_section_unlock(cs); - while (q.next != CV_WAKE) - RtlWaitOnAddress(&q.next, &next, sizeof(next), NULL); + call_Context_Block(q.ctx); critical_section_lock(cs); }
@@ -3058,35 +3058,26 @@ DEFINE_THISCALL_WRAPPER(_Condition_variable_wait_for, 12) bool __thiscall _Condition_variable_wait_for(_Condition_variable *this, critical_section *cs, unsigned int timeout) { - LARGE_INTEGER to; - NTSTATUS status; - FILETIME ft; - cv_queue *q, *next; + cv_queue *q;
TRACE("(%p %p %d)\n", this, cs, timeout);
q = operator_new(sizeof(cv_queue)); + q->ctx = get_current_context(); + q->expired = FALSE; critical_section_lock(&this->lock); q->next = this->queue; - q->expired = FALSE; - next = q->next; this->queue = q; critical_section_unlock(&this->lock);
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; - } - break; + if(block_context_for(q->ctx, timeout)) { + if(!InterlockedExchange(&q->expired, TRUE)) { + critical_section_lock(cs); + return FALSE; } + call_Context_Block(q->ctx); }
operator_delete(q); @@ -3118,7 +3109,7 @@ void __thiscall _Condition_variable_notify_one(_Condition_variable *this)
node->next = CV_WAKE; if(!InterlockedExchange(&node->expired, TRUE)) { - RtlWakeAddressSingle(&node->next); + call_Context_Unblock(node->ctx); return; } else { operator_delete(node); @@ -3148,7 +3139,7 @@ void __thiscall _Condition_variable_notify_all(_Condition_variable *this)
ptr->next = CV_WAKE; if(!InterlockedExchange(&ptr->expired, TRUE)) - RtlWakeAddressSingle(&ptr->next); + call_Context_Unblock(ptr->ctx); else operator_delete(ptr); ptr = next;
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 tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=133589
Your paranoid android.
=== debian11 (32 bit report) ===
quartz: dsoundrender: Timeout