Re: [PATCH] Add thread-local storage for POSIX-y platforms.
[Thread Prev] | [Thread Next]
- Subject: Re: [PATCH] Add thread-local storage for POSIX-y platforms.
- From: Ori Bernstein <ori@xxxxxxxxxxxxxx>
- Reply-to: myrddin-dev@xxxxxxxxxxxxxx
- Date: Thu, 18 Oct 2018 23:23:05 -0700
- To: myrddin-dev@xxxxxxxxxxxxxx
- Cc: iriri <iri@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Sorry about taking so long, this month is extremely extremely busy for me. I'm pushing this into a the `tls` branch as I test it more, and add support on non-posixy platforms. Hopefully we can get this landed soon, and I can start messing with it for things like the memory allocator. On Sat, 13 Oct 2018 13:58:52 -0700, iriri <iri@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> wrote: > This patch implements thread-local storage by using a segment register > to store pointers to regions of memory unique to each thread. In spawned > threads, this region starts above the top of the stack, while in the > main thread, this region is initially statically allocated so it can be > used in `__init__` functions and dynamically reallocated if it needs to > grow beyond 8 slots. The api consists of 3 functions: `tlsalloc()`, > which must be called from the main thread, allocates a slot and returns > a key to be used with `settls(k, v)` and `gettls(k)`. Each thread > inherits its tls slots from the thread that spawned it and any slot > added after a given thread is spawned is not available in that thread. > > Adding tls regions gives threads an easy way to get their own tids, > allowing us to add some basic correctness checks to the mutex code. A > pointer to the base of the stack and the size of the mapping are also > stored in the tls region, making it easy to support user-specified stack > sizes in the future. > > Changes from previous version: > - Fixed size of main tls static allocation. > - More comments, less magic. > - Fixed typo in start+osx-x64.s exit+{freebsd,linux,openbsd}-x64.s > - `gettlskey` renamed to `tlsalloc`. > - `key` is now `tlskey(@a#)`, improving safety. > - Test is slightly less bad. > > --- > bld.tags | 4 ++ > lib/sys/sys+freebsd-x64.myr | 12 +++- > lib/sys/sys+linux-x64.myr | 16 ++++- > lib/sys/sys+netbsd-x64.myr | 23 +++++++ > lib/sys/sys+openbsd-x64.myr | 2 +- > lib/sys/sys+openbsd:6.1-x64.myr | 4 +- > lib/sys/sys+openbsd:6.2-x64.myr | 6 +- > lib/sys/sys+openbsd:6.3-x64.myr | 4 +- > lib/thread/bld.sub | 12 ++++ > lib/thread/common.myr | 4 +- > lib/thread/exit+freebsd-x64.s | 11 +-- > lib/thread/exit+linux-x64.s | 13 +--- > lib/thread/exit+openbsd-x64.s | 11 +-- > lib/thread/fsbase+freebsd.myr | 28 ++++++++ > lib/thread/fsbase+linux.myr | 28 ++++++++ > lib/thread/fsbase+netbsd.myr | 28 ++++++++ > lib/thread/fsbase+openbsd.myr | 16 +++++ > lib/thread/mutex+futex.myr | 43 +++++++++++- > lib/thread/mutex.myr | 1 - > lib/thread/rwlock+futex.myr | 27 +++++++- > lib/thread/spawn+freebsd.myr | 78 ++++++++++++---------- > lib/thread/spawn+linux.myr | 63 ++++++++--------- > lib/thread/spawn+openbsd.myr | 60 +++++++++-------- > lib/thread/spawn+osx.myr | 68 +++++++++---------- > lib/thread/start+osx-x64.s | 11 +-- > lib/thread/test/die.myr | 8 +++ > lib/thread/test/tls.myr | 49 ++++++++++++++ > lib/thread/tls+fsbase.myr | 59 ++++++++++++++++ > lib/thread/tls+osx.myr | 70 +++++++++++++++++++ > lib/thread/tls-impl+fsbase-x64.s | 48 +++++++++++++ > lib/thread/tls-impl+osx-x64.s | 64 ++++++++++++++++++ > lib/thread/types+fsbase.myr | 19 ++++++ > lib/thread/types+osx.myr | 20 ++++++ > mk/bootstrap/bootstrap+Darwin-x86_64.sh | 11 +-- > mk/bootstrap/bootstrap+FreeBSD-amd64.sh | 12 ++-- > mk/bootstrap/bootstrap+Linux-x86_64.sh | 12 ++-- > mk/bootstrap/bootstrap+NetBSD-amd64.sh | 12 ++-- > mk/bootstrap/bootstrap+OpenBSD-amd64.sh | 12 ++-- > rt/start-freebsd.s | 15 +++++ > rt/start-linux.s | 11 +++ > rt/start-netbsd.s | 15 +++++ > rt/start-openbsd.s | 10 +++ > rt/start-osx.s | 11 +++ > support/syscall-gen/types+freebsd-x64.frag | 8 +++ > support/syscall-gen/types+linux-x64.frag | 7 ++ > 45 files changed, 834 insertions(+), 212 deletions(-) > create mode 100644 lib/thread/fsbase+freebsd.myr > create mode 100644 lib/thread/fsbase+linux.myr > create mode 100644 lib/thread/fsbase+netbsd.myr > create mode 100644 lib/thread/fsbase+openbsd.myr > create mode 100644 lib/thread/test/die.myr > create mode 100644 lib/thread/test/tls.myr > create mode 100644 lib/thread/tls+fsbase.myr > create mode 100644 lib/thread/tls+osx.myr > create mode 100644 lib/thread/tls-impl+fsbase-x64.s > create mode 100644 lib/thread/tls-impl+osx-x64.s > create mode 100644 lib/thread/types+fsbase.myr > create mode 100644 lib/thread/types+osx.myr > > diff --git a/bld.tags b/bld.tags > index ce47dd11..c6eae4a7 100644 > --- a/bld.tags > +++ b/bld.tags > @@ -1,3 +1,7 @@ > +fsbase: freebsd > +fsbase: linux > +fsbase: netbsd > +fsbase: openbsd > futex: freebsd > futex: linux > futex: openbsd:6.2 > diff --git a/lib/sys/sys+freebsd-x64.myr b/lib/sys/sys+freebsd-x64.myr > index b89e99b9..73821b4f 100644 > --- a/lib/sys/sys+freebsd-x64.myr > +++ b/lib/sys/sys+freebsd-x64.myr > @@ -38,6 +38,7 @@ pkg sys = > type cpulevel = int > type cpusetid = int > type idtype = int > + type sysarchop = int64 > > type acltype = int > type acltag = uint32 > @@ -802,6 +803,13 @@ pkg sys = > const Siglwp : signo = Sigthr > const Siglibrt : signo = 33 /* reserved by real-time library. */ > > + /* sysarch ops */ > + const Archamd64getfs : sysarchop = 128 > + const Archamd64setfs : sysarchop = 129 > + const Archamd64getgs : sysarchop = 130 > + const Archamd64setgs : sysarchop = 131 > + const Archamd64getxfpu : sysarchop = 132 > + > extern const syscall : (sc:scno, args:... -> int64) > extern var __cenvp : byte## > > @@ -1285,7 +1293,7 @@ pkg sys = > const quotactl : (path : byte#, cmd : int, uid : int, arg : void# -> int) > const lgetfh : (fname : byte#, fhp : fhandle# -> int) > const getfh : (fname : byte#, fhp : fhandle# -> int) > - const sysarch : (op : int, parms : byte# -> int) > + const sysarch : (op : sysarchop, parms : void## -> int) > const rtprio : (function : int, pid : pid, rtp : rtprio# -> int) > const setfib : (fibnum : int -> int) > const ntp_adjtime : (tp : timex# -> int) > @@ -1969,7 +1977,7 @@ const getfh = {fname, fhp > -> (syscall(Sysgetfh, a(fname), a(fhp)) : int) > } > const sysarch = {op, parms > - -> (syscall(Syssysarch, a(op), a(parms)) : int) > + -> (syscall(Syssysarch, op, a(parms)) : int) > } > const rtprio = {function, pid, rtp > -> (syscall(Sysrtprio, a(function), a(pid), a(rtp)) : int) > diff --git a/lib/sys/sys+linux-x64.myr b/lib/sys/sys+linux-x64.myr > index 61bb8b2d..bbfb6897 100644 > --- a/lib/sys/sys+linux-x64.myr > +++ b/lib/sys/sys+linux-x64.myr > @@ -45,6 +45,7 @@ pkg sys = > type mfdflags = uint32 > type aiocontext = uint64 > type msg = void# > + type arch_prctlop = uint64 > > > type clock = union > @@ -590,6 +591,12 @@ pkg sys = > > /* return value for a failed mapping */ > const Mapbad : byte# = (-1 : byte#) > + > + /* arch_prctl ops */ > + const Archsetgs : arch_prctlop = 0x1001 > + const Archsetfs : arch_prctlop = 0x1002 > + const Archgetfs : arch_prctlop = 0x1003 > + const Archgetgs : arch_prctlop = 0x1004 > > /* signal flags */ > const Sanocldstop : sigflags = 0x00000001 > @@ -1097,6 +1104,7 @@ pkg sys = > const Sysmq_notify : scno = 244 > const Sysmq_getsetattr : scno = 245 > const Sysprctl : scno = 157 > + const Sysarch_prctl : scno = 158 > const Sysswapon : scno = 167 > const Sysswapoff : scno = 168 > const Sys_sysctl : scno = 156 > @@ -1308,7 +1316,7 @@ pkg sys = > const settimeofday : (tv : timeval#, tz : timezone# -> int64) > const adjtimex : (txc_p : timex# -> int64) > const times : (tbuf : tms# -> int64) > - const gettid : ( -> int64) > + const gettid : ( -> pid) > const alarm : (seconds : uint -> int64) > const getppid : ( -> int64) > const geteuid : ( -> int64) > @@ -1484,6 +1492,7 @@ pkg sys = > const mq_notify : (mqdes : int, notification : sigevent# -> int64) > const mq_getsetattr : (mqdes : int, mqstat : mq_attr#, omqstat : mq_attr# -> int64) > const prctl : (option : int, arg2 : uint64, arg3 : uint64, arg4 : uint64, arg5 : uint64 -> int64) > + const arch_prctl : (op : arch_prctlop, addr : void# -> int64) > const swapon : (specialfile : byte#, swap_flags : int -> int64) > const swapoff : (specialfile : byte# -> int64) > const _sysctl : (args : sysctl_args# -> int64) > @@ -1782,7 +1791,7 @@ const times = {tbuf > -> (syscall(Systimes, a(tbuf)) : int64) > } > const gettid = { > - -> (syscall(Sysgettid) : int64) > + -> (syscall(Sysgettid) : pid) > } > const alarm = {seconds > -> (syscall(Sysalarm, a(seconds)) : int64) > @@ -2309,6 +2318,9 @@ const mq_getsetattr = {mqdes, mqstat, omqstat > const prctl = {option, arg2, arg3, arg4, arg5 > -> (syscall(Sysprctl, a(option), a(arg2), a(arg3), a(arg4), a(arg5)) : int64) > } > +const arch_prctl = {op, addr > + -> syscall(Sysarch_prctl, op, addr) > +} > const swapon = {specialfile, swap_flags > -> (syscall(Sysswapon, a(specialfile), a(swap_flags)) : int64) > } > diff --git a/lib/sys/sys+netbsd-x64.myr b/lib/sys/sys+netbsd-x64.myr > index 8e22c0b7..5fd3bb04 100644 > --- a/lib/sys/sys+netbsd-x64.myr > +++ b/lib/sys/sys+netbsd-x64.myr > @@ -18,6 +18,7 @@ pkg sys = > type umtxop = int32 > type signo = int32 > type sigflags = int32 > + type sysarchop = int64 > > type clock = union > `Clockrealtime > @@ -344,6 +345,21 @@ pkg sys = > const Umtxmtxwake2 : umtxop = 22 > const Umtxmax : umtxop = 23 > > + /* sysarch ops */ > + const X8664getldt : sysarchop = 0 > + const X8664setldt : sysarchop = 1 > + const X8664iopl : sysarchop = 2 > + const X8664getioperm : sysarchop = 3 > + const X8664setioperm : sysarchop = 4 > + const X8664oldvm86 : sysarchop = 5 > + const X8664getmtrr : sysarchop = 11 > + const X8664setmtrr : sysarchop = 12 > + const X8664vm86 : sysarchop = 13 > + const X8664getgsbase : sysarchop = 14 > + const X8664getfsbase : sysarchop = 15 > + const X8664setgsbase : sysarchop = 16 > + const X8664setfsbase : sysarchop = 17 > + > /* signal actions */ > const Saonstack : sigflags = 0x0001 /* take signal on signal stack */ > const Sarestart : sigflags = 0x0002 /* restart system call on signal return */ > @@ -908,6 +924,9 @@ pkg sys = > new : void#, newsz : size# \ > -> int) > > + /* misc */ > + const sysarch : (op : sysarchop, args : void## -> int) > + > extern const cstring : (str : byte[:] -> byte#) > /* filled by start code */ > extern var __cenvp : byte## > @@ -1102,6 +1121,10 @@ const sysctl = {mib, old, oldsz, new, newsz > (mib : int#), a(mib.len), old, oldsz, new, newsz) : int) > } > > +const sysarch = {op, args > + -> (syscall(Syssysarch, op, args) : int) > +} > + > const clockid = {clk > match clk > | `Clockrealtime: -> 0 > diff --git a/lib/sys/sys+openbsd-x64.myr b/lib/sys/sys+openbsd-x64.myr > index a2601344..d840608f 100644 > --- a/lib/sys/sys+openbsd-x64.myr > +++ b/lib/sys/sys+openbsd-x64.myr > @@ -215,7 +215,7 @@ pkg sys = > const Mfixed : mopt = 0x10 > const Mfile : mopt = 0x0 > const Manon : mopt = 0x1000 > - const Mstack : mopt = 0x4000 > + const Mstack : mopt = 0x0 > const Mnoreplace : mopt = 0x0800 > > /* file types */ > diff --git a/lib/sys/sys+openbsd:6.1-x64.myr b/lib/sys/sys+openbsd:6.1-x64.myr > index 93143945..9ac648a2 100644 > --- a/lib/sys/sys+openbsd:6.1-x64.myr > +++ b/lib/sys/sys+openbsd:6.1-x64.myr > @@ -1031,7 +1031,7 @@ pkg sys = > const symlinkat : (path : byte#, fd : int, link : byte# -> int) > const unlinkat : (fd : int, path : byte#, flag : int -> int) > const __set_tcb : (tcb : void# -> void) > - const __get_tcb : ( -> void) > + const __get_tcb : ( -> void#) > ;; > > /* start manual overrides { */ > @@ -1750,5 +1750,5 @@ const __set_tcb = {tcb > -> (syscall(Sys__set_tcb, a(tcb)) : void) > } > const __get_tcb = { > - -> (syscall(Sys__get_tcb) : void) > + -> (syscall(Sys__get_tcb) : void#) > } > diff --git a/lib/sys/sys+openbsd:6.2-x64.myr b/lib/sys/sys+openbsd:6.2-x64.myr > index 598d3817..d89b7023 100644 > --- a/lib/sys/sys+openbsd:6.2-x64.myr > +++ b/lib/sys/sys+openbsd:6.2-x64.myr > @@ -348,7 +348,7 @@ pkg sys = > const Mfixed : mopt = 0x10 > const Mfile : mopt = 0x0 > const Manon : mopt = 0x1000 > - const Mstack : mopt = 0x4000 > + const Mstack : mopt = 0x0 > const Mnoreplace : mopt = 0x0800 > > /* file types */ > @@ -1037,7 +1037,7 @@ pkg sys = > const symlinkat : (path : byte#, fd : int, link : byte# -> int) > const unlinkat : (fd : int, path : byte#, flag : int -> int) > const __set_tcb : (tcb : void# -> void) > - const __get_tcb : ( -> void) > + const __get_tcb : ( -> void#) > ;; > > /* start manual overrides { */ > @@ -1759,5 +1759,5 @@ const __set_tcb = {tcb > -> (syscall(Sys__set_tcb, a(tcb)) : void) > } > const __get_tcb = { > - -> (syscall(Sys__get_tcb) : void) > + -> (syscall(Sys__get_tcb) : void#) > } > diff --git a/lib/sys/sys+openbsd:6.3-x64.myr b/lib/sys/sys+openbsd:6.3-x64.myr > index d013643e..ac7170b2 100644 > --- a/lib/sys/sys+openbsd:6.3-x64.myr > +++ b/lib/sys/sys+openbsd:6.3-x64.myr > @@ -1036,7 +1036,7 @@ pkg sys = > const symlinkat : (path : byte#, fd : int, link : byte# -> int) > const unlinkat : (fd : int, path : byte#, flag : int -> int) > const __set_tcb : (tcb : void# -> void) > - const __get_tcb : ( -> void) > + const __get_tcb : ( -> void#) > ;; > > /* start manual overrides { */ > @@ -1755,5 +1755,5 @@ const __set_tcb = {tcb > -> (syscall(Sys__set_tcb, a(tcb)) : void) > } > const __get_tcb = { > - -> (syscall(Sys__get_tcb) : void) > + -> (syscall(Sys__get_tcb) : void#) > } > diff --git a/lib/thread/bld.sub b/lib/thread/bld.sub > index c3800918..57aed13c 100644 > --- a/lib/thread/bld.sub > +++ b/lib/thread/bld.sub > @@ -14,6 +14,11 @@ lib thread = > sem.myr > waitgrp.myr > > + # fsbase-based impls > + tls+fsbase.myr > + tls-impl+fsbase-x64.s > + types+fsbase.myr > + > # futex-based impls > mutex+futex.myr > rwlock+futex.myr > @@ -23,6 +28,7 @@ lib thread = > # linux impl of basic thread primitives > condvar+linux.myr > exit+linux-x64.s > + fsbase+linux.myr > futex+linux.myr > ncpu+linux.myr > spawn+linux.myr > @@ -30,6 +36,7 @@ lib thread = > # freebsd impl of thread primitives > condvar+freebsd.myr > exit+freebsd-x64.s > + fsbase+freebsd.myr > futex+freebsd.myr > ncpu+freebsd.myr > spawn+freebsd.myr > @@ -37,6 +44,7 @@ lib thread = > # netbsd impl of thread primitives > #condvar+netbsd.myr > #mutex+netbsd.myr > + fsbase+netbsd.myr > spawn+netbsd.myr > #ncpu+netbsd.myr > #exit+netbsd-x64.s > @@ -46,6 +54,9 @@ lib thread = > futex+osx.myr > spawn+osx.myr > start+osx-x64.s > + tls+osx.myr > + tls-impl+osx-x64.s > + types+osx.myr > > # 9front impl of thread primitives > #condvar+plan9.myr > @@ -58,6 +69,7 @@ lib thread = > # openbsd impl of thread primitives > condvar+openbsd:6.2.myr > exit+openbsd-x64.s > + fsbase+openbsd.myr > futex+openbsd:6.2.myr > ncpu+openbsd.myr > spawn+openbsd.myr > diff --git a/lib/thread/common.myr b/lib/thread/common.myr > index 66fc9d56..3e4f1f5c 100644 > --- a/lib/thread/common.myr > +++ b/lib/thread/common.myr > @@ -1,5 +1,3 @@ > -use std > - > -pkg thread = > +pkg thread = > pkglocal generic Zptr : @a# = (0 : @a#) > ;; > diff --git a/lib/thread/exit+freebsd-x64.s b/lib/thread/exit+freebsd-x64.s > index d8952b6d..45a4bb72 100644 > --- a/lib/thread/exit+freebsd-x64.s > +++ b/lib/thread/exit+freebsd-x64.s > @@ -1,19 +1,12 @@ > /* > const thread.exit : (stacksz : std.size -> void) > -NOTE: must be called from the bottom of the stack, since > -we assume that %rbp is in the top 4k of the stack. > */ > .globl thread$exit > thread$exit: > - /* find top of stack */ > - movq %rbp,%rdi /* addr */ > - andq $~0xfff,%rdi /* align it */ > - addq $0x1000,%rdi > - > /* munmap(base, size) */ > movq $73,%rax /* munmap */ > - movq -8(%rdi),%rsi /* size */ > - subq %rsi,%rdi /* move to base ptr */ > + movq %fs:0x08,%rdi /* base */ > + movq %fs:0x10,%rsi /* stksz */ > syscall > > /* thr_exit(null) */ > diff --git a/lib/thread/exit+linux-x64.s b/lib/thread/exit+linux-x64.s > index a54e8026..d736f6d1 100644 > --- a/lib/thread/exit+linux-x64.s > +++ b/lib/thread/exit+linux-x64.s > @@ -1,19 +1,12 @@ > /* > -const thread.exit : (stacksz : std.size -> void) > -NOTE: must be called from the bottom of the stack, since > -we assume that %rbp is in the top 4k of the stack. > +const thread.exit : (-> void) > */ > .globl thread$exit > thread$exit: > - /* find top of stack */ > - movq %rbp,%rdi /* addr */ > - andq $~0xfff,%rdi /* align it */ > - addq $0x1000,%rdi > - > /* munmap(base, size) */ > movq $11,%rax /* munmap */ > - movq -8(%rdi),%rsi /* size */ > - subq %rsi,%rdi /* move to base ptr */ > + movq %fs:0x08,%rdi /* base */ > + movq %fs:0x10,%rsi /* stksz */ > syscall > > /* thread_exit(0) */ > diff --git a/lib/thread/exit+openbsd-x64.s b/lib/thread/exit+openbsd-x64.s > index 6421cc3a..0eaf63a2 100644 > --- a/lib/thread/exit+openbsd-x64.s > +++ b/lib/thread/exit+openbsd-x64.s > @@ -1,15 +1,8 @@ > /* > const thread.exit : (stacksz : std.size -> void) > -NOTE: must be called from the bottom of the stack, since > -we assume that %rbp is in the top 4k of the stack. > */ > .globl thread$exit > thread$exit: > - /* find top of stack */ > - movq %rbp,%rdi /* addr */ > - andq $~0xfff,%rdi /* align it */ > - addq $0x1000,%rdi > - > /* > Because OpenBSD wants a valid stack whenever > we enter the kernel, we need to toss a preallocated > @@ -19,8 +12,8 @@ thread$exit: > > /* munmap(base, size) */ > movq $73,%rax /* munmap */ > - movq -8(%rdi),%rsi /* size */ > - subq %rsi,%rdi /* move to base ptr */ > + movq %fs:0x08,%rdi /* base */ > + movq %fs:0x10,%rsi /* stksz */ > syscall > > /* __threxit(0) */ > diff --git a/lib/thread/fsbase+freebsd.myr b/lib/thread/fsbase+freebsd.myr > new file mode 100644 > index 00000000..e648aba0 > --- /dev/null > +++ b/lib/thread/fsbase+freebsd.myr > @@ -0,0 +1,28 @@ > +use std > +use sys > + > +use "types" > + > +pkg thread = > + pkglocal const setfsbase : (h : tlshdr# -> void) > + pkglocal const getfsbase : (-> tlshdr#) > +;; > + > +const setfsbase = {h > + match sys.sysarch(sys.Archamd64setfs, &(h : void#)) > + | 0: > + | err: > + std.fput(std.Err, "error: sysarch returned {}\n", err) > + std.suicide() > + ;; > +} > + > +const getfsbase = { > + var h > + match sys.sysarch(sys.Archamd64getfs, &h) > + | 0: -> (h : tlshdr#) > + | err: > + std.fput(std.Err, "error: sysarch returned {}\n", err) > + std.suicide() > + ;; > +} > diff --git a/lib/thread/fsbase+linux.myr b/lib/thread/fsbase+linux.myr > new file mode 100644 > index 00000000..1641a649 > --- /dev/null > +++ b/lib/thread/fsbase+linux.myr > @@ -0,0 +1,28 @@ > +use std > +use sys > + > +use "types" > + > +pkg thread = > + pkglocal const setfsbase : (h : tlshdr# -> void) > + pkglocal const getfsbase : (-> tlshdr#) > +;; > + > +const setfsbase = {h > + match sys.arch_prctl(sys.Archsetfs, (h : void#)) > + | 0: > + | err: > + std.fput(std.Err, "error: arch_prctl returned {}\n", err) > + std.suicide() > + ;; > +} > + > +const getfsbase = { > + var h : tlshdr# > + match sys.arch_prctl(sys.Archgetfs, (&h : void#)) > + | 0: -> h > + | err: > + std.fput(std.Err, "error: arch_prctl returned {}\n", err) > + std.suicide() > + ;; > +} > diff --git a/lib/thread/fsbase+netbsd.myr b/lib/thread/fsbase+netbsd.myr > new file mode 100644 > index 00000000..3c470cf1 > --- /dev/null > +++ b/lib/thread/fsbase+netbsd.myr > @@ -0,0 +1,28 @@ > +use std > +use sys > + > +use "types" > + > +pkg thread = > + pkglocal const setfsbase : (h : tlshdr# -> void) > + pkglocal const getfsbase : (-> tlshdr#) > +;; > + > +const setfsbase = {h > + match sys.sysarch(sys.X8664setfsbase, &(h : void#)) > + | 0: > + | err: > + std.fput(std.Err, "error: sysarch returned: {}\n", err) > + std.suicide() > + ;; > +} > + > +const getfsbase = { > + var h > + match sys.sysarch(sys.X8664getfsbase, &h) > + | 0: -> (h : tlshdr#) > + | err: > + std.fput(std.Err, "error: sysarch returned: {}\n", err) > + std.suicide() > + ;; > +} > diff --git a/lib/thread/fsbase+openbsd.myr b/lib/thread/fsbase+openbsd.myr > new file mode 100644 > index 00000000..7ae92b27 > --- /dev/null > +++ b/lib/thread/fsbase+openbsd.myr > @@ -0,0 +1,16 @@ > +use sys > + > +use "types" > + > +pkg thread = > + pkglocal const setfsbase : (h : tlshdr# -> void) > + pkglocal const getfsbase : (-> tlshdr#) > +;; > + > +const setfsbase = {h > + sys.__set_tcb((h : void#)) > +} > + > +const getfsbase = { > + -> (sys.__get_tcb() : tlshdr#) > +} > diff --git a/lib/thread/mutex+futex.myr b/lib/thread/mutex+futex.myr > index 50e8406d..bb9012d8 100644 > --- a/lib/thread/mutex+futex.myr > +++ b/lib/thread/mutex+futex.myr > @@ -1,9 +1,14 @@ > +use std > + > use "atomic" > use "futex" > +use "tls" > +use "types" > > pkg thread = > type mutex = struct > _state : ftxtag > + _owner : tid > ;; > > const mkmtx : (-> mutex) > @@ -21,12 +26,19 @@ const Contended = 2 > var nspin = 10 /* FIXME: pick a sane number, based on CPU count */ > > const mkmtx = { > - -> [._state = Unlocked] > + -> [._state = Unlocked, ._owner = -1] > } > > const mtxlock = {mtx > var c > > + if mtx._owner == tid() > + std.fput(std.Err, > + "error: thread {} attempted to relock a mutex it already holds\n", > + tid()) > + std.suicide() > + ;; > + > /* > Uncontended case: we get an unlocked mutex, and we lock it. > */ > @@ -34,6 +46,7 @@ const mtxlock = {mtx > for var i = 0; i < nspin; i++ > c = xcas(&mtx._state, Unlocked, Locked) > if c == Unlocked > + mtx._owner = tid() > -> void > ;; > ;; > @@ -51,13 +64,31 @@ const mtxlock = {mtx > ftxwait(&mtx._state, Contended, -1) > c = xchg(&mtx._state, Contended) > ;; > + mtx._owner = tid() > } > > const mtxtrylock = {mtx > - -> xcas(&mtx._state, Unlocked, Locked) == Unlocked > + if xcas(&mtx._state, Unlocked, Locked) == Unlocked > + mtx._owner = tid() > + -> true > + ;; > + -> false > } > > const mtxunlock = {mtx > + /* > + Nonatomically loading mtx._owner may produce false negatives on > + weakly-ordered architectures but having to atomically store and load > + mtx._owner doesn't seem worth it. > + */ > + if mtx._owner != tid() > + std.fput(std.Err, > + "error: thread {} attempted to unlock a mutex last held by {}\n", > + tid(), mtx._owner) > + std.suicide() > + ;; > + mtx._owner = -1 > + > /* > Either the lock is contended or it's uncontended. Any other > state is a bug. > @@ -72,7 +103,15 @@ const mtxunlock = {mtx > } > > const mtxcontended = {mtx > + if mtx._owner == tid() > + std.fput(std.Err, > + "error: thread {} attempted to relock a mutex it already holds\n", > + tid()) > + std.suicide() > + ;; > + > while xchg(&mtx._state, Contended) != Unlocked > ftxwait(&mtx._state, Contended, -1) > ;; > + mtx._owner = tid() > } > diff --git a/lib/thread/mutex.myr b/lib/thread/mutex.myr > index b37f2fb3..100ab450 100644 > --- a/lib/thread/mutex.myr > +++ b/lib/thread/mutex.myr > @@ -1,5 +1,4 @@ > use std > -use sys > > use "atomic" > > diff --git a/lib/thread/rwlock+futex.myr b/lib/thread/rwlock+futex.myr > index 4975c953..a1174405 100644 > --- a/lib/thread/rwlock+futex.myr > +++ b/lib/thread/rwlock+futex.myr > @@ -2,6 +2,8 @@ use std > > use "atomic" > use "futex" > +use "tls" > +use "types" > > pkg thread = > /* > @@ -13,6 +15,7 @@ pkg thread = > */ > type rwlock = struct > _state : ftxtag > + _owner : tid > ;; > > const mkrwlock : (-> rwlock) > @@ -28,7 +31,7 @@ const Nrmask = 0x7fffffff > const Waitbit = 0x80000000 > > const mkrwlock = { > - -> [._state = 0] > + -> [._state = 0, ._owner = -1] > } > > const rdlock = {rw > @@ -61,6 +64,13 @@ const rdlock = {rw > > const wrlock = {rw > for ; ; > + if rw._owner == tid() > + std.fput(std.Err, > + "error: thread {} attempted to relock an rwlock it already holds\n", > + tid()) > + std.suicide() > + ;; > + > /* > `_state` must be 0 for a writer to acquire the lock. Anything > else means the lock is either held or in the process of being > @@ -68,6 +78,7 @@ const wrlock = {rw > */ > var s = xcas(&rw._state, 0, Nrmask) > if s == 0 > + rw._owner = tid() > -> void > ;; > > @@ -98,7 +109,11 @@ const tryrdlock = {rw > } > > const trywrlock = {rw > - -> xcas(&rw._state, 0, Nrmask) == 0 > + if xcas(&rw._state, 0, Nrmask) == 0 > + rw._owner = tid() > + -> true > + ;; > + -> false > } > > const rdunlock = {rw > @@ -122,6 +137,14 @@ const rdunlock = {rw > } > > const wrunlock = {rw > + if rw._owner != tid() > + std.fput(std.Err, > + "error: thread {} attempted to unlock an rwlock last held by {}\n", > + tid(), rw._owner) > + std.suicide() > + ;; > + rw._owner = -1 > + > /* > If the wait bit was set then there are one or more waiting readers, > writers, or both. In the first and third cases, we need to wake > diff --git a/lib/thread/spawn+freebsd.myr b/lib/thread/spawn+freebsd.myr > index cdc76732..66a28bdc 100644 > --- a/lib/thread/spawn+freebsd.myr > +++ b/lib/thread/spawn+freebsd.myr > @@ -1,9 +1,12 @@ > use sys > use std > > -pkg thread = > - type tid = uint64 > +use "common" > +use "fsbase" > +use "tls" > +use "types" > > +pkg thread = > const spawn : (fn : (-> void) -> std.result(tid, byte[:])) > ;; > > @@ -16,60 +19,63 @@ const spawn = {fn > } > > const spawnstk = {fn, sz > - var stk : byte#, tid, ctid, ret > - var szp, f, tos, env, envsz > + var stk, tos, stksz, hdr, tid = -1, ret > > - stk = getstk(sz) > + stk = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0) > if stk == sys.Mapbad > -> `std.Err "couldn't get stack" > ;; > - tid = -1 > - /* find top of stack */ > - tos = (stk : std.intptr) + (sz : std.intptr) > - > - /* store the stack size */ > - tos -= sizeof(sys.size) > - sz -= sizeof(sys.size) > - szp = (tos : sys.size#) > - szp# = Stacksz > - > - /* store the function we call */ > - envsz = std.fnenvsz(fn) > - tos -= (envsz : std.intptr) > - sz -= (envsz : sys.size) > - env = tos > - tos -= sizeof((->void)) > - sz -= sizeof((->void)) > - f = (tos : (->void)#) > - f# = std.fnbdup(fn, (env : byte#)[:envsz]) > - var repr = (&fn : int64[2]#)# > + (tos, stksz, hdr) = initstk(stk, fn, sz) > > ret = sys.thr_new(&[ > .startfn = (startthread : void#), > .arg = (tos : void#), > .stkbase = (stk : byte#), > - .stksz = sz, > - .tid = &ctid, > + .stksz = stksz, > + .tid = (&hdr.tid : uint64#), > .ptid = &tid, > .flags = 2, > - .rtp = (0 : sys.rtprio#) > + .rtp = Zptr, > ], sizeof(sys.thrparam)) > > if ret < 0 > + sys.munmap(stk, sz) > -> `std.Err "couldn't spawn thread" > ;; > -> `std.Ok (tid : tid) > } > > -const getstk = {sz > - var p, m > +const initstk = {stk, fn, sz > + var stksz, len, tos, hdr, fp, env, envsz > > - p = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0) > - if p == sys.Mapbad > - -> p > - ;; > - m = (p : std.intptr) > - -> (m : byte#) > + stksz = sz > + len = tlslen() > + stksz -= (sizeof(tlshdr) + ((len : sys.size) * sizeof(void#)) + 0xf) & ~0xf > + tos = (stk : std.intptr) + (stksz : std.intptr) > + hdr = (tos : tlshdr#) > + hdr.base = stk > + hdr.stksz = sz > + > + var fn1 = { > + /* > + We write `hdr.len` here because it follows `hdr.tid` so it gets > + overwritten by the kernel in `thr_new`. Even though `sys.pid` > + is 32 bits, `thr_param.tid` is a `uint64#` for legacy reasons. > + */ > + hdr.len = len > + setfsbase(hdr) > + fn() > + } > + > + envsz = std.fnenvsz(fn1) > + tos -= (envsz : std.intptr) > + stksz -= (envsz : sys.size) > + env = tos > + tos -= sizeof((->void)) > + stksz -= sizeof((->void)) > + fp = (tos : (->void)#) > + fp# = std.fnbdup(fn1, (env : byte#)[:envsz]) > + -> ((tos : byte#), stksz, hdr) > } > > const startthread = {f : (-> void)# > diff --git a/lib/thread/spawn+linux.myr b/lib/thread/spawn+linux.myr > index a56317f7..d56ae478 100644 > --- a/lib/thread/spawn+linux.myr > +++ b/lib/thread/spawn+linux.myr > @@ -1,72 +1,67 @@ > use sys > use std > > -pkg thread = > - type tid = sys.pid > +use "common" > +use "tls" > +use "types" > > +pkg thread = > const spawn : (fn : (-> void) -> std.result(tid, byte[:])) > ;; > > +const Stacksz = 8*std.MiB > extern const exit : (-> void) > > /* Holy shit flag mania. */ > -const Thrflag = sys.Clonevm | sys.Clonefs | sys.Clonefiles | \ > - sys.Clonesighand | sys.Clonethread |sys.Clonesysvsem | \ > - sys.Clonesettls | sys.Cloneparentsettid | sys.Clonechildcleartid > - > -const Stacksz = 8*std.MiB > +const Thrflag = sys.Clonevm | sys.Clonefs | sys.Clonefiles | \ > + sys.Clonesighand | sys.Clonethread | sys.Clonesettls | \ > + sys.Clonechildsettid > > const spawn = {fn > -> spawnstk(fn, Stacksz) > } > > const spawnstk = {fn, sz > - var stk : byte#, tid, ctid, ret > + var stk, tos, hdr, ret > > - stk = getstk(sz) > + stk = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0) > if stk == sys.Mapbad > -> `std.Err "couldn't get stack" > ;; > - stk = initstack(stk, fn, Stacksz) > + (tos, hdr) = initstk(stk, fn, sz) > > - ret = sys.fnclone(Thrflag, \ > - (stk : byte#),\ > - &tid, (0 : byte#), \ > - &ctid, (0 : byte#), \ > + ret = sys.fnclone(Thrflag, > + tos, > + Zptr, > + (hdr : byte#), > + (&hdr.tid : sys.pid#), > + Zptr, > (startthread : void#)) > if ret < 0 > + sys.munmap(stk, sz) > -> `std.Err "couldn't spawn thread" > ;; > -> `std.Ok (ret : tid) > } > > -const initstack = {stk, fn, sz > - var tos, szp, fp, env, envsz > +const initstk = {stk, fn, sz > + var len, tos, hdr, fp, env, envsz > + > + len = tlslen() > + tos = (stk : std.intptr) + (sz : std.intptr) > + tos -= (sizeof(tlshdr) + ((len : std.intptr) * sizeof(void#)) + 0xf) & ~0xf > + hdr = (tos : tlshdr#) > + hdr.len = len > + hdr.base = stk > + hdr.stksz = sz > > envsz = std.fnenvsz(fn) > - tos = (stk : std.intptr) > - tos -= sizeof(int64) > - szp = (tos : sys.size#) > - szp# = sz > tos -= (envsz : std.intptr) > env = tos > tos -= sizeof((->void)) > fp = (tos : (->void)#) > fp# = std.fnbdup(fn, (env : byte#)[:envsz]) > - -> (tos : byte#) > -} > - > -const getstk = {sz > - var p, m > - > - p = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0) > - if p == sys.Mapbad > - -> p > - ;; > - /* stack starts at the top of memory and grows down. */ > - m = (p : std.intptr) > - m += (sz : std.intptr) > - -> (m : byte#) > + -> ((tos : byte#), hdr) > } > > const startthread = {fn : (-> void) > diff --git a/lib/thread/spawn+openbsd.myr b/lib/thread/spawn+openbsd.myr > index 4526520a..c63b51b8 100644 > --- a/lib/thread/spawn+openbsd.myr > +++ b/lib/thread/spawn+openbsd.myr > @@ -1,9 +1,11 @@ > use std > use sys > > -pkg thread = > - type tid = uint64 > +use "common" > +use "tls" > +use "types" > > +pkg thread = > const spawn : (fn : (-> void) -> std.result(tid, byte[:])) > pkglocal var exitstk : byte# > ;; > @@ -18,6 +20,7 @@ const __init__ = { > time to swap to before we invalidate a stack. > */ > exitstk = getstk(16) > + std.assert(exitstk != sys.Mapbad, "error: failed to mmap exitstk\n") > } > > const spawn = {fn; > @@ -25,30 +28,17 @@ const spawn = {fn; > } > > const spawnstk = {fn, sz > - var stk, szp, fp, tos, tfp, env, envsz > - var ret > + var stk, tos, hdr, tfp, ret > > stk = getstk(sz) > if stk == sys.Mapbad > -> `std.Err "couldn't get stack" > ;; > - /* store size */ > - tos = (stk : std.intptr) > - tos -= sizeof(int64) > - szp = (tos : sys.size#) > - szp# = Stacksz > - > - /* store func */ > - envsz = std.fnenvsz(fn) > - tos -= (envsz : std.intptr) > - env = tos > - tos -= sizeof((->void)) > - fp = (tos : (->void)#) > - fp# = std.fnbdup(fn, (env : byte#)[:envsz]) > + (tos, hdr) = initstk(stk, fn, sz) > > tfp = [ > - .tcb = (0 : void#), > - .tid = &ret, > + .tcb = (hdr : void#), > + .tid = (&hdr.tid : sys.pid#), > .stk = (tos : byte#), > ] > ret = sys.__tfork_thread(&tfp, > @@ -56,22 +46,34 @@ const spawnstk = {fn, sz > (startthread : void#), > (0 : void#)) > if ret < 0 > + sys.munmap(stk, sz) > -> `std.Err "couldn't spawn thread" > ;; > -> `std.Ok (ret : tid) > } > > -const getstk = {sz > - var p, m > +const initstk = {stk, fn, sz > + var len, tos, hdr, fp, env, envsz > > - p = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon | sys.Mstack, -1, 0) > - if p == sys.Mapbad > - -> p > - ;; > - /* stack starts at the top of memory and grows down. */ > - m = (p : std.intptr) > - m += (sz : std.intptr) > - -> (m : byte#) > + len = tlslen() > + tos = (stk : std.intptr) + (sz : std.intptr) > + tos -= (sizeof(tlshdr) + ((len : std.intptr) * sizeof(void#)) + 0xf) & ~0xf > + hdr = (tos : tlshdr#) > + hdr.len = len > + hdr.base = stk > + hdr.stksz = sz > + > + envsz = std.fnenvsz(fn) > + tos -= (envsz : std.intptr) > + env = tos > + tos -= sizeof((->void)) > + fp = (tos : (->void)#) > + fp# = std.fnbdup(fn, (env : byte#)[:envsz]) > + -> ((tos : byte#), hdr) > +} > + > +const getstk = {sz > + -> sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0) > } > > const startthread = {fn : (-> void) > diff --git a/lib/thread/spawn+osx.myr b/lib/thread/spawn+osx.myr > index 417e64aa..3e6ed161 100644 > --- a/lib/thread/spawn+osx.myr > +++ b/lib/thread/spawn+osx.myr > @@ -1,9 +1,10 @@ > use sys > use std > > -pkg thread = > - type tid = uint64 > +use "tls" > +use "types" > > +pkg thread = > const spawn : (fn : (-> void) -> std.result(tid, byte[:])) > ;; > > @@ -34,34 +35,13 @@ const spawn = {fn > } > > const spawnstk = {fn, sz > - var stk : byte#, tid, ret > - var szp, f, tos, env, envsz > + var stk, tos, ret > > - stk = getstk(sz) > + stk = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0) > if stk == sys.Mapbad > -> `std.Err "couldn't get stack" > ;; > - tid = -1 > - > - /* find top of stack */ > - tos = (stk : std.intptr) + (sz : std.intptr) > - > - /* store the stack size */ > - tos -= sizeof(sys.size) > - sz -= sizeof(sys.size) > - szp = (tos : sys.size#) > - szp# = Stacksz > - > - /* store the function we call */ > - envsz = std.fnenvsz(fn) > - tos -= (envsz : std.intptr) > - sz -= (envsz : sys.size) > - env = tos > - tos -= sizeof((->void)) > - sz -= sizeof((->void)) > - f = (tos : (->void)#) > - f# = std.fnbdup(fn, (env : byte#)[:envsz]) > - var repr = (&fn : int64[2]#)# > + tos = initstk(stk, fn, sz) > > ret = sys.bsdthread_create( \ > (tramp : void#), \ /* start */ > @@ -70,21 +50,37 @@ const spawnstk = {fn, sz > (0 : void#), \ /* pthread struct */ > 0x01000000) /* flags (PTHREAD_START_CUSTOM): don't alloc stack in kernel */ > > - if ret == (-1 : void#) > + if (ret : std.size) < 0 > + sys.munmap(stk, sz) > -> `std.Err "couldn't spawn thread" > ;; > - -> `std.Ok (ret : tid) > + -> `std.Ok (stk : tid) > } > > -const getstk = {sz > - var p, m > +const initstk = {stk, fn, sz > + var len, tos, hdr, fp, env, envsz > > - p = sys.mmap((0 : byte#), sz, sys.Mprotrw, sys.Mpriv | sys.Manon, -1, 0) > - if p == sys.Mapbad > - -> p > - ;; > - m = (p : std.intptr) > - -> (m : byte#) > + len = tlslen() > + tos = (stk : std.intptr) + (sz : std.intptr) > + tos -= (sizeof(tlshdr) + ((len : std.intptr) * sizeof(void#)) + 0xf) & ~0xf > + hdr = (tos : tlshdr#) > + hdr.tid = (stk : tid) > + hdr.len = len > + hdr.base = stk > + hdr.stksz = sz > + > + var fn1 = { > + setgsbase(hdr) > + fn() > + } > + > + envsz = std.fnenvsz(fn1) > + tos -= (envsz : std.intptr) > + env = tos > + tos -= sizeof((->void)) > + fp = (tos : (->void)#) > + fp# = std.fnbdup(fn1, (env : byte#)[:envsz]) > + -> (tos : byte#) > } > > /* > diff --git a/lib/thread/start+osx-x64.s b/lib/thread/start+osx-x64.s > index bb497bb8..081ed454 100644 > --- a/lib/thread/start+osx-x64.s > +++ b/lib/thread/start+osx-x64.s > @@ -15,20 +15,13 @@ _thread$start: > > /* > const thread.exit : (stacksz : std.size -> void) > -NOTE: must be called from the bottom of the stack, since > -we assume that %rbp is in the top 4k of the stack. > */ > .globl _thread$exit > _thread$exit: > - /* find top of stack */ > - movq %rbp,%rdi /* addr */ > - andq $~0xfff,%rdi /* align it */ > - addq $0x1000,%rdi > - > /* munmap(base, size) */ > movq $0x2000049,%rax /* munmap */ > - movq -8(%rdi),%rsi /* size */ > - subq %rsi,%rdi /* move to base ptr */ > + movq %gs:0x08,%rdi /* base */ > + movq %gs:0x10,%rsi /* stksz */ > syscall > > /* exit the thread */ > diff --git a/lib/thread/test/die.myr b/lib/thread/test/die.myr > new file mode 100644 > index 00000000..db0fb219 > --- /dev/null > +++ b/lib/thread/test/die.myr > @@ -0,0 +1,8 @@ > +use thread > + > +const main = { > + var m = thread.mkmtx() > + thread.mtxlock(&m) > + thread.mtxunlock(&m) > + thread.mtxunlock(&m) > +} > diff --git a/lib/thread/test/tls.myr b/lib/thread/test/tls.myr > new file mode 100644 > index 00000000..fa111111 > --- /dev/null > +++ b/lib/thread/test/tls.myr > @@ -0,0 +1,49 @@ > +use std > +use sys > +use thread > + > +const Nelt = 100 > +const Nthr = 100 > + > +var elts : thread.tid[Nelt] > +var start > +var wg > + > +const setget = { > + var tid = thread.tid() > + var localelts : thread.tid[Nelt] > + for var i = 0; i < Nelt; i++ > + localelts[i] = elts[i] + tid > + ;; > + > + var k = start > + for var i = 0; i < Nelt; i++ > + thread.tlsset(k, &localelts[i]) > + k++ > + ;; > + k = start > + for var i = 0; i < Nelt; i++ > + std.assert(thread.tlsget(k)# == localelts[i], "tls is broken\n") > + k++ > + ;; > + thread.wgpost(&wg) > +} > + > +const main = { > + for var i = 0; i < Nelt; i++ > + elts[i] = std.randnum() > + ;; > + > + start = thread.tlsalloc() > + for var i = 1; i < Nelt; i++ > + var k : thread.tlskey(thread.tid#) = thread.tlsalloc() > + ;; > + > + wg = thread.mkwg(Nthr) > + for var i = 1; i < 100; i++ > + thread.spawn(setget) > + ;; > + setget() > + > + thread.wgwait(&wg) > +} > diff --git a/lib/thread/tls+fsbase.myr b/lib/thread/tls+fsbase.myr > new file mode 100644 > index 00000000..0b593734 > --- /dev/null > +++ b/lib/thread/tls+fsbase.myr > @@ -0,0 +1,59 @@ > +use std > + > +use "common" > +use "fsbase" > +use "types" > + > +pkg thread = > + generic tlsalloc : (-> tlskey(@a#)) > + generic tlsset : (k : tlskey(@a#), v : @a# -> void) > + generic tlsget : (k : tlskey(@a#) -> @a#) > + extern const tid : (-> tid) > + > + pkglocal const tlsoob : (k : tlskey(void) -> void) > + pkglocal extern const tlslen : (-> tlskey(void)) > +;; > + > +const Staticcap = 8 > + > +var _hdr > +var _cap = Staticcap > + > +generic tlsalloc = { > + std.assert(tid() == 0, "error: tlsalloc must be called from main thread\n") > + if _hdr == Zptr > + /* `_hdr` is lazily initialized here since we can't set it in start.s */ > + _hdr = getfsbase() > + ;; > + > + if _hdr.len++ == _cap > + std.assert(_cap < 0x8000_0000, "error: max tls slots exceeded\n") > + var l = sizeof(tlshdr) + ((_cap : std.size) * sizeof(void#)) > + var h = std.bytealloc(sizeof(tlshdr) + ((_cap *= 2 : std.size) * sizeof(void#))) > + > + std.memblit(h, (_hdr : byte#), l) > + setfsbase((h : tlshdr#)) > + /* this is ugly... the initial tls region is statically allocated */ > + if _cap != Staticcap * 2 > + std.bytefree((_hdr : byte#), l) > + ;; > + _hdr = (h : tlshdr#) > + ;; > + -> (_hdr.len - 1 : tlskey(@a#)) > +} > + > +generic tlsset = {k, v > + _tlsset((k : tlskey(void)), (v : void#)) > +} > + > +generic tlsget = {k > + -> (_tlsget((k : tlskey(void))) : @a#) > +} > + > +const tlsoob = {k > + std.fput(std.Err, "error: tlskey {} out of bounds {}\n", k, tlslen()) > + std.suicide() > +} > + > +extern const _tlsset : (k : tlskey(void), v : void# -> void) > +extern const _tlsget : (k : tlskey(void) -> void#) > diff --git a/lib/thread/tls+osx.myr b/lib/thread/tls+osx.myr > new file mode 100644 > index 00000000..763f3f3c > --- /dev/null > +++ b/lib/thread/tls+osx.myr > @@ -0,0 +1,70 @@ > +use std > + > +use "common" > +use "types" > + > +pkg thread = > + generic tlsalloc : (-> tlskey(@a#)) > + generic tlsset : (k : tlskey(@a#), v : @a# -> void) > + generic tlsget : (k : tlskey(@a#) -> @a#) > + extern const tid : (-> tid) > + > + pkglocal const tlsoob : (k : tlskey(void) -> void) > + pkglocal extern const tlslen : (-> tlskey(void)) > + pkglocal const setgsbase : (h : tlshdr# -> void) > + pkglocal extern const getgsbase : (-> tlshdr#) > +;; > + > +const Staticcap = 8 > + > +var _hdr > +var _cap = Staticcap > + > +generic tlsalloc = { > + std.assert(tid() == 0, "error: tlsalloc must be called from main thread\n") > + if _hdr == Zptr > + /* `_hdr` is lazily initialized here since we can't set it in start.s */ > + _hdr = getgsbase() > + ;; > + > + if _hdr.len++ == _cap > + std.assert(_cap < 0x8000_0000, "error: max tls slots exceeded\n") > + var l = sizeof(tlshdr) + ((_cap : std.size) * sizeof(void#)) > + var h = std.bytealloc(sizeof(tlshdr) + ((_cap *= 2 : std.size) * sizeof(void#))) > + > + std.memblit(h, (_hdr : byte#), l) > + setgsbase((h : tlshdr#)) > + /* this is ugly... the initial tls region is statically allocated */ > + if _cap != Staticcap * 2 > + std.bytefree((_hdr : byte#), l) > + ;; > + _hdr = (h : tlshdr#) > + ;; > + -> (_hdr.len - 1 : tlskey(@a#)) > +} > + > +generic tlsset = {k, v > + _tlsset((k : tlskey(void)), (v : void#)) > +} > + > +generic tlsget = {k > + -> (_tlsget((k : tlskey(void))) : @a#) > +} > + > +const tlsoob = {k > + std.fput(std.Err, "error: tlskey {} out of bounds {}\n", k, tlslen()) > + std.suicide() > +} > + > +const setgsbase = {h > + match _setgsbase(h) > + | 0xf: /* yes, this indicates success; no, it's not documented */ > + | err: > + std.fput(std.Err, "error: setgsbase returned {}\n", err) > + std.suicide() > + ;; > +} > + > +extern const _tlsset : (k : tlskey(void), v : void# -> void) > +extern const _tlsget : (k : tlskey(void) -> void#) > +extern const _setgsbase : (h : tlshdr# -> int64) > diff --git a/lib/thread/tls-impl+fsbase-x64.s b/lib/thread/tls-impl+fsbase-x64.s > new file mode 100644 > index 00000000..d34e4219 > --- /dev/null > +++ b/lib/thread/tls-impl+fsbase-x64.s > @@ -0,0 +1,48 @@ > +.set tid, 0x00 > +.set len, 0x04 > +.set slots, 0x18 > + > +/* const tid : (-> tid) */ > +.globl thread$tid > +.globl _thread$tid > +thread$tid: > +_thread$tid: > + movl %fs:tid, %eax > + ret > + > +/* const _tlsset : (k : key, v : void# -> void) */ > +.globl thread$_tlsset > +.globl _thread$_tlsset > +thread$_tlsset: > +_thread$_tlsset: > + cmpl %fs:len, %edi > + jnb oob > + > + movslq %edi, %rdi > + movq $slots, %r10 > + movq %rsi, %fs:(%r10, %rdi, 0x8) > + ret > + > +/* const _tlsget : (k : key -> void#) */ > +.globl thread$_tlsget > +.globl _thread$_tlsget > +thread$_tlsget: > +_thread$_tlsget: > + cmpl %fs:len, %edi > + jnb oob > + > + movslq %edi, %rdi > + movq $slots, %r10 > + movq %fs:(%r10, %rdi, 0x8), %rax > + ret > + > +oob: > + call thread$tlsoob > + > +/* const tlslen : (-> key) */ > +.globl thread$tlslen > +.globl _thread$tlslen > +thread$tlslen: > +_thread$tlslen: > + movl %fs:len, %eax > + ret > diff --git a/lib/thread/tls-impl+osx-x64.s b/lib/thread/tls-impl+osx-x64.s > new file mode 100644 > index 00000000..bbe7dcdd > --- /dev/null > +++ b/lib/thread/tls-impl+osx-x64.s > @@ -0,0 +1,64 @@ > +.set tid, 0x00 > +.set len, 0x08 > +.set self, 0x20 > +.set slots, 0x28 > + > +/* const tid : (-> tid) */ > +.globl thread$tid > +.globl _thread$tid > +thread$tid: > +_thread$tid: > + movq %gs:tid, %rax > + ret > + > +/* const _tlsset : (k : key, v : void# -> void) */ > +.globl thread$_tlsset > +.globl _thread$_tlsset > +thread$_tlsset: > +_thread$_tlsset: > + cmpq %gs:len, %rdi > + jnb oob > + > + movq $slots, %r10 > + movq %rsi, %gs:(%r10, %rdi, 0x8) > + ret > + > +/* const _tlsget : (k : key -> void#) */ > +.globl thread$_tlsget > +.globl _thread$_tlsget > +thread$_tlsget: > +_thread$_tlsget: > + cmpq %gs:len, %rdi > + jnb oob > + > + movq $slots, %r10 > + movq %gs:(%r10, %rdi, 0x8), %rax > + ret > + > +oob: > + call _thread$tlsoob > + > +/* const tlslen : (-> key) */ > +.globl thread$tlslen > +.globl _thread$tlslen > +thread$tlslen: > +_thread$tlslen: > + movq %gs:len, %rax > + ret > + > +/* const _setgsbase : (h : tlshdr# -> int64) */ > +.globl thread$_setgsbase > +.globl _thread$_setgsbase > +thread$_setgsbase: > +_thread$_setgsbase: > + movq $0x3000003, %rax /* undocumented syscall; sets %gs to %rdi */ > + syscall > + ret > + > +/* const getgsbase : (-> tlshdr#) */ > +.globl thread$getgsbase > +.globl _thread$getgsbase > +thread$getgsbase: > +_thread$getgsbase: > + movq %gs:self, %rax > + ret > diff --git a/lib/thread/types+fsbase.myr b/lib/thread/types+fsbase.myr > new file mode 100644 > index 00000000..1e3647cd > --- /dev/null > +++ b/lib/thread/types+fsbase.myr > @@ -0,0 +1,19 @@ > +use sys > + > +pkg thread = > + type tid = sys.pid /* 32 bits on all of the fsbase platforms */ > + type tlskey(@a) = uint32 > + > + /* > + XXX: Be sure to update tls-impl+fsbase.s and > + rt/start-{freebsd,linux,netbsd,openbsd}.s if any changes are made to > + the size of this struct and/or the offsets of any of its members. > + */ > + pkglocal type tlshdr = struct > + tid : tid > + len : tlskey(void) > + base : byte# > + stksz : sys.size > + slots : void#[...] > + ;; > +;; > diff --git a/lib/thread/types+osx.myr b/lib/thread/types+osx.myr > new file mode 100644 > index 00000000..bba067df > --- /dev/null > +++ b/lib/thread/types+osx.myr > @@ -0,0 +1,20 @@ > +use sys > + > +pkg thread = > + type tid = sys.pid /* 64 bits */ > + type tlskey(@a) = uint64 > + > + /* > + XXX: Be sure to update tls-impl+osx.s and rt/start-osx.s if any changes > + are made to the size of this struct and/or the offsets of any of its > + members. > + */ > + pkglocal type tlshdr = struct > + tid : tid > + len : tlskey(void) > + base : byte# > + stksz : sys.size > + self : tlshdr# > + slots : void#[...] > + ;; > +;; > diff --git a/mk/bootstrap/bootstrap+Darwin-x86_64.sh b/mk/bootstrap/bootstrap+Darwin-x86_64.sh > index 9e639571..3bc1f367 100755 > --- a/mk/bootstrap/bootstrap+Darwin-x86_64.sh > +++ b/mk/bootstrap/bootstrap+Darwin-x86_64.sh > @@ -7,6 +7,7 @@ set -x > as -g -o mbld/cpufeatures.o mbld/cpufeatures+posixy-x64.s > as -g -o lib/thread/start.o lib/thread/start+osx-x64.s > as -g -o lib/thread/atomic-impl.o lib/thread/atomic-impl+x64.s > + as -g -o lib/thread/tls-impl.o lib/thread/tls-impl+osx-x64.s > as -g -o lib/std/getbp.o lib/std/getbp+posixy-x64.s > $pwd/6/6m -I lib/sys lib/std/option.myr > $pwd/6/6m -I lib/sys lib/std/traits.myr > @@ -120,16 +121,18 @@ set -x > $pwd/6/6m -I lib/std -I lib/sys lib/bio/puti.myr > ar -rcs lib/bio/libbio.a lib/bio/puti.o lib/bio/geti.o lib/bio/fd.o lib/bio/mem.o lib/bio/bio.o lib/bio/types.o lib/bio/iter.o > $pwd/muse/muse -o lib/bio/libbio.use -p bio lib/bio/puti.use lib/bio/geti.use lib/bio/fd.use lib/bio/mem.use lib/bio/bio.use lib/bio/types.use lib/bio/iter.use > - $pwd/6/6m -I lib/sys -I lib/std lib/thread/spawn+osx.myr > - $pwd/6/6m -I lib/sys -I lib/std lib/thread/ncpu.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/common.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/atomic.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/types+osx.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/tls+osx.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/spawn+osx.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/ncpu.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/futex+osx.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/sem.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/mutex.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/hookstd.myr > - ar -rcs lib/thread/libthread.a lib/thread/mutex.o lib/thread/atomic.o lib/thread/atomic-impl.o lib/thread/hookstd.o lib/thread/sem.o lib/thread/common.o lib/thread/ncpu.o lib/thread/start.o lib/thread/futex.o lib/thread/spawn.o > - $pwd/muse/muse -o lib/thread/libthread.use -p thread lib/thread/mutex.use lib/thread/atomic.use lib/thread/hookstd.use lib/thread/sem.use lib/thread/common.use lib/thread/ncpu.use lib/thread/futex.use lib/thread/spawn.use > + ar -rcs lib/thread/libthread.a lib/thread/mutex.o lib/thread/atomic.o lib/thread/atomic-impl.o lib/thread/types.o lib/thread/tls.o lib/thread/tls-impl.o lib/thread/hookstd.o lib/thread/sem.o lib/thread/common.o lib/thread/ncpu.o lib/thread/start.o lib/thread/futex.o lib/thread/spawn.o > + $pwd/muse/muse -o lib/thread/libthread.use -p thread lib/thread/mutex.use lib/thread/atomic.use lib/thread/types.use lib/thread/tls.use lib/thread/hookstd.use lib/thread/sem.use lib/thread/common.use lib/thread/ncpu.use lib/thread/futex.use lib/thread/spawn.use > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/opts.myr > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/syssel.myr > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/libs.myr > diff --git a/mk/bootstrap/bootstrap+FreeBSD-amd64.sh b/mk/bootstrap/bootstrap+FreeBSD-amd64.sh > index b5c62b13..dd835cdb 100755 > --- a/mk/bootstrap/bootstrap+FreeBSD-amd64.sh > +++ b/mk/bootstrap/bootstrap+FreeBSD-amd64.sh > @@ -7,6 +7,7 @@ set -x > as -g -o mbld/cpufeatures.o mbld/cpufeatures+posixy-x64.s > as -g -o lib/thread/exit.o lib/thread/exit+freebsd-x64.s > as -g -o lib/thread/atomic-impl.o lib/thread/atomic-impl+x64.s > + as -g -o lib/thread/tls-impl.o lib/thread/tls-impl+fsbase-x64.s > as -g -o lib/std/getbp.o lib/std/getbp+posixy-x64.s > $pwd/6/6m -I lib/sys lib/std/option.myr > $pwd/6/6m -I lib/sys lib/std/traits.myr > @@ -120,16 +121,19 @@ set -x > $pwd/6/6m -I lib/std -I lib/sys lib/bio/puti.myr > ar -rcs lib/bio/libbio.a lib/bio/puti.o lib/bio/geti.o lib/bio/fd.o lib/bio/mem.o lib/bio/bio.o lib/bio/types.o lib/bio/iter.o > $pwd/muse/muse -o lib/bio/libbio.use -p bio lib/bio/puti.use lib/bio/geti.use lib/bio/fd.use lib/bio/mem.use lib/bio/bio.use lib/bio/types.use lib/bio/iter.use > - $pwd/6/6m -I lib/sys -I lib/std lib/thread/spawn+freebsd.myr > - $pwd/6/6m -I lib/sys -I lib/std lib/thread/ncpu+freebsd.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/common.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/atomic.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/types+fsbase.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/fsbase+freebsd.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/tls+fsbase.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/spawn+freebsd.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/ncpu+freebsd.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/futex+freebsd.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/sem.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/mutex.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/hookstd.myr > - ar -rcs lib/thread/libthread.a lib/thread/mutex.o lib/thread/atomic.o lib/thread/atomic-impl.o lib/thread/hookstd.o lib/thread/sem.o lib/thread/common.o lib/thread/ncpu.o lib/thread/exit.o lib/thread/futex.o lib/thread/spawn.o > - $pwd/muse/muse -o lib/thread/libthread.use -p thread lib/thread/mutex.use lib/thread/atomic.use lib/thread/hookstd.use lib/thread/sem.use lib/thread/common.use lib/thread/ncpu.use lib/thread/futex.use lib/thread/spawn.use > + ar -rcs lib/thread/libthread.a lib/thread/mutex.o lib/thread/atomic.o lib/thread/atomic-impl.o lib/thread/types.o lib/thread/fsbase.o lib/thread/tls.o lib/thread/tls-impl.o lib/thread/hookstd.o lib/thread/sem.o lib/thread/common.o lib/thread/ncpu.o lib/thread/exit.o lib/thread/futex.o lib/thread/spawn.o > + $pwd/muse/muse -o lib/thread/libthread.use -p thread lib/thread/mutex.use lib/thread/atomic.use lib/thread/types.use lib/thread/fsbase.use lib/thread/tls.use lib/thread/hookstd.use lib/thread/sem.use lib/thread/common.use lib/thread/ncpu.use lib/thread/futex.use lib/thread/spawn.use > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/opts.myr > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/syssel.myr > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/libs.myr > diff --git a/mk/bootstrap/bootstrap+Linux-x86_64.sh b/mk/bootstrap/bootstrap+Linux-x86_64.sh > index 0b5b7619..c3282de6 100755 > --- a/mk/bootstrap/bootstrap+Linux-x86_64.sh > +++ b/mk/bootstrap/bootstrap+Linux-x86_64.sh > @@ -7,6 +7,7 @@ set -x > as -g -o mbld/cpufeatures.o mbld/cpufeatures+posixy-x64.s > as -g -o lib/thread/exit.o lib/thread/exit+linux-x64.s > as -g -o lib/thread/atomic-impl.o lib/thread/atomic-impl+x64.s > + as -g -o lib/thread/tls-impl.o lib/thread/tls-impl+fsbase-x64.s > as -g -o lib/std/getbp.o lib/std/getbp+posixy-x64.s > $pwd/6/6m -I lib/sys lib/std/option.myr > $pwd/6/6m -I lib/sys lib/std/traits.myr > @@ -120,16 +121,19 @@ set -x > $pwd/6/6m -I lib/std -I lib/sys lib/bio/puti.myr > ar -rcs lib/bio/libbio.a lib/bio/puti.o lib/bio/geti.o lib/bio/fd.o lib/bio/mem.o lib/bio/bio.o lib/bio/types.o lib/bio/iter.o > $pwd/muse/muse -o lib/bio/libbio.use -p bio lib/bio/puti.use lib/bio/geti.use lib/bio/fd.use lib/bio/mem.use lib/bio/bio.use lib/bio/types.use lib/bio/iter.use > - $pwd/6/6m -I lib/sys -I lib/std lib/thread/spawn+linux.myr > - $pwd/6/6m -I lib/sys -I lib/std lib/thread/ncpu+linux.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/common.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/atomic.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/types+fsbase.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/fsbase+linux.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/tls+fsbase.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/spawn+linux.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/ncpu+linux.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/futex+linux.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/sem.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/mutex.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/hookstd.myr > - ar -rcs lib/thread/libthread.a lib/thread/mutex.o lib/thread/atomic.o lib/thread/atomic-impl.o lib/thread/hookstd.o lib/thread/sem.o lib/thread/common.o lib/thread/ncpu.o lib/thread/exit.o lib/thread/futex.o lib/thread/spawn.o > - $pwd/muse/muse -o lib/thread/libthread.use -p thread lib/thread/mutex.use lib/thread/atomic.use lib/thread/hookstd.use lib/thread/sem.use lib/thread/common.use lib/thread/ncpu.use lib/thread/futex.use lib/thread/spawn.use > + ar -rcs lib/thread/libthread.a lib/thread/mutex.o lib/thread/atomic.o lib/thread/atomic-impl.o lib/thread/types.o lib/thread/fsbase.o lib/thread/tls.o lib/thread/tls-impl.o lib/thread/hookstd.o lib/thread/sem.o lib/thread/common.o lib/thread/ncpu.o lib/thread/exit.o lib/thread/futex.o lib/thread/spawn.o > + $pwd/muse/muse -o lib/thread/libthread.use -p thread lib/thread/mutex.use lib/thread/atomic.use lib/thread/types.use lib/thread/fsbase.use lib/thread/tls.use lib/thread/hookstd.use lib/thread/sem.use lib/thread/common.use lib/thread/ncpu.use lib/thread/futex.use lib/thread/spawn.use > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/opts.myr > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/syssel.myr > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/libs.myr > diff --git a/mk/bootstrap/bootstrap+NetBSD-amd64.sh b/mk/bootstrap/bootstrap+NetBSD-amd64.sh > index ae560c05..a81f8c3b 100755 > --- a/mk/bootstrap/bootstrap+NetBSD-amd64.sh > +++ b/mk/bootstrap/bootstrap+NetBSD-amd64.sh > @@ -6,6 +6,7 @@ set -x > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/config.myr > as -g -o mbld/cpufeatures.o mbld/cpufeatures+posixy-x64.s > as -g -o lib/thread/atomic-impl.o lib/thread/atomic-impl+x64.s > + as -g -o lib/thread/tls-impl.o lib/thread/tls-impl+fsbase-x64.s > as -g -o lib/std/getbp.o lib/std/getbp+posixy-x64.s > $pwd/6/6m -I lib/sys lib/std/option.myr > $pwd/6/6m -I lib/sys lib/std/traits.myr > @@ -119,15 +120,18 @@ set -x > $pwd/6/6m -I lib/std -I lib/sys lib/bio/puti.myr > ar -rcs lib/bio/libbio.a lib/bio/puti.o lib/bio/geti.o lib/bio/fd.o lib/bio/mem.o lib/bio/bio.o lib/bio/types.o lib/bio/iter.o > $pwd/muse/muse -o lib/bio/libbio.use -p bio lib/bio/puti.use lib/bio/geti.use lib/bio/fd.use lib/bio/mem.use lib/bio/bio.use lib/bio/types.use lib/bio/iter.use > - $pwd/6/6m -I lib/sys -I lib/std lib/thread/spawn+netbsd.myr > - $pwd/6/6m -I lib/sys -I lib/std lib/thread/ncpu.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/common.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/atomic.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/types+fsbase.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/fsbase+netbsd.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/tls+fsbase.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/spawn+netbsd.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/ncpu.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/sem.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/mutex.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/hookstd.myr > - ar -rcs lib/thread/libthread.a lib/thread/mutex.o lib/thread/atomic.o lib/thread/atomic-impl.o lib/thread/hookstd.o lib/thread/sem.o lib/thread/common.o lib/thread/ncpu.o lib/thread/spawn.o > - $pwd/muse/muse -o lib/thread/libthread.use -p thread lib/thread/mutex.use lib/thread/atomic.use lib/thread/hookstd.use lib/thread/sem.use lib/thread/common.use lib/thread/ncpu.use lib/thread/spawn.use > + ar -rcs lib/thread/libthread.a lib/thread/mutex.o lib/thread/atomic.o lib/thread/atomic-impl.o lib/thread/types.o lib/thread/fsbase.o lib/thread/tls.o lib/thread/tls-impl.o lib/thread/hookstd.o lib/thread/sem.o lib/thread/common.o lib/thread/ncpu.o lib/thread/spawn.o > + $pwd/muse/muse -o lib/thread/libthread.use -p thread lib/thread/mutex.use lib/thread/atomic.use lib/thread/types.use lib/thread/fsbase.use lib/thread/tls.use lib/thread/hookstd.use lib/thread/sem.use lib/thread/common.use lib/thread/ncpu.use lib/thread/spawn.use > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/opts.myr > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/syssel.myr > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/libs.myr > diff --git a/mk/bootstrap/bootstrap+OpenBSD-amd64.sh b/mk/bootstrap/bootstrap+OpenBSD-amd64.sh > index 65c45ccd..ad097852 100755 > --- a/mk/bootstrap/bootstrap+OpenBSD-amd64.sh > +++ b/mk/bootstrap/bootstrap+OpenBSD-amd64.sh > @@ -7,6 +7,7 @@ set -x > as -g -o mbld/cpufeatures.o mbld/cpufeatures+posixy-x64.s > as -g -o lib/thread/exit.o lib/thread/exit+openbsd-x64.s > as -g -o lib/thread/atomic-impl.o lib/thread/atomic-impl+x64.s > + as -g -o lib/thread/tls-impl.o lib/thread/tls-impl+fsbase-x64.s > as -g -o lib/std/getbp.o lib/std/getbp+posixy-x64.s > $pwd/6/6m -I lib/sys lib/std/option.myr > $pwd/6/6m -I lib/sys lib/std/traits.myr > @@ -120,16 +121,19 @@ set -x > $pwd/6/6m -I lib/std -I lib/sys lib/bio/puti.myr > ar -rcs lib/bio/libbio.a lib/bio/puti.o lib/bio/geti.o lib/bio/fd.o lib/bio/mem.o lib/bio/bio.o lib/bio/types.o lib/bio/iter.o > $pwd/muse/muse -o lib/bio/libbio.use -p bio lib/bio/puti.use lib/bio/geti.use lib/bio/fd.use lib/bio/mem.use lib/bio/bio.use lib/bio/types.use lib/bio/iter.use > - $pwd/6/6m -I lib/sys -I lib/std lib/thread/spawn+openbsd.myr > - $pwd/6/6m -I lib/sys -I lib/std lib/thread/ncpu+openbsd.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/common.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/atomic.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/types+fsbase.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/fsbase+openbsd.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/tls+fsbase.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/spawn+openbsd.myr > + $pwd/6/6m -I lib/sys -I lib/std lib/thread/ncpu+openbsd.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/futex+openbsd:6.2.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/sem.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/mutex.myr > $pwd/6/6m -I lib/sys -I lib/std lib/thread/hookstd.myr > - ar -rcs lib/thread/libthread.a lib/thread/mutex.o lib/thread/atomic.o lib/thread/atomic-impl.o lib/thread/hookstd.o lib/thread/sem.o lib/thread/common.o lib/thread/ncpu.o lib/thread/exit.o lib/thread/futex.o lib/thread/spawn.o > - $pwd/muse/muse -o lib/thread/libthread.use -p thread lib/thread/mutex.use lib/thread/atomic.use lib/thread/hookstd.use lib/thread/sem.use lib/thread/common.use lib/thread/ncpu.use lib/thread/futex.use lib/thread/spawn.use > + ar -rcs lib/thread/libthread.a lib/thread/mutex.o lib/thread/atomic.o lib/thread/atomic-impl.o lib/thread/types.o lib/thread/fsbase.o lib/thread/tls.o lib/thread/tls-impl.o lib/thread/hookstd.o lib/thread/sem.o lib/thread/common.o lib/thread/ncpu.o lib/thread/exit.o lib/thread/futex.o lib/thread/spawn.o > + $pwd/muse/muse -o lib/thread/libthread.use -p thread lib/thread/mutex.use lib/thread/atomic.use lib/thread/types.use lib/thread/fsbase.use lib/thread/tls.use lib/thread/hookstd.use lib/thread/sem.use lib/thread/common.use lib/thread/ncpu.use lib/thread/futex.use lib/thread/spawn.use > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/opts.myr > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/syssel.myr > $pwd/6/6m -I lib/sys -I lib/std -I lib/bio -I lib/regex -I lib/thread mbld/libs.myr > diff --git a/rt/start-freebsd.s b/rt/start-freebsd.s > index 9c1091b3..399fac04 100644 > --- a/rt/start-freebsd.s > +++ b/rt/start-freebsd.s > @@ -4,6 +4,10 @@ > sys$__cenvp: > .quad 0 > > +.globl thread$__tls > +thread$__tls: > + .fill 88 /* sizeof(tlshdr) + (8 * sizeof(void#)) = 24 + 64 */ > + > .text > /* > * The entry point for the whole program. > @@ -11,6 +15,7 @@ sys$__cenvp: > * - Sets up all argc entries as slices > * - Converts argc/argv to a slice > * - Stashes a raw envp copy in __cenvp (for syscalls to use) > + * - Sets up thread local storage for the main thread > * - Calls main() > */ > .globl _start > @@ -35,6 +40,16 @@ _start: > pushq %rcx > call cvt > > + /* set up the intial tls region for the main thread */ > + subq $0x10,%rsp > + movq $165,%rax /* sysarch */ > + movq $129,%rdi /* Archamd64setfs */ > + leaq thread$__tls(%rip),%rsi > + movq %rsi,(%rsp) > + movq %rsp,%rsi > + syscall > + addq $0x10,%rsp > + > xorq %rbp,%rbp > /* call pre-main initializers */ > call __init__ > diff --git a/rt/start-linux.s b/rt/start-linux.s > index 742b4a38..a0cbfb6f 100644 > --- a/rt/start-linux.s > +++ b/rt/start-linux.s > @@ -4,6 +4,10 @@ > sys$__cenvp: > .quad 0 > > +.globl thread$__tls > +thread$__tls: > + .fill 88 /* sizeof(tlshdr) + (8 * sizeof(void#)) = 24 + 64 */ > + > .text > /* > * The entry point for the whole program. > @@ -11,6 +15,7 @@ sys$__cenvp: > * - Sets up all argc entries as slices > * - Converts argc/argv to a slice > * - Stashes a raw envp copy in __cenvp (for syscalls to use) > + * - Sets up thread local storage for the main thread > * - Calls main() > */ > .globl _start > @@ -36,6 +41,12 @@ _start: > pushq %rcx > call cvt > > + /* set up the intial tls region for the main thread */ > + movq $158,%rax /* arch_prctl */ > + movq $0x1002,%rdi /* Archsetfs */ > + leaq thread$__tls(%rip),%rsi > + syscall > + > xorq %rbp,%rbp > /* call pre-main initializers */ > call __init__ > diff --git a/rt/start-netbsd.s b/rt/start-netbsd.s > index dd3213e5..3a6cfc70 100644 > --- a/rt/start-netbsd.s > +++ b/rt/start-netbsd.s > @@ -12,6 +12,10 @@ > sys$__cenvp: > .quad 0 > > +.globl thread$__tls > +thread$__tls: > + .fill 88 /* sizeof(tlshdr) + (8 * sizeof(void#)) = 24 + 64 */ > + > .text > /* > * The entry point for the whole program. > @@ -19,6 +23,7 @@ sys$__cenvp: > * - Sets up all argc entries as slices > * - Converts argc/argv to a slice > * - Stashes a raw envp copy in __cenvp (for syscalls to use) > + * - Sets up thread local storage for the main thread > * - Calls main() > */ > .globl _start > @@ -44,6 +49,16 @@ _start: > pushq %rcx > call cvt > > + /* set up the intial tls region for the main thread */ > + subq $0x10,%rsp > + movq $165,%rax /* sysarch */ > + movq $15,%rdi /* X8664setfsbase */ > + leaq thread$__tls(%rip),%rsi > + movq %rsi,(%rsp) > + movq %rsp,%rsi > + syscall > + addq $0x10,%rsp > + > xorq %rbp,%rbp > /* call pre-main initializers */ > call __init__ > diff --git a/rt/start-openbsd.s b/rt/start-openbsd.s > index c0e061af..eef7b454 100644 > --- a/rt/start-openbsd.s > +++ b/rt/start-openbsd.s > @@ -13,6 +13,10 @@ > sys$__cenvp: > .quad 0 > > +.globl thread$__tls > +thread$__tls: > + .fill 88 /* sizeof(tlshdr) + (8 * sizeof(void#)) = 24 + 64 */ > + > .text > /* > * The entry point for the whole program. > @@ -20,6 +24,7 @@ sys$__cenvp: > * - Sets up all argc entries as slices > * - Converts argc/argv to a slice > * - Stashes a raw envp copy in __cenvp (for syscalls to use) > + * - Sets up thread local storage for the main thread > * - Calls main() > */ > .globl _start > @@ -45,6 +50,11 @@ _start: > pushq %rcx > call cvt > > + /* set up the intial tls region for the main thread */ > + movq $329,%rax /* Sys__set_tcb */ > + leaq thread$__tls(%rip),%rdi > + syscall > + > xorq %rbp,%rbp > /* > we're done startup, and we kind of want > diff --git a/rt/start-osx.s b/rt/start-osx.s > index b43b30c3..a1e18568 100644 > --- a/rt/start-osx.s > +++ b/rt/start-osx.s > @@ -4,6 +4,10 @@ > _sys$__cenvp: > .quad 0 > > +.globl thread$__tls > +thread$__tls: > + .fill 104 /* sizeof(tlshdr) + (8 * sizeof(void#)) = 40 + 64 */ > + > .text > /* > * The entry point for the whole program. > @@ -11,6 +15,7 @@ _sys$__cenvp: > * - Sets up all argc entries as slices > * - Converts argc/argv to a slice > * - Stashes a raw envp copy in __cenvp (for syscalls to use) > + * - Sets up thread local storage for the main thread > * - Calls main() > */ > .globl start > @@ -36,6 +41,12 @@ start: > pushq %rcx > call cvt > > + /* set up the intial tls region for the main thread */ > + movq $0x3000003,%rax /* undocumented setgsbase syscall */ > + leaq thread$__tls(%rip),%rdi > + movq %rdi,0x20(%rdi) /* also store a copy in __tls.self */ > + syscall > + > xorq %rbp,%rbp > call ___init__ > /* enter the main program */ > diff --git a/support/syscall-gen/types+freebsd-x64.frag b/support/syscall-gen/types+freebsd-x64.frag > index f8990533..5ed178c9 100644 > --- a/support/syscall-gen/types+freebsd-x64.frag > +++ b/support/syscall-gen/types+freebsd-x64.frag > @@ -32,6 +32,7 @@ type id = int64 > type cpulevel = int > type cpusetid = int > type idtype = int > +type sysarchop = int > > type acltype = int > type acltag = uint32 > @@ -796,5 +797,12 @@ const Sigthr : signo = 32 /* reserved by thread library. */ > const Siglwp : signo = Sigthr > const Siglibrt : signo = 33 /* reserved by real-time library. */ > > +/* sysarch ops */ > +const Archamd64getfs : sysarchop = 128 > +const Archamd64setfs : sysarchop = 129 > +const Archamd64getgs : sysarchop = 130 > +const Archamd64setgs : sysarchop = 131 > +const Archamd64getxfpu : sysarchop = 131 > + > extern const syscall : (sc:scno, args:... -> int64) > extern var __cenvp : byte## > diff --git a/support/syscall-gen/types+linux-x64.frag b/support/syscall-gen/types+linux-x64.frag > index 9e90a5ac..966de307 100644 > --- a/support/syscall-gen/types+linux-x64.frag > +++ b/support/syscall-gen/types+linux-x64.frag > @@ -38,6 +38,7 @@ type fallocmode = uint32 > type mfdflags = uint32 > type aiocontext = uint64 > type msg = void# > +type arch_prctlop = uint64 > > > type clock = union > @@ -584,6 +585,12 @@ const Seekend : whence = 2 > /* return value for a failed mapping */ > const Mapbad : byte# = (-1 : byte#) > > +/* arch_prctl ops */ > +const Archsetgs : arch_prctlop = 0x1001 > +const Archsetfs : arch_prctlop = 0x1002 > +const Archgetfs : arch_prctlop = 0x1003 > +const Archgetgs : arch_prctlop = 0x1004 > + > /* signal flags */ > const Sanocldstop : sigflags = 0x00000001 > const Sanocldwait : sigflags = 0x00000002 > -- > 2.19.1 > > -- Ori Bernstein
[PATCH] Add thread-local storage for POSIX-y platforms. | iriri <iri@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> |
[PATCH] Add thread-local storage for POSIX-y platforms. | iriri <iri@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> |
Re: [PATCH] Add thread-local storage for POSIX-y platforms. | Ori Bernstein <ori@xxxxxxxxxxxxxx> |
[PATCH] Add thread-local storage for POSIX-y platforms. | iriri <iri@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> |
- Prev by Date: [PATCH] Add thread-local storage for POSIX-y platforms.
- Next by Date: Re: [PATCH] Add thread-local storage for POSIX-y platforms.
- Previous by thread: [PATCH] Add thread-local storage for POSIX-y platforms.
- Next by thread: Re: [PATCH] Add thread-local storage for POSIX-y platforms.
- Index(es):