ref: a68e92f1e80f262e04d6e6c1d27af80199afbdc0
dir: /lib/thread/tls+fsbase.myr/
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#)