ref: 1708e4bc0d9d199b17054a5837e89fabfdc4298e
parent: 1018f0d5c592cbe9c2d78b7197369f422ffa26b0
parent: 06f83c93631d8af9eb25199a8229183c48b89ce8
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Oct 27 10:54:44 EDT 2018
Merge branch 'master' of git+ssh://git.eigenstate.org/git/ori/mc
--- 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
--- a/lib/sys/sys+freebsd-x64.myr
+++ b/lib/sys/sys+freebsd-x64.myr
@@ -38,6 +38,7 @@
type cpulevel = int
type cpusetid = int
type idtype = int
+ type sysarchop = int64
type acltype = int
type acltag = uint32
@@ -802,6 +803,13 @@
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 @@
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 @@
-> (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)
--- a/lib/sys/sys+linux-x64.myr
+++ b/lib/sys/sys+linux-x64.myr
@@ -45,6 +45,7 @@
type mfdflags = uint32
type aiocontext = uint64
type msg = void#
+ type arch_prctlop = uint64
type clock = union
@@ -590,6 +591,12 @@
/* 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 @@
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 @@
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 @@
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 @@
-> (syscall(Systimes, a(tbuf)) : int64)
}
const gettid = {
- -> (syscall(Sysgettid) : int64)
+ -> (syscall(Sysgettid) : pid)
}
const alarm = {seconds
-> (syscall(Sysalarm, a(seconds)) : int64)
@@ -2308,6 +2317,9 @@
}
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)
--- a/lib/sys/sys+netbsd-x64.myr
+++ b/lib/sys/sys+netbsd-x64.myr
@@ -18,6 +18,7 @@
type umtxop = int32
type signo = int32
type sigflags = int32
+ type sysarchop = int64
type clock = union
`Clockrealtime
@@ -344,6 +345,21 @@
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 @@
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##
@@ -1100,6 +1119,10 @@
/* all args already passed through a() or ar ptrs */
-> (syscall(Sys__sysctl, \
(mib : int#), a(mib.len), old, oldsz, new, newsz) : int)
+}
+
+const sysarch = {op, args
+ -> (syscall(Syssysarch, op, args) : int)
}
const clockid = {clk
--- a/lib/sys/sys+openbsd-x64.myr
+++ b/lib/sys/sys+openbsd-x64.myr
@@ -215,7 +215,7 @@
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 */
--- a/lib/sys/sys+openbsd:6.1-x64.myr
+++ b/lib/sys/sys+openbsd:6.1-x64.myr
@@ -1031,7 +1031,7 @@
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 @@
-> (syscall(Sys__set_tcb, a(tcb)) : void)
}
const __get_tcb = {
- -> (syscall(Sys__get_tcb) : void)
+ -> (syscall(Sys__get_tcb) : void#)
}
--- a/lib/sys/sys+openbsd:6.2-x64.myr
+++ b/lib/sys/sys+openbsd:6.2-x64.myr
@@ -348,7 +348,7 @@
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 @@
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 @@
-> (syscall(Sys__set_tcb, a(tcb)) : void)
}
const __get_tcb = {
- -> (syscall(Sys__get_tcb) : void)
+ -> (syscall(Sys__get_tcb) : void#)
}
--- a/lib/sys/sys+openbsd:6.3-x64.myr
+++ b/lib/sys/sys+openbsd:6.3-x64.myr
@@ -1036,7 +1036,7 @@
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 @@
-> (syscall(Sys__set_tcb, a(tcb)) : void)
}
const __get_tcb = {
- -> (syscall(Sys__get_tcb) : void)
+ -> (syscall(Sys__get_tcb) : void#)
}
--- a/lib/thread/bld.sub
+++ b/lib/thread/bld.sub
@@ -14,6 +14,11 @@
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 @@
# 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 @@
# 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 @@
# 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 @@
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 @@
# 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
--- 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#)
;;
--- 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) */
--- 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) */
--- 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 @@
/* 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) */
--- /dev/null
+++ b/lib/thread/fsbase+freebsd.myr
@@ -1,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()
+ ;;
+}
--- /dev/null
+++ b/lib/thread/fsbase+linux.myr
@@ -1,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()
+ ;;
+}
--- /dev/null
+++ b/lib/thread/fsbase+netbsd.myr
@@ -1,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()
+ ;;
+}
--- /dev/null
+++ b/lib/thread/fsbase+openbsd.myr
@@ -1,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#)
+}
--- 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 @@
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 @@
for var i = 0; i < nspin; i++
c = xcas(&mtx._state, Unlocked, Locked)
if c == Unlocked
+ mtx._owner = tid()
-> void
;;
;;
@@ -51,14 +64,32 @@
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 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()
}
--- a/lib/thread/mutex.myr
+++ b/lib/thread/mutex.myr
@@ -1,5 +1,4 @@
use std
-use sys
use "atomic"
--- a/lib/thread/rwlock+futex.myr
+++ b/lib/thread/rwlock+futex.myr
@@ -2,6 +2,8 @@
use "atomic"
use "futex"
+use "tls"
+use "types"
pkg thread =
/*
@@ -13,6 +15,7 @@
*/
type rwlock = struct
_state : ftxtag
+ _owner : tid
;;
const mkrwlock : (-> rwlock)
@@ -28,7 +31,7 @@
const Waitbit = 0x80000000
const mkrwlock = {
- -> [._state = 0]
+ -> [._state = 0, ._owner = -1]
}
const rdlock = {rw
@@ -61,6 +64,13 @@
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 @@
*/
var s = xcas(&rw._state, 0, Nrmask)
if s == 0
+ rw._owner = tid()
-> void
;;
@@ -98,7 +109,11 @@
}
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 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
--- 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,65 @@
}
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)
+ (tos, stksz, hdr) = initstk(stk, fn, sz)
- /* 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]#)#
-
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
+ fn = std.fndup(fn)
+
+ 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()
+ std.fnfree(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)#
--- 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 Thrflag = sys.Clonevm | sys.Clonefs | sys.Clonefiles | \
+ sys.Clonesighand | sys.Clonethread | sys.Clonesettls | \
+ sys.Clonechildsettid
-const Stacksz = 8*std.MiB
-
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)
--- 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 @@
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 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
+ (tos, hdr) = initstk(stk, fn, sz)
- /* 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])
-
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 @@
(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)
--- 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,35 +35,14 @@
}
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
+ tos = initstk(stk, fn, sz)
- /* 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]#)#
-
ret = sys.bsdthread_create( \
(tramp : void#), \ /* start */
(tos : void#), \ /* arg */
@@ -70,21 +50,39 @@
(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
+ fn = std.fndup(fn)
+
+ var fn1 = {
+ setgsbase(hdr)
+ fn()
+ std.fnfree(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#)
}
/*
--- a/lib/thread/start+osx-x64.s
+++ b/lib/thread/start+osx-x64.s
@@ -15,20 +15,13 @@
/*
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 */
--- /dev/null
+++ b/lib/thread/test/die.myr
@@ -1,0 +1,8 @@
+use thread
+
+const main = {
+ var m = thread.mkmtx()
+ thread.mtxlock(&m)
+ thread.mtxunlock(&m)
+ thread.mtxunlock(&m)
+}
--- /dev/null
+++ b/lib/thread/test/tls.myr
@@ -1,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)
+}
--- /dev/null
+++ b/lib/thread/tls+fsbase.myr
@@ -1,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#)
--- /dev/null
+++ b/lib/thread/tls+osx.myr
@@ -1,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)
--- /dev/null
+++ b/lib/thread/tls-impl+fsbase-x64.s
@@ -1,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
--- /dev/null
+++ b/lib/thread/tls-impl+osx-x64.s
@@ -1,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
--- /dev/null
+++ b/lib/thread/types+fsbase.myr
@@ -1,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#[...]
+ ;;
+;;
--- /dev/null
+++ b/lib/thread/types+osx.myr
@@ -1,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#[...]
+ ;;
+;;
--- a/mk/bootstrap/bootstrap+Darwin-x86_64.sh
+++ b/mk/bootstrap/bootstrap+Darwin-x86_64.sh
@@ -7,6 +7,7 @@
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 @@
$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
--- a/mk/bootstrap/bootstrap+FreeBSD-amd64.sh
+++ b/mk/bootstrap/bootstrap+FreeBSD-amd64.sh
@@ -7,6 +7,7 @@
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 @@
$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
--- a/mk/bootstrap/bootstrap+Linux-x86_64.sh
+++ b/mk/bootstrap/bootstrap+Linux-x86_64.sh
@@ -7,6 +7,7 @@
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 @@
$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
--- a/mk/bootstrap/bootstrap+NetBSD-amd64.sh
+++ b/mk/bootstrap/bootstrap+NetBSD-amd64.sh
@@ -6,6 +6,7 @@
$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 @@
$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
--- a/mk/bootstrap/bootstrap+OpenBSD-amd64.sh
+++ b/mk/bootstrap/bootstrap+OpenBSD-amd64.sh
@@ -7,6 +7,7 @@
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 @@
$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
--- a/parse/type.c
+++ b/parse/type.c
@@ -236,8 +236,6 @@
bindtype(t->env, param[i]);
if (!base->env)
base->env = t->env;
- else
- assert(base->env->super == t->env || base->narg > 0);
return t;
}
--- 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 @@
* - 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
@@ -34,6 +39,16 @@
pushq %rax
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 */
--- 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 @@
* - 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,12 @@
pushq %rax
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 */
--- 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 @@
* - 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
@@ -43,6 +48,16 @@
pushq %rax
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 */
--- 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 @@
* - 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,11 @@
pushq %rax
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
/*
--- 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 @@
* - 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,12 @@
pushq %rax
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__
--- a/support/syscall-gen/types+freebsd-x64.frag
+++ b/support/syscall-gen/types+freebsd-x64.frag
@@ -32,6 +32,7 @@
type cpulevel = int
type cpusetid = int
type idtype = int
+type sysarchop = int
type acltype = int
type acltag = uint32
@@ -795,6 +796,13 @@
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##
--- a/support/syscall-gen/types+linux-x64.frag
+++ b/support/syscall-gen/types+linux-x64.frag
@@ -38,6 +38,7 @@
type mfdflags = uint32
type aiocontext = uint64
type msg = void#
+type arch_prctlop = uint64
type clock = union
@@ -583,6 +584,12 @@
/* 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