mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-06 07:38:24 +00:00
144 lines
5.5 KiB
Nim
144 lines
5.5 KiB
Nim
#
|
|
#
|
|
# Nim's Runtime Library
|
|
# (c) Copyright 2026 Andreas Rumpf
|
|
#
|
|
# See the file "copying.txt", included in this
|
|
# distribution, for details about the copyright.
|
|
#
|
|
|
|
# Read-write lock (RwLock) for lib/system.
|
|
# Used by YRC and by traceable containers that perform topology-changing ops.
|
|
# POSIX: pthread_rwlock_* ; Windows: SRWLOCK (slim reader/writer).
|
|
|
|
{.push stackTrace: off.}
|
|
|
|
when defined(windows):
|
|
# SRWLOCK is pointer-sized; use single pointer for ABI compatibility
|
|
type
|
|
RwLock* {.importc: "SRWLOCK", header: "<synchapi.h>", final, pure, byref.} = object
|
|
p: pointer
|
|
|
|
proc initializeSRWLock(L: var RwLock) {.importc: "InitializeSRWLock",
|
|
header: "<synchapi.h>".}
|
|
proc acquireSRWLockShared(L: var RwLock) {.importc: "AcquireSRWLockShared",
|
|
header: "<synchapi.h>".}
|
|
proc releaseSRWLockShared(L: var RwLock) {.importc: "ReleaseSRWLockShared",
|
|
header: "<synchapi.h>".}
|
|
proc acquireSRWLockExclusive(L: var RwLock) {.importc: "AcquireSRWLockExclusive",
|
|
header: "<synchapi.h>".}
|
|
proc releaseSRWLockExclusive(L: var RwLock) {.importc: "ReleaseSRWLockExclusive",
|
|
header: "<synchapi.h>".}
|
|
|
|
proc initRwLock*(L: var RwLock) {.inline.} =
|
|
initializeSRWLock(L)
|
|
proc deinitRwLock*(L: var RwLock) {.inline.} =
|
|
discard
|
|
proc acquireRead*(L: var RwLock) {.inline.} =
|
|
acquireSRWLockShared(L)
|
|
proc releaseRead*(L: var RwLock) {.inline.} =
|
|
releaseSRWLockShared(L)
|
|
proc acquireWrite*(L: var RwLock) {.inline.} =
|
|
acquireSRWLockExclusive(L)
|
|
proc releaseWrite*(L: var RwLock) {.inline.} =
|
|
releaseSRWLockExclusive(L)
|
|
|
|
elif defined(genode):
|
|
{.error: "RwLock is not implemented for Genode".}
|
|
|
|
else:
|
|
# POSIX: pthread_rwlock_*
|
|
type
|
|
SysRwLockObj {.importc: "pthread_rwlock_t", pure, final,
|
|
header: """#include <sys/types.h>
|
|
#include <pthread.h>""", byref.} = object
|
|
when defined(linux) and defined(amd64):
|
|
abi: array[56 div sizeof(clong), clong]
|
|
|
|
proc pthread_rwlock_init(rwlock: var SysRwLockObj, attr: pointer): cint {.
|
|
importc: "pthread_rwlock_init", header: "<pthread.h>", noSideEffect.}
|
|
proc pthread_rwlock_destroy(rwlock: var SysRwLockObj): cint {.
|
|
importc: "pthread_rwlock_destroy", header: "<pthread.h>", noSideEffect.}
|
|
proc pthread_rwlock_rdlock(rwlock: var SysRwLockObj): cint {.
|
|
importc: "pthread_rwlock_rdlock", header: "<pthread.h>", noSideEffect.}
|
|
proc pthread_rwlock_wrlock(rwlock: var SysRwLockObj): cint {.
|
|
importc: "pthread_rwlock_wrlock", header: "<pthread.h>", noSideEffect.}
|
|
proc pthread_rwlock_unlock(rwlock: var SysRwLockObj): cint {.
|
|
importc: "pthread_rwlock_unlock", header: "<pthread.h>", noSideEffect.}
|
|
|
|
when defined(linux):
|
|
# PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP: once a writer is waiting,
|
|
# new readers block. Prevents continuous mutator read-locks from starving
|
|
# the collector's write-lock acquisition (glibc default is PREFER_READER).
|
|
type
|
|
SysRwLockAttr {.importc: "pthread_rwlockattr_t", pure, final,
|
|
header: "<pthread.h>".} = object
|
|
const PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = cint(3)
|
|
proc pthread_rwlockattr_init(attr: ptr SysRwLockAttr): cint {.
|
|
importc: "pthread_rwlockattr_init", header: "<pthread.h>".}
|
|
proc pthread_rwlockattr_destroy(attr: ptr SysRwLockAttr): cint {.
|
|
importc: "pthread_rwlockattr_destroy", header: "<pthread.h>".}
|
|
proc pthread_rwlockattr_setkind_np(attr: ptr SysRwLockAttr; pref: cint): cint {.
|
|
importc: "pthread_rwlockattr_setkind_np", header: "<pthread.h>".}
|
|
|
|
when defined(ios):
|
|
type RwLock* = ptr SysRwLockObj
|
|
proc initRwLock*(L: var RwLock) =
|
|
when not declared(c_malloc):
|
|
proc c_malloc(size: csize_t): pointer {.importc: "malloc", header: "<stdlib.h>".}
|
|
proc c_free(p: pointer) {.importc: "free", header: "<stdlib.h>".}
|
|
L = cast[RwLock](c_malloc(csize_t(sizeof(SysRwLockObj))))
|
|
discard pthread_rwlock_init(L[], nil)
|
|
proc deinitRwLock*(L: var RwLock) =
|
|
if L != nil:
|
|
discard pthread_rwlock_destroy(L[])
|
|
when not declared(c_free):
|
|
proc c_free(p: pointer) {.importc: "free", header: "<stdlib.h>".}
|
|
c_free(L)
|
|
L = nil
|
|
proc acquireRead*(L: var RwLock) =
|
|
discard pthread_rwlock_rdlock(L[])
|
|
proc releaseRead*(L: var RwLock) =
|
|
discard pthread_rwlock_unlock(L[])
|
|
proc acquireWrite*(L: var RwLock) =
|
|
discard pthread_rwlock_wrlock(L[])
|
|
proc releaseWrite*(L: var RwLock) =
|
|
discard pthread_rwlock_unlock(L[])
|
|
else:
|
|
type RwLock* = SysRwLockObj
|
|
proc initRwLock*(L: var RwLock) =
|
|
when defined(linux):
|
|
var attr: SysRwLockAttr
|
|
discard pthread_rwlockattr_init(addr attr)
|
|
discard pthread_rwlockattr_setkind_np(addr attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
|
|
discard pthread_rwlock_init(L, addr attr)
|
|
discard pthread_rwlockattr_destroy(addr attr)
|
|
else:
|
|
discard pthread_rwlock_init(L, nil)
|
|
proc deinitRwLock*(L: var RwLock) =
|
|
discard pthread_rwlock_destroy(L)
|
|
proc acquireRead*(L: var RwLock) =
|
|
discard pthread_rwlock_rdlock(L)
|
|
proc releaseRead*(L: var RwLock) =
|
|
discard pthread_rwlock_unlock(L)
|
|
proc acquireWrite*(L: var RwLock) =
|
|
discard pthread_rwlock_wrlock(L)
|
|
proc releaseWrite*(L: var RwLock) =
|
|
discard pthread_rwlock_unlock(L)
|
|
|
|
template withReadLock*(L: var RwLock, body: untyped) =
|
|
acquireRead(L)
|
|
try:
|
|
body
|
|
finally:
|
|
releaseRead(L)
|
|
|
|
template withWriteLock*(L: var RwLock, body: untyped) =
|
|
acquireWrite(L)
|
|
try:
|
|
body
|
|
finally:
|
|
releaseWrite(L)
|
|
|
|
{.pop.}
|