Abi fields byref (#21)

* barriers: add abi fields

...allowing compile-time sizeof discovery

* `bycopy`

* barrier init actually takes a barrier attr

* use byref for barrier

* note mapping safety issues

* add PR link
This commit is contained in:
Jacek Sieka 2022-07-20 09:55:42 +02:00 committed by GitHub
parent d74d4afadc
commit 17e8479a74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 13 deletions

View File

@ -43,7 +43,7 @@ else:
proc init*(syncBarrier: var SyncBarrier, threadCount: range[0'i32..high(int32)]) {.inline.} = proc init*(syncBarrier: var SyncBarrier, threadCount: range[0'i32..high(int32)]) {.inline.} =
## Initialize a synchronization barrier that will block ``threadCount`` threads ## Initialize a synchronization barrier that will block ``threadCount`` threads
## before release. ## before release.
let err {.used.} = pthread_barrier_init(syncBarrier, nil, threadCount) let err {.used.} = pthread_barrier_init(syncBarrier, nil, cuint threadCount)
when compileOption("assertions"): when compileOption("assertions"):
if err != 0: if err != 0:
raiseOSError(OSErrorCode(err)) raiseOSError(OSErrorCode(err))

View File

@ -13,11 +13,9 @@
import locks import locks
type type
Natural32 = range[0'i32..high(int32)]
Errno* = cint Errno* = cint
PthreadAttr* = object PthreadBarrierAttr* = object
## Dummy ## Dummy
PthreadBarrier* = object PthreadBarrier* = object
## Implementation of a sense reversing barrier ## Implementation of a sense reversing barrier
@ -26,8 +24,8 @@ type
lock: Lock # Alternatively spinlock on Atomic lock: Lock # Alternatively spinlock on Atomic
cond {.guard: lock.}: Cond cond {.guard: lock.}: Cond
sense {.guard: lock.}: bool # Choose int32 to avoid zero-expansion cost in registers? sense {.guard: lock.}: bool # Choose int32 to avoid zero-expansion cost in registers?
left {.guard: lock.}: Natural32 # Number of threads missing at the barrier before opening left {.guard: lock.}: cuint # Number of threads missing at the barrier before opening
count: Natural32 # Total number of threads that need to arrive before opening the barrier count: cuint # Total number of threads that need to arrive before opening the barrier
const const
PTHREAD_BARRIER_SERIAL_THREAD* = Errno(1) PTHREAD_BARRIER_SERIAL_THREAD* = Errno(1)
@ -41,8 +39,8 @@ proc broadcast(cond: var Cond) {.inline.}=
func pthread_barrier_init*( func pthread_barrier_init*(
barrier: var PthreadBarrier, barrier: var PthreadBarrier,
attr: ptr PthreadAttr, attr: ptr PthreadBarrierAttr,
count: range[0'i32..high(int32)] count: cuint
): Errno = ): Errno =
barrier.lock.initLock() barrier.lock.initLock()
{.locks: [barrier.lock].}: {.locks: [barrier.lock].}:

View File

@ -15,11 +15,15 @@ when not compileOption("threads"):
when defined(osx): when defined(osx):
import ./barriers_macos import ./barriers_macos
export PthreadAttr, PthreadBarrier, Errno, PTHREAD_BARRIER_SERIAL_THREAD export PthreadBarrierAttr, PthreadBarrier, Errno, PTHREAD_BARRIER_SERIAL_THREAD
else: else:
type type
PthreadAttr* {.byref, importc: "pthread_attr_t", header: "<sys/types.h>".} = object PthreadBarrierAttr* {.importc: "pthread_barrierattr_t", header: "<sys/types.h>", byref.} = object
PthreadBarrier* {.byref, importc: "pthread_barrier_t", header: "<sys/types.h>".} = object when (defined(linux) and not defined(android)) and defined(amd64):
abi: array[4 div sizeof(cint), cint] # https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86/nptl/bits/pthreadtypes-arch.h;h=dd06d6753ebc80d94ede6c3c18227a3ad3104570;hb=HEAD#l45
PthreadBarrier* {.importc: "pthread_barrier_t", header: "<sys/types.h>", byref.} = object
when (defined(linux) and not defined(android)) and defined(amd64):
abi: array[32 div sizeof(clong), clong] # https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86/nptl/bits/pthreadtypes-arch.h;h=dd06d6753ebc80d94ede6c3c18227a3ad3104570;hb=HEAD#l28
Errno* = cint Errno* = cint
@ -30,14 +34,19 @@ else:
when defined(osx): when defined(osx):
export pthread_barrier_init, pthread_barrier_wait, pthread_barrier_destroy export pthread_barrier_init, pthread_barrier_wait, pthread_barrier_destroy
else: else:
# TODO careful, this function mutates `barrier` without it being `var` which
# is allowed as a consequence of `byref` - it is also different from the
# one in barriers_macos
# see https://github.com/status-im/nim-taskpools/pull/20#discussion_r923843093
proc pthread_barrier_init*( proc pthread_barrier_init*(
barrier: PthreadBarrier, barrier: PthreadBarrier,
attr: PthreadAttr or ptr PthreadAttr, attr: ptr PthreadBarrierAttr,
count: range[0'i32..high(int32)] count: cuint
): Errno {.header: "<pthread.h>".} ): Errno {.header: "<pthread.h>".}
## Initialize `barrier` with the attributes `attr`. ## Initialize `barrier` with the attributes `attr`.
## The barrier is opened when `count` waiters arrived. ## The barrier is opened when `count` waiters arrived.
# TODO the macos signature is var instead of sink
proc pthread_barrier_destroy*( proc pthread_barrier_destroy*(
barrier: sink PthreadBarrier): Errno {.header: "<pthread.h>".} barrier: sink PthreadBarrier): Errno {.header: "<pthread.h>".}
## Destroy a previously dynamically initialized `barrier`. ## Destroy a previously dynamically initialized `barrier`.