diff options
author | flywind <xzsflywind@gmail.com> | 2021-04-19 16:51:13 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-19 10:51:13 +0200 |
commit | dc89b212572fecd449dd469ffb2424c78941c12f (patch) | |
tree | f1458632d93f4c94e06dd3114e49773519ffad56 | |
parent | cedbc7035d171d1535365c8acb889911b839ce99 (diff) | |
download | Nim-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.nim | 9 | ||||
-rw-r--r-- | lib/genode_cpp/syslocks.h | 5 | ||||
-rw-r--r-- | lib/system/syslocks.nim | 55 | ||||
-rw-r--r-- | lib/system/sysspawn.nim | 33 | ||||
-rw-r--r-- | lib/system/threadlocalstorage.nim | 3 |
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, |