use std::sync::atomic::{AtomicI8, Ordering};
use std::sync::OnceLock;
const ENV_GEMM_INTERIOR: &[&str] = &[
"TESSL_GEMM_INTERIOR",
"METAL_RUNTIME_GEMM_INTERIOR",
"METAL_NATIVE_GEMM_INTERIOR",
];
const ENV_GEMM_ACCUM: &[&str] = &[
"TESSL_GEMM_ACCUM",
"METAL_RUNTIME_GEMM_ACCUM",
"METAL_NATIVE_GEMM_ACCUM",
];
const ENV_GEMM_ACCUM_DX: &[&str] = &[
"TESSL_GEMM_ACCUM_DX",
"METAL_RUNTIME_GEMM_ACCUM_DX",
"METAL_NATIVE_GEMM_ACCUM_DX",
];
const ENV_HAZARD_BARRIERS: &[&str] = &[
"TESSL_HAZARD_BARRIERS",
"METAL_RUNTIME_HAZARD_BARRIERS",
"METAL_NATIVE_HAZARD_BARRIERS",
];
const ENV_COARSE_BARRIERS: &[&str] = &[
"TESSL_COARSE_BARRIERS",
"GEMMA_METAL_COARSE_BARRIERS",
"METAL_RUNTIME_COARSE_BARRIERS",
];
fn parse_truthy(value: Option<&str>) -> Option<bool> {
match value {
Some("1") | Some("true") | Some("TRUE") | Some("yes") => Some(true),
Some("0") | Some("false") | Some("FALSE") | Some("no") => Some(false),
_ => None,
}
}
fn resolve(names: &[&str], lookup: impl Fn(&str) -> Option<String>) -> Option<bool> {
names
.iter()
.find_map(|name| parse_truthy(lookup(name).as_deref()))
}
pub(crate) fn env_truthy(names: &[&str]) -> Option<bool> {
resolve(names, |name| std::env::var(name).ok())
}
fn flags() -> &'static (bool, bool, bool) {
static FLAGS: OnceLock<(bool, bool, bool)> = OnceLock::new();
FLAGS.get_or_init(|| {
let gemm_interior = env_truthy(ENV_GEMM_INTERIOR).unwrap_or(false);
let gemm_accum = env_truthy(ENV_GEMM_ACCUM).unwrap_or(false);
let gemm_accum_dx = env_truthy(ENV_GEMM_ACCUM_DX).unwrap_or(false);
(gemm_interior, gemm_accum, gemm_accum_dx)
})
}
static HAZARD_BARRIERS: AtomicI8 = AtomicI8::new(-1);
pub fn set_hazard_barriers(skip_auto: bool) {
HAZARD_BARRIERS.store(if skip_auto { 1 } else { 0 }, Ordering::Relaxed);
}
pub fn hazard_barriers_explicitly_set() -> bool {
HAZARD_BARRIERS.load(Ordering::Relaxed) >= 0
}
pub fn gemm_interior_offsets() -> bool {
flags().0
}
pub fn hazard_barriers() -> bool {
let v = HAZARD_BARRIERS.load(Ordering::Relaxed);
if v >= 0 {
return v == 1;
}
let from_env = env_truthy(ENV_HAZARD_BARRIERS).unwrap_or(false);
HAZARD_BARRIERS.store(if from_env { 1 } else { 0 }, Ordering::Relaxed);
from_env
}
pub fn gemm_accum() -> bool {
flags().1
}
pub fn gemm_accum_dx() -> bool {
flags().2
}
static COARSE_BARRIERS: AtomicI8 = AtomicI8::new(-1);
fn coarse_default(from_env: Option<bool>, hazard: bool) -> bool {
from_env.unwrap_or(hazard)
}
pub fn coarse_barriers() -> bool {
let v = COARSE_BARRIERS.load(Ordering::Relaxed);
if v >= 0 {
return v == 1;
}
let on = coarse_default(env_truthy(ENV_COARSE_BARRIERS), hazard_barriers());
COARSE_BARRIERS.store(if on { 1 } else { 0 }, Ordering::Relaxed);
on
}
fn need_barrier_from(hazard: bool, coarse: impl FnOnce() -> bool, phase_edge: bool) -> bool {
if !hazard {
return false;
}
if coarse() {
phase_edge
} else {
true
}
}
pub fn need_barrier(phase_edge: bool) -> bool {
need_barrier_from(hazard_barriers(), coarse_barriers, phase_edge)
}
#[cfg(test)]
mod tests {
use super::*;
use std::cell::Cell;
fn table<'a>(
entries: &'a [(&'a str, &'a str)],
seen: &'a Cell<usize>,
) -> impl Fn(&str) -> Option<String> + 'a {
move |name| {
seen.set(seen.get() + 1);
entries
.iter()
.find(|(k, _)| *k == name)
.map(|(_, v)| (*v).to_string())
}
}
#[test]
fn parse_truthy_accepts_only_the_documented_spellings() {
let cases: &[(Option<&str>, Option<bool>)] = &[
(Some("1"), Some(true)),
(Some("true"), Some(true)),
(Some("TRUE"), Some(true)),
(Some("yes"), Some(true)),
(Some("0"), Some(false)),
(Some("false"), Some(false)),
(Some("FALSE"), Some(false)),
(Some("no"), Some(false)),
(Some("True"), None),
(Some("Yes"), None),
(Some("YES"), None),
(Some("NO"), None),
(Some("2"), None),
(Some("on"), None),
(Some(""), None),
(None, None),
];
for (value, expected) in cases {
assert_eq!(parse_truthy(*value), *expected, "parse_truthy({value:?})");
}
}
#[test]
fn resolve_takes_the_first_name_that_parses() {
const NAMES: &[&str] = &["FIRST", "SECOND", "THIRD"];
type Case<'a> = (&'a [(&'a str, &'a str)], Option<bool>);
let cases: &[Case] = &[
(&[("FIRST", "0"), ("SECOND", "1")], Some(false)),
(&[("FIRST", "1"), ("SECOND", "0")], Some(true)),
(&[("SECOND", "1")], Some(true)),
(&[("THIRD", "0")], Some(false)),
(&[("FIRST", "junk"), ("SECOND", "0")], Some(false)),
(&[("FIRST", "junk"), ("THIRD", "1")], Some(true)),
(&[("FIRST", "junk")], None),
(&[("FIRST", "junk"), ("SECOND", "Yes")], None),
(&[], None),
];
for (entries, expected) in cases {
let seen = Cell::new(0);
assert_eq!(
resolve(NAMES, table(entries, &seen)),
*expected,
"resolve over {entries:?}"
);
}
}
#[test]
fn resolve_stops_at_the_first_parsing_name() {
const NAMES: &[&str] = &["FIRST", "SECOND", "THIRD"];
let seen = Cell::new(0);
assert_eq!(resolve(NAMES, table(&[("FIRST", "1")], &seen)), Some(true));
assert_eq!(seen.get(), 1, "later names must not be looked up");
let seen = Cell::new(0);
assert_eq!(
resolve(NAMES, table(&[("SECOND", "0")], &seen)),
Some(false)
);
assert_eq!(seen.get(), 2, "must stop once SECOND answers");
let seen = Cell::new(0);
assert_eq!(resolve(NAMES, table(&[], &seen)), None);
assert_eq!(seen.get(), 3, "with no answer every name must be tried");
}
#[test]
fn every_flag_reads_its_canonical_tessl_name_first() {
let lists: &[(&str, &[&str])] = &[
("gemm_interior", ENV_GEMM_INTERIOR),
("gemm_accum", ENV_GEMM_ACCUM),
("gemm_accum_dx", ENV_GEMM_ACCUM_DX),
("hazard_barriers", ENV_HAZARD_BARRIERS),
("coarse_barriers", ENV_COARSE_BARRIERS),
];
for (flag, names) in lists {
assert!(!names.is_empty(), "{flag} has no env names");
assert!(
names[0].starts_with("TESSL_"),
"{flag} reads {} before its canonical TESSL_* name",
names[0]
);
for (i, name) in names.iter().enumerate() {
assert!(
!names[i + 1..].contains(name),
"{flag} lists {name} twice; the duplicate can never win"
);
assert!(
i == 0 || !name.starts_with("TESSL_"),
"{flag} has a second canonical name {name}; only slot 0 is canonical"
);
}
}
}
#[test]
fn coarse_default_inherits_hazard_and_yields_to_an_explicit_value() {
assert!(
coarse_default(None, true),
"hazard on must coarsen by default"
);
assert!(
!coarse_default(None, false),
"with always-on barriers there is nothing to coarsen"
);
assert!(!coarse_default(Some(false), true), "explicit 0 must disarm");
assert!(coarse_default(Some(true), false), "explicit 1 must arm");
}
#[test]
fn need_barrier_truth_table() {
for phase_edge in [false, true] {
assert!(
!need_barrier_from(false, || true, phase_edge),
"hazard off: the always-on barrier already covers this edge"
);
assert!(
!need_barrier_from(false, || false, phase_edge),
"hazard off: the always-on barrier already covers this edge"
);
assert!(
need_barrier_from(true, || false, phase_edge),
"hazard + fine grained: every RAW edge needs an explicit barrier"
);
assert_eq!(
need_barrier_from(true, || true, phase_edge),
phase_edge,
"hazard + coarse: only major producer->consumer edges"
);
}
}
#[test]
fn need_barrier_does_not_read_coarse_when_hazard_is_off() {
let read = Cell::new(false);
let probe = || {
read.set(true);
true
};
assert!(!need_barrier_from(false, probe, true));
assert!(
!read.get(),
"need_barrier latched COARSE_BARRIERS while hazard mode was off"
);
let read_on = Cell::new(false);
let probe_on = || {
read_on.set(true);
true
};
assert!(need_barrier_from(true, probe_on, true));
assert!(read_on.get(), "hazard on must consult the coarse flag");
}
#[test]
fn hazard_barriers_latches_once_and_reports_itself_set() {
let expected = env_truthy(ENV_HAZARD_BARRIERS).unwrap_or(false);
let first = hazard_barriers();
assert_eq!(
first, expected,
"hazard_barriers disagrees with its own env name list"
);
assert!(
hazard_barriers_explicitly_set(),
"reading the flag must latch it; GPU init keys off this"
);
assert_eq!(hazard_barriers(), first, "latched value must be stable");
}
#[test]
fn coarse_barriers_live_path_matches_its_pure_default() {
let hazard = hazard_barriers();
let expected = coarse_default(env_truthy(ENV_COARSE_BARRIERS), hazard);
let first = coarse_barriers();
assert_eq!(
first, expected,
"live coarse_barriers diverged from coarse_default"
);
assert_eq!(coarse_barriers(), first, "latched value must be stable");
assert_eq!(
need_barrier(true),
hazard,
"phase edge: hazard mode decides, in both coarse and fine mode"
);
assert_eq!(
need_barrier(false),
hazard && !first,
"non-phase edge: only fine-grained hazard mode needs a barrier"
);
}
}