1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
include system/inclrtl
const hasSharedHeap* = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own
when defined(windows):
type
Handle* = int
SysThread* = Handle
WinThreadProc* = proc (x: pointer): int32 {.stdcall.}
proc createThread*(lpThreadAttributes: pointer, dwStackSize: int32,
lpStartAddress: WinThreadProc,
lpParameter: pointer,
dwCreationFlags: int32,
lpThreadId: var int32): SysThread {.
stdcall, dynlib: "kernel32", importc: "CreateThread".}
proc winSuspendThread*(hThread: SysThread): int32 {.
stdcall, dynlib: "kernel32", importc: "SuspendThread".}
proc winResumeThread*(hThread: SysThread): int32 {.
stdcall, dynlib: "kernel32", importc: "ResumeThread".}
proc waitForSingleObject*(hHandle: SysThread, dwMilliseconds: int32): int32 {.
stdcall, dynlib: "kernel32", importc: "WaitForSingleObject".}
proc waitForMultipleObjects*(nCount: int32,
lpHandles: ptr SysThread,
bWaitAll: int32,
dwMilliseconds: int32): int32 {.
stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
proc terminateThread*(hThread: SysThread, dwExitCode: int32): int32 {.
stdcall, dynlib: "kernel32", importc: "TerminateThread".}
proc setThreadAffinityMask*(hThread: SysThread, dwThreadAffinityMask: uint) {.
importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".}
elif defined(genode):
const
GenodeHeader* = "genode_cpp/threads.h"
type
SysThread* {.importcpp: "Nim::SysThread",
header: GenodeHeader, final, pure.} = object
GenodeThreadProc* = proc (x: pointer) {.noconv.}
proc initThread*(s: var SysThread,
env: GenodeEnv,
stackSize: culonglong,
entry: GenodeThreadProc,
arg: pointer,
affinity: cuint) {.
importcpp: "#.initThread(@)".}
else:
when not (defined(macosx) or defined(haiku)):
{.passl: "-pthread".}
when not defined(haiku):
{.passc: "-pthread".}
const
schedh = "#define _GNU_SOURCE\n#include <sched.h>"
pthreadh* = "#define _GNU_SOURCE\n#include <pthread.h>"
when not declared(Time):
when defined(linux):
type Time = clong
else:
type Time = int
when (defined(linux) or defined(nintendoswitch)) and defined(amd64):
type
SysThread* {.importc: "pthread_t",
header: "<sys/types.h>" .} = distinct culong
Pthread_attr* {.importc: "pthread_attr_t",
header: "<sys/types.h>".} = object
abi: array[56 div sizeof(clong), clong]
elif defined(openbsd) and defined(amd64):
type
SysThread* {.importc: "pthread_t", header: "<pthread.h>".} = object
Pthread_attr* {.importc: "pthread_attr_t",
header: "<pthread.h>".} = object
else:
type
SysThread* {.importc: "pthread_t", header: "<sys/types.h>".} = int
Pthread_attr* {.importc: "pthread_attr_t",
header: "<sys/types.h>".} = object
type
Timespec* {.importc: "struct timespec", header: "<time.h>".} = object
tv_sec*: Time
tv_nsec*: clong
proc pthread_attr_init*(a1: var Pthread_attr): cint {.
importc, header: pthreadh.}
proc pthread_attr_setstack*(a1: ptr Pthread_attr, a2: pointer, a3: int): cint {.
importc, header: pthreadh.}
proc pthread_attr_setstacksize*(a1: var Pthread_attr, a2: int): cint {.
importc, header: pthreadh.}
proc pthread_attr_destroy*(a1: var Pthread_attr): cint {.
importc, header: pthreadh.}
proc pthread_create*(a1: var SysThread, a2: var Pthread_attr,
a3: proc (x: pointer): pointer {.noconv.},
a4: pointer): cint {.importc: "pthread_create",
header: pthreadh.}
proc pthread_join*(a1: SysThread, a2: ptr pointer): cint {.
importc, header: pthreadh.}
proc pthread_cancel*(a1: SysThread): cint {.
importc: "pthread_cancel", header: pthreadh.}
type CpuSet* {.importc: "cpu_set_t", header: schedh.} = object
when defined(linux) and defined(amd64):
abi: array[1024 div (8 * sizeof(culong)), culong]
proc cpusetZero*(s: var CpuSet) {.importc: "CPU_ZERO", header: schedh.}
proc cpusetIncl*(cpu: cint; s: var CpuSet) {.
importc: "CPU_SET", header: schedh.}
when defined(android):
# libc of android doesn't implement pthread_setaffinity_np,
# it exposes pthread_gettid_np though, so we can use that in combination
# with sched_setaffinity to set the thread affinity.
type Pid* {.importc: "pid_t", header: "<sys/types.h>".} = int32 # From posix_other.nim
proc setAffinityTID*(tid: Pid; setsize: csize_t; s: var CpuSet) {.
importc: "sched_setaffinity", header: schedh.}
proc pthread_gettid_np*(thread: SysThread): Pid {.
importc: "pthread_gettid_np", header: pthreadh.}
proc setAffinity*(thread: SysThread; setsize: csize_t; s: var CpuSet) =
setAffinityTID(pthread_gettid_np(thread), setsize, s)
else:
proc setAffinity*(thread: SysThread; setsize: csize_t; s: var CpuSet) {.
importc: "pthread_setaffinity_np", header: pthreadh.}
const
emulatedThreadVars* = compileOption("tlsEmulation")
# we preallocate a fixed size for thread local storage, so that no heap
# allocations are needed. Currently less than 16K are used on a 64bit machine.
# We use `float` for proper alignment:
const nimTlsSize {.intdefine.} = 16000
type
ThreadLocalStorage* = array[0..(nimTlsSize div sizeof(float)), float]
PGcThread* = ptr GcThread
GcThread* {.pure, inheritable.} = object
when emulatedThreadVars:
tls*: ThreadLocalStorage
else:
nil
when hasSharedHeap:
next*, prev*: PGcThread
stackBottom*, stackTop*: pointer
stackSize*: int
else:
nil
const hasAllocStack* = defined(zephyr) # maybe freertos too?
type
Thread*[TArg] = object
core*: PGcThread
sys*: SysThread
when TArg is void:
dataFn*: proc () {.nimcall, gcsafe.}
else:
dataFn*: proc (m: TArg) {.nimcall, gcsafe.}
data*: TArg
when hasAllocStack:
rawStack*: pointer
proc `=copy`*[TArg](x: var Thread[TArg], y: Thread[TArg]) {.error.}
|