threaded alloc (#20492)
* allocator: catch up with multi-threading techniques * removed the global thread lock * more atomics for fun and profit * added important sysAssert * stats remain thread local and don't have to be atomic * undo split chunk optimizations in the hope it makes the CI happy
This commit is contained in:
parent
b47d5486db
commit
fbc6975922
3 changed files with 262 additions and 133 deletions
|
|
@ -53,13 +53,23 @@ when defined(nimPreviewSlimSystem):
|
|||
const
|
||||
hasAllocStack = defined(zephyr) # maybe freertos too?
|
||||
|
||||
when defined(gcDestructors):
|
||||
proc allocThreadStorage(size: int): pointer =
|
||||
result = c_malloc(csize_t size)
|
||||
zeroMem(result, size)
|
||||
|
||||
proc deallocThreadStorage(p: pointer) = c_free(p)
|
||||
else:
|
||||
template allocThreadStorage(size: untyped): untyped = allocShared0(size)
|
||||
template deallocThreadStorage(p: pointer) = deallocShared(p)
|
||||
|
||||
when hasAllocStack or defined(zephyr) or defined(freertos):
|
||||
const
|
||||
nimThreadStackSize {.intdefine.} = 8192
|
||||
nimThreadStackSize {.intdefine.} = 8192
|
||||
nimThreadStackGuard {.intdefine.} = 128
|
||||
|
||||
StackGuardSize = nimThreadStackGuard
|
||||
ThreadStackSize = nimThreadStackSize - nimThreadStackGuard
|
||||
StackGuardSize = nimThreadStackGuard
|
||||
ThreadStackSize = nimThreadStackSize - nimThreadStackGuard
|
||||
else:
|
||||
const
|
||||
StackGuardSize = 4096
|
||||
|
|
@ -176,7 +186,7 @@ else:
|
|||
finally:
|
||||
afterThreadRuns()
|
||||
when hasAllocStack:
|
||||
deallocShared(thrd.rawStack)
|
||||
deallocThreadStorage(thrd.rawStack)
|
||||
|
||||
proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) {.raises: [].} =
|
||||
when defined(boehmgc):
|
||||
|
|
@ -207,7 +217,7 @@ template threadProcWrapperBody(closure: untyped): untyped =
|
|||
# mark as not running anymore:
|
||||
thrd.core = nil
|
||||
thrd.dataFn = nil
|
||||
deallocShared(cast[pointer](core))
|
||||
deallocThreadStorage(cast[pointer](core))
|
||||
|
||||
{.push stack_trace:off.}
|
||||
when defined(windows):
|
||||
|
|
@ -278,7 +288,7 @@ when false:
|
|||
t.dataFn = nil
|
||||
## if thread `t` already exited, `t.core` will be `null`.
|
||||
if not isNil(t.core):
|
||||
deallocShared(t.core)
|
||||
deallocThreadStorage(t.core)
|
||||
t.core = nil
|
||||
|
||||
when hostOS == "windows":
|
||||
|
|
@ -290,7 +300,7 @@ when hostOS == "windows":
|
|||
## Entry point is the proc `tp`.
|
||||
## `param` is passed to `tp`. `TArg` can be `void` if you
|
||||
## don't need to pass any data to the thread.
|
||||
t.core = cast[PGcThread](allocShared0(sizeof(GcThread)))
|
||||
t.core = cast[PGcThread](allocThreadStorage(sizeof(GcThread)))
|
||||
|
||||
when TArg isnot void: t.data = param
|
||||
t.dataFn = tp
|
||||
|
|
@ -315,7 +325,7 @@ elif defined(genode):
|
|||
proc createThread*[TArg](t: var Thread[TArg],
|
||||
tp: proc (arg: TArg) {.thread, nimcall.},
|
||||
param: TArg) =
|
||||
t.core = cast[PGcThread](allocShared0(sizeof(GcThread)))
|
||||
t.core = cast[PGcThread](allocThreadStorage(sizeof(GcThread)))
|
||||
|
||||
when TArg isnot void: t.data = param
|
||||
t.dataFn = tp
|
||||
|
|
@ -339,7 +349,7 @@ else:
|
|||
## Entry point is the proc `tp`. `param` is passed to `tp`.
|
||||
## `TArg` can be `void` if you
|
||||
## don't need to pass any data to the thread.
|
||||
t.core = cast[PGcThread](allocShared0(sizeof(GcThread)))
|
||||
t.core = cast[PGcThread](allocThreadStorage(sizeof(GcThread)))
|
||||
|
||||
when TArg isnot void: t.data = param
|
||||
t.dataFn = tp
|
||||
|
|
@ -348,7 +358,7 @@ else:
|
|||
doAssert pthread_attr_init(a) == 0
|
||||
when hasAllocStack:
|
||||
var
|
||||
rawstk = allocShared0(ThreadStackSize + StackGuardSize)
|
||||
rawstk = allocThreadStorage(ThreadStackSize + StackGuardSize)
|
||||
stk = cast[pointer](cast[uint](rawstk) + StackGuardSize)
|
||||
let setstacksizeResult = pthread_attr_setstack(addr a, stk, ThreadStackSize)
|
||||
t.rawStack = rawstk
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue