-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
Copy paththreadtypes.nim
177 lines (146 loc) · 6.2 KB
/
threadtypes.nim
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
177
include system/inclrtl
import std/atomics
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*: Atomic[proc () {.nimcall, gcsafe.}]
else:
dataFn*: Atomic[proc (m: TArg) {.nimcall, gcsafe.}]
data*: TArg
when hasAllocStack:
rawStack*: pointer
proc `=copy`*[TArg](x: var Thread[TArg], y: Thread[TArg]) {.error.}