summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorflywind <xzsflywind@gmail.com>2021-04-19 16:51:13 +0800
committerGitHub <noreply@github.com>2021-04-19 10:51:13 +0200
commitdc89b212572fecd449dd469ffb2424c78941c12f (patch)
treef1458632d93f4c94e06dd3114e49773519ffad56
parentcedbc7035d171d1535365c8acb889911b839ce99 (diff)
downloadNim-dc89b212572fecd449dd469ffb2424c78941c12f.tar.gz
[std/locks]close #7998(complete condition variables) (#17711)
* close #7998
* workaround genode

* Update lib/system/syslocks.nim
-rw-r--r--lib/core/locks.nim9
-rw-r--r--lib/genode_cpp/syslocks.h5
-rw-r--r--lib/system/syslocks.nim55
-rw-r--r--lib/system/sysspawn.nim33
-rw-r--r--lib/system/threadlocalstorage.nim3
5 files changed, 60 insertions, 45 deletions
diff --git a/lib/core/locks.nim b/lib/core/locks.nim
index 674817674..92967b9db 100644
--- a/lib/core/locks.nim
+++ b/lib/core/locks.nim
@@ -66,13 +66,18 @@ proc deinitCond*(cond: var Cond) {.inline.} =
   deinitSysCond(cond)
 
 proc wait*(cond: var Cond, lock: var Lock) {.inline.} =
-  ## waits on the condition variable `cond`.
+  ## Waits on the condition variable `cond`.
   waitSysCond(cond, lock)
 
 proc signal*(cond: var Cond) {.inline.} =
-  ## sends a signal to the condition variable `cond`.
+  ## Sends a signal to the condition variable `cond`.
   signalSysCond(cond)
 
+proc broadcast*(cond: var Cond) {.inline.} =
+  ## Unblocks all threads currently blocked on the
+  ## specified condition variable `cond`.
+  broadcastSysCond(cond)
+
 template withLock*(a: Lock, body: untyped) =
   ## Acquires the given lock, executes the statements in body and
   ## releases the lock after the statements finish executing.
diff --git a/lib/genode_cpp/syslocks.h b/lib/genode_cpp/syslocks.h
index c50180903..b5d5ae694 100644
--- a/lib/genode_cpp/syslocks.h
+++ b/lib/genode_cpp/syslocks.h
@@ -71,6 +71,11 @@ struct Nim::SysCond
 	{
 		_semaphore.up();
 	}
+
+	void broadcastSysCond()
+	{
+		_semaphore.up();
+	}
 };
 
 #endif
diff --git a/lib/system/syslocks.nim b/lib/system/syslocks.nim
index 51dbfd3a2..ac52d9a8c 100644
--- a/lib/system/syslocks.nim
+++ b/lib/system/syslocks.nim
@@ -24,7 +24,9 @@ when defined(windows):
       LockSemaphore: int
       SpinCount: int
 
-    SysCond = Handle
+    RTL_CONDITION_VARIABLE {.importc: "RTL_CONDITION_VARIABLE", header: "synchapi.h".} = object
+      thePtr {.importc: "ptr".} : Handle
+    SysCond = RTL_CONDITION_VARIABLE
 
   proc initSysLock(L: var SysLock) {.importc: "InitializeCriticalSection",
                                      header: "<windows.h>".}
@@ -48,30 +50,29 @@ when defined(windows):
   proc deinitSys(L: var SysLock) {.importc: "DeleteCriticalSection",
                                    header: "<windows.h>".}
 
-  proc createEvent(lpEventAttributes: pointer,
-                   bManualReset, bInitialState: int32,
-                   lpName: cstring): SysCond {.stdcall, noSideEffect,
-    dynlib: "kernel32", importc: "CreateEventA".}
+  proc initializeConditionVariable(
+    conditionVariable: var SysCond
+  ) {.stdcall, noSideEffect, dynlib: "kernel32", importc: "InitializeConditionVariable".}
 
-  proc closeHandle(hObject: Handle) {.stdcall, noSideEffect,
-    dynlib: "kernel32", importc: "CloseHandle".}
-  proc waitForSingleObject(hHandle: Handle, dwMilliseconds: int32): int32 {.
-    stdcall, dynlib: "kernel32", importc: "WaitForSingleObject", noSideEffect.}
+  proc sleepConditionVariableCS(
+    conditionVariable: var SysCond,
+    PCRITICAL_SECTION: var SysLock,
+    dwMilliseconds: int
+  ): int32 {.stdcall, noSideEffect, dynlib: "kernel32", importc: "SleepConditionVariableCS".}
 
-  proc signalSysCond(hEvent: SysCond) {.stdcall, noSideEffect,
-    dynlib: "kernel32", importc: "SetEvent".}
+
+  proc signalSysCond(hEvent: var SysCond) {.stdcall, noSideEffect,
+    dynlib: "kernel32", importc: "WakeConditionVariable".}
+
+  proc broadcastSysCond(hEvent: var SysCond) {.stdcall, noSideEffect,
+    dynlib: "kernel32", importc: "WakeAllConditionVariable".}
 
   proc initSysCond(cond: var SysCond) {.inline.} =
-    cond = createEvent(nil, 0'i32, 0'i32, nil)
+    initializeConditionVariable(cond)
   proc deinitSysCond(cond: var SysCond) {.inline.} =
-    closeHandle(cond)
+    discard
   proc waitSysCond(cond: var SysCond, lock: var SysLock) =
-    releaseSys(lock)
-    discard waitForSingleObject(cond, -1'i32)
-    acquireSys(lock)
-
-  proc waitSysCondWindows(cond: var SysCond) =
-    discard waitForSingleObject(cond, -1'i32)
+    discard sleepConditionVariableCS(cond, lock, -1'i32)
 
 elif defined(genode):
   const
@@ -94,6 +95,8 @@ elif defined(genode):
     noSideEffect, importcpp.}
   proc signalSysCond(cond: var SysCond) {.
     noSideEffect, importcpp.}
+  proc broadcastSysCond(cond: var SysCond) {.
+    noSideEffect, importcpp.}
 
 else:
   type
@@ -181,7 +184,7 @@ else:
       releaseSysAux(L)
 
   when insideRLocksModule:
-    let SysLockType_Reentrant{.importc: "PTHREAD_MUTEX_RECURSIVE",
+    let SysLockType_Reentrant {.importc: "PTHREAD_MUTEX_RECURSIVE",
       header: "<pthread.h>".}: SysLockType
     proc initSysLockAttr(a: var SysLockAttr) {.
       importc: "pthread_mutexattr_init", header: "<pthread.h>", noSideEffect.}
@@ -194,10 +197,12 @@ else:
     proc deinitSysCondAux(cond: var SysCondObj) {.noSideEffect,
       importc: "pthread_cond_destroy", header: "<pthread.h>".}
 
-    proc waitSysCondAux(cond: var SysCondObj, lock: var SysLockObj) {.
+    proc waitSysCondAux(cond: var SysCondObj, lock: var SysLockObj): cint {.
       importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
     proc signalSysCondAux(cond: var SysCondObj) {.
       importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
+    proc broadcastSysCondAux(cond: var SysCondObj) {.
+      importc: "pthread_cond_broadcast", header: "<pthread.h>", noSideEffect.}
 
     when defined(ios):
       proc initSysCond(cond: var SysCond, cond_attr: ptr SysCondAttr = nil) =
@@ -209,9 +214,11 @@ else:
         c_free(cond)
 
       template waitSysCond(cond: var SysCond, lock: var SysLock) =
-        waitSysCondAux(cond[], lock[])
+        discard waitSysCondAux(cond[], lock[])
       template signalSysCond(cond: var SysCond) =
         signalSysCondAux(cond[])
+      template broadcastSysCond(cond: var SysCond) =
+        broadcastSysCondAux(cond[])
     else:
       template initSysCond(cond: var SysCond, cond_attr: ptr SysCondAttr = nil) =
         initSysCondAux(cond, cond_attr)
@@ -219,8 +226,10 @@ else:
         deinitSysCondAux(cond)
 
       template waitSysCond(cond: var SysCond, lock: var SysLock) =
-        waitSysCondAux(cond, lock)
+        discard waitSysCondAux(cond, lock)
       template signalSysCond(cond: var SysCond) =
         signalSysCondAux(cond)
+      template broadcastSysCond(cond: var SysCond) =
+        broadcastSysCondAux(cond)
 
 {.pop.}
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index d1f5803f4..c9b9a68f0 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -20,34 +20,28 @@ when not declared(NimString):
 type
   CondVar = object
     c: SysCond
-    when defined(posix):
-      stupidLock: SysLock
-      counter: int
+    stupidLock: SysLock
+    counter: int
 
 proc createCondVar(): CondVar =
   initSysCond(result.c)
-  when defined(posix):
-    initSysLock(result.stupidLock)
-    #acquireSys(result.stupidLock)
+  initSysLock(result.stupidLock)
+  #acquireSys(result.stupidLock)
 
 proc destroyCondVar(c: var CondVar) {.inline.} =
   deinitSysCond(c.c)
 
 proc await(cv: var CondVar) =
-  when defined(posix):
-    acquireSys(cv.stupidLock)
-    while cv.counter <= 0:
-      waitSysCond(cv.c, cv.stupidLock)
-    dec cv.counter
-    releaseSys(cv.stupidLock)
-  else:
-    waitSysCondWindows(cv.c)
+  acquireSys(cv.stupidLock)
+  while cv.counter <= 0:
+    waitSysCond(cv.c, cv.stupidLock)
+  dec cv.counter
+  releaseSys(cv.stupidLock)
 
 proc signal(cv: var CondVar) =
-  when defined(posix):
-    acquireSys(cv.stupidLock)
-    inc cv.counter
-    releaseSys(cv.stupidLock)
+  acquireSys(cv.stupidLock)
+  inc cv.counter
+  releaseSys(cv.stupidLock)
   signalSysCond(cv.c)
 
 type
@@ -57,8 +51,7 @@ type
 
 proc createFastCondVar(): FastCondVar =
   initSysCond(result.slow.c)
-  when defined(posix):
-    initSysLock(result.slow.stupidLock)
+  initSysLock(result.slow.stupidLock)
     #acquireSys(result.slow.stupidLock)
   result.event = false
   result.slowPath = false
diff --git a/lib/system/threadlocalstorage.nim b/lib/system/threadlocalstorage.nim
index cbb74c7df..30962ef77 100644
--- a/lib/system/threadlocalstorage.nim
+++ b/lib/system/threadlocalstorage.nim
@@ -17,6 +17,9 @@ when defined(windows):
   proc winResumeThread(hThread: SysThread): int32 {.
     stdcall, dynlib: "kernel32", importc: "ResumeThread".}
 
+  proc waitForSingleObject(hHandle: SysThread, dwMilliseconds: int32): int32 {.
+    stdcall, dynlib: "kernel32", importc: "WaitForSingleObject".}
+
   proc waitForMultipleObjects(nCount: int32,
                               lpHandles: ptr SysThread,
                               bWaitAll: int32,