diff options
author | def <dennis@felsin9.de> | 2014-11-11 00:47:32 +0100 |
---|---|---|
committer | def <dennis@felsin9.de> | 2014-11-11 00:50:29 +0100 |
commit | 78b3f739b13b93e42016e32e0f923436ce9b207e (patch) | |
tree | d9bdfa8b12685ae8a770a28e3be9472b9d4d1dad /lib/core/locks.nim | |
parent | ea57f340f2870f1c08d00ff1c2ef18e94c40f9b0 (diff) | |
download | Nim-78b3f739b13b93e42016e32e0f923436ce9b207e.tar.gz |
Remove runtime deadlock prevention as deadlock detection at compile-time is available
Conflicts: lib/core/locks.nim
Diffstat (limited to 'lib/core/locks.nim')
-rw-r--r-- | lib/core/locks.nim | 108 |
1 files changed, 2 insertions, 106 deletions
diff --git a/lib/core/locks.nim b/lib/core/locks.nim index 817d84858..4e85474fb 100644 --- a/lib/core/locks.nim +++ b/lib/core/locks.nim @@ -8,19 +8,12 @@ # ## This module contains Nim's support for locks and condition vars. -## If the symbol ``preventDeadlocks`` is defined -## (compiled with ``-d:preventDeadlocks``) special logic is added to -## every ``acquire``, ``tryAcquire`` and ``release`` action that ensures at -## runtime that no deadlock can occur. This is achieved by forcing a thread -## to release its locks should it be part of a deadlock. This thread then -## re-acquires its locks and proceeds. include "system/syslocks" type TLock* = TSysLock ## Nim lock; whether this is re-entrant - ## or not is unspecified! However, compilation - ## in preventDeadlocks-mode guarantees re-entrancy. + ## or not is unspecified! TCond* = TSysCond ## Nim condition variable LockEffect* = object of RootEffect ## effect that denotes that some lock operation @@ -31,26 +24,6 @@ type ## released {.deprecated: [FLock: LockEffect, FAquireLock: AquireEffect, FReleaseLock: ReleaseEffect].} - -const - noDeadlocks = defined(preventDeadlocks) - maxLocksPerThread* = 10 ## max number of locks a thread can hold - ## at the same time; this limit is only relevant - ## when compiled with ``-d:preventDeadlocks``. - -var - deadlocksPrevented*: int ## counts the number of times a - ## deadlock has been prevented - -when noDeadlocks: - var - locksLen {.threadvar.}: int - locks {.threadvar.}: array [0..maxLocksPerThread-1, pointer] - - proc orderedLocks(): bool = - for i in 0 .. locksLen-2: - if locks[i] >= locks[i+1]: return false - result = true proc initLock*(lock: var TLock) {.inline.} = ## Initializes the given lock. @@ -63,90 +36,13 @@ proc deinitLock*(lock: var TLock) {.inline.} = proc tryAcquire*(lock: var TLock): bool {.tags: [AquireEffect].} = ## Tries to acquire the given lock. Returns `true` on success. result = tryAcquireSys(lock) - when noDeadlocks: - if not result: return - # we have to add it to the ordered list. Oh, and we might fail if - # there is no space in the array left ... - if locksLen >= len(locks): - releaseSys(lock) - raise newException(EResourceExhausted, "cannot acquire additional lock") - # find the position to add: - var p = addr(lock) - var L = locksLen-1 - var i = 0 - while i <= L: - assert locks[i] != nil - if locks[i] < p: inc(i) # in correct order - elif locks[i] == p: return # thread already holds lock - else: - # do the crazy stuff here: - while L >= i: - locks[L+1] = locks[L] - dec L - locks[i] = p - inc(locksLen) - assert orderedLocks() - return - # simply add to the end: - locks[locksLen] = p - inc(locksLen) - assert orderedLocks() proc acquire*(lock: var TLock) {.tags: [AquireEffect].} = ## Acquires the given lock. - when nodeadlocks: - var p = addr(lock) - var L = locksLen-1 - var i = 0 - while i <= L: - assert locks[i] != nil - if locks[i] < p: inc(i) # in correct order - elif locks[i] == p: return # thread already holds lock - else: - # do the crazy stuff here: - if locksLen >= len(locks): - raise newException(EResourceExhausted, - "cannot acquire additional lock") - while L >= i: - releaseSys(cast[ptr TSysLock](locks[L])[]) - locks[L+1] = locks[L] - dec L - # acquire the current lock: - acquireSys(lock) - locks[i] = p - inc(locksLen) - # acquire old locks in proper order again: - L = locksLen-1 - inc i - while i <= L: - acquireSys(cast[ptr TSysLock](locks[i])[]) - inc(i) - # DANGER: We can only modify this global var if we gained every lock! - # NO! We need an atomic increment. Crap. - discard system.atomicInc(deadlocksPrevented, 1) - assert orderedLocks() - return - - # simply add to the end: - if locksLen >= len(locks): - raise newException(EResourceExhausted, "cannot acquire additional lock") - acquireSys(lock) - locks[locksLen] = p - inc(locksLen) - assert orderedLocks() - else: - acquireSys(lock) + acquireSys(lock) proc release*(lock: var TLock) {.tags: [ReleaseEffect].} = ## Releases the given lock. - when nodeadlocks: - var p = addr(lock) - var L = locksLen - for i in countdown(L-1, 0): - if locks[i] == p: - for j in i..L-2: locks[j] = locks[j+1] - dec locksLen - break releaseSys(lock) |