barrier more efficient
This commit is contained in:
parent
7303c3292f
commit
a4323b06b3
1 changed files with 24 additions and 18 deletions
|
|
@ -40,31 +40,37 @@ proc signal(cv: var CondVar) =
|
||||||
release(cv.L)
|
release(cv.L)
|
||||||
signal(cv.c)
|
signal(cv.c)
|
||||||
|
|
||||||
|
const CacheLineSize = 32 # true for most archs
|
||||||
|
|
||||||
type
|
type
|
||||||
Barrier* {.compilerProc.} = object
|
Barrier {.compilerProc.} = object
|
||||||
entered: int
|
entered: int
|
||||||
cv: CondVar
|
cv: CondVar # condvar takes 3 words at least
|
||||||
cacheAlign: array[0..20, byte] # ensure 'left' is not on the same
|
when sizeof(int) < 8:
|
||||||
# cache line as 'entered'
|
cacheAlign: array[CacheLineSize-4*sizeof(int), byte]
|
||||||
left: int
|
left: int
|
||||||
|
cacheAlign2: array[CacheLineSize-sizeof(int), byte]
|
||||||
|
interest: bool ## wether the master is interested in the "all done" event
|
||||||
|
|
||||||
proc barrierEnter*(b: ptr Barrier) {.compilerProc.} =
|
proc barrierEnter(b: ptr Barrier) {.compilerProc, inline.} =
|
||||||
atomicInc b.entered
|
## due to the signaling between threads, it is ensured we are the only
|
||||||
|
## one with access to 'entered' so we don't need 'atomicInc' here:
|
||||||
|
inc b.entered
|
||||||
|
|
||||||
proc barrierLeave*(b: ptr Barrier) {.compilerProc.} =
|
proc barrierLeave(b: ptr Barrier) {.compilerProc, inline.} =
|
||||||
atomicInc b.left
|
atomicInc b.left
|
||||||
# these can only be equal if 'closeBarrier' already signaled its interest
|
if b.interest and b.left == b.entered: signal(b.cv)
|
||||||
# in this event:
|
|
||||||
if b.left == b.entered: signal(b.cv)
|
|
||||||
|
|
||||||
proc openBarrier*(b: ptr Barrier) {.compilerProc.} =
|
proc openBarrier(b: ptr Barrier) {.compilerProc, inline.} =
|
||||||
b.entered = 0
|
b.entered = 0
|
||||||
b.cv = createCondVar()
|
b.left = 0
|
||||||
b.left = -1
|
b.interest = false
|
||||||
|
|
||||||
proc closeBarrier*(b: ptr Barrier) {.compilerProc.} =
|
proc closeBarrier(b: ptr Barrier) {.compilerProc.} =
|
||||||
# signal interest in the "all done" event:
|
if b.left != b.entered:
|
||||||
atomicInc b.left
|
b.cv = createCondVar()
|
||||||
|
b.interest = true # XXX we really need to ensure no re-orderings are done
|
||||||
|
# by the C compiler here
|
||||||
while b.left != b.entered: await(b.cv)
|
while b.left != b.entered: await(b.cv)
|
||||||
destroyCondVar(b.cv)
|
destroyCondVar(b.cv)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue