Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get Thread ID in a portable way #42

Closed
mratsim opened this issue Dec 15, 2019 · 0 comments · Fixed by #67
Closed

Get Thread ID in a portable way #42

mratsim opened this issue Dec 15, 2019 · 0 comments · Fixed by #67
Labels
enhancement :shipit: New feature or request

Comments

@mratsim
Copy link
Owner

mratsim commented Dec 15, 2019

Currently the threadID is leaking into all datastructures.

It seems like "obvious facilities" do not fit:

  • pthread_self return a pthread handle
  • gettid is Linux only
  • syscall(__NR_gettid) is Linux only (and involves a syscall)
  • pthread_getthreadid_np is BSD only
  • getThreadID is Windows-only

This is necessary to decouple the memory management and allow upstreaming it.

LookAside list:

# Stack pointer
top: T
# Mempool doesn't provide the proper free yet
freeFn*: proc(threadID: int32, t: T) {.nimcall, gcsafe.}
threadID*: int32 # TODO, memory pool abstraction leaking
# Adaptative freeing
count: int
recentAsk: int
# "closure" - This points to the proc + env currently registered in the allocator
# It is nil-ed on destruction of the lookaside list.
#
registeredAt: ptr tuple[onHeartbeat: proc(env: pointer) {.nimcall.}, env: pointer]

Mempool free requires the caller to supply its ThreadID

proc recycle*[T](myThreadID: int32, p: ptr T) {.gcsafe.} =
## Returns a memory block to its memory pool.
##
## This is thread-safe, any thread can call it.
## It must indicates its ID.
## A fast path is used if it's the ID of the borrowing thread,
## otherwise a slow path will be used.
##
## If the thread owning the pool was exited before this
## block was returned, the main thread should now
## have ownership of the related arenas and can deallocate them.
# TODO: sink ptr T - parsing bug to raise
# similar to https://github.com/nim-lang/Nim/issues/12091
preCondition: not p.isNil
let p = cast[ptr MemBlock](p)
# Find the owning arena
let arena = p.getArena()
if myThreadID == arena.meta.threadID.load(moRelaxed):
# thread-local free
if arena.meta.localFree.isNil:
p.next.store(nil, moRelaxed)
arena.meta.localFree = p
else:
arena.meta.localFree.prepend(p)
arena.meta.used -= 1
if unlikely(arena.isUnused()):
# If an arena is unused, we can try releasing it immediately
arena.allocator[].considerRelease(arena)
else:
# remote arena
let remoteRecycled = arena.meta.remoteFree.trySend(p)
postCondition: remoteRecycled

References
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadid
https://stackoverflow.com/questions/21091000/how-to-get-thread-id-of-a-pthread-in-linux-c-program

@mratsim mratsim added the enhancement :shipit: New feature or request label Jan 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement :shipit: New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant