Piotr Caban : msvcr110: Make sure we don't hang in _Condition_variable::notify* functions.

Alexandre Julliard julliard at winehq.org
Wed Mar 16 16:48:23 CDT 2022


Module: wine
Branch: master
Commit: 746df92dba928c8f5bfbff44c2b7156ab5bcf195
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=746df92dba928c8f5bfbff44c2b7156ab5bcf195

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed Mar 16 14:38:02 2022 +0100

msvcr110: Make sure we don't hang in _Condition_variable::notify* functions.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcrt/concurrency.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c
index 18138901594..54b2c49db99 100644
--- a/dlls/msvcrt/concurrency.c
+++ b/dlls/msvcrt/concurrency.c
@@ -261,6 +261,7 @@ typedef struct
 } event;
 
 #if _MSVCR_VER >= 110
+#define CV_WAKE (void*)1
 typedef struct cv_queue {
     struct cv_queue *next;
     LONG expired;
@@ -2299,18 +2300,20 @@ 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;
+    cv_queue q, *next;
 
     TRACE("(%p, %p)\n", this, cs);
 
     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);
-    NtWaitForKeyedEvent(keyed_event, &q, 0, NULL);
+    while (q.next != CV_WAKE)
+        RtlWaitOnAddress(&q.next, &next, sizeof(next), NULL);
     critical_section_lock(cs);
 }
 
@@ -2323,7 +2326,7 @@ bool __thiscall _Condition_variable_wait_for(_Condition_variable *this,
     LARGE_INTEGER to;
     NTSTATUS status;
     FILETIME ft;
-    cv_queue *q;
+    cv_queue *q, *next;
 
     TRACE("(%p %p %d)\n", this, cs, timeout);
 
@@ -2331,6 +2334,7 @@ bool __thiscall _Condition_variable_wait_for(_Condition_variable *this,
     critical_section_lock(&this->lock);
     q->next = this->queue;
     q->expired = FALSE;
+    next = q->next;
     this->queue = q;
     critical_section_unlock(&this->lock);
 
@@ -2339,14 +2343,15 @@ bool __thiscall _Condition_variable_wait_for(_Condition_variable *this,
     GetSystemTimeAsFileTime(&ft);
     to.QuadPart = ((LONGLONG)ft.dwHighDateTime << 32) +
         ft.dwLowDateTime + (LONGLONG)timeout * 10000;
-    status = NtWaitForKeyedEvent(keyed_event, q, 0, &to);
-    if(status == STATUS_TIMEOUT) {
-        if(!InterlockedExchange(&q->expired, TRUE)) {
-            critical_section_lock(cs);
-            return FALSE;
+    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;
         }
-        else
-            NtWaitForKeyedEvent(keyed_event, q, 0, 0);
     }
 
     operator_delete(q);
@@ -2376,8 +2381,9 @@ void __thiscall _Condition_variable_notify_one(_Condition_variable *this)
         this->queue = node->next;
         critical_section_unlock(&this->lock);
 
+        node->next = CV_WAKE;
         if(!InterlockedExchange(&node->expired, TRUE)) {
-            NtReleaseKeyedEvent(keyed_event, node, 0, NULL);
+            RtlWakeAddressSingle(&node->next);
             return;
         } else {
             HeapFree(GetProcessHeap(), 0, node);
@@ -2405,8 +2411,9 @@ void __thiscall _Condition_variable_notify_all(_Condition_variable *this)
     while(ptr) {
         cv_queue *next = ptr->next;
 
+        ptr->next = CV_WAKE;
         if(!InterlockedExchange(&ptr->expired, TRUE))
-            NtReleaseKeyedEvent(keyed_event, ptr, 0, NULL);
+            RtlWakeAddressSingle(&ptr->next);
         else
             HeapFree(GetProcessHeap(), 0, ptr);
         ptr = next;




More information about the wine-cvs mailing list