sel4_panicking/count/
with_tls.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7use core::cell::Cell;
8use core::fmt;
9
10#[thread_local]
11static PANIC_COUNT: Cell<usize> = Cell::new(0);
12
13const MAX_PANIC_DEPTH: usize = if cfg!(feature = "alloc") { 3 } else { 1 };
14
15pub(crate) enum MustAbort {
16    MaxDepthExceeded,
17}
18
19impl fmt::Display for MustAbort {
20    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21        match self {
22            Self::MaxDepthExceeded => {
23                write!(f, "maximum panic depth of {MAX_PANIC_DEPTH} exceeded")
24            }
25        }
26    }
27}
28
29pub(crate) fn count_panic() -> Option<MustAbort> {
30    if PANIC_COUNT.get() == MAX_PANIC_DEPTH {
31        return Some(MustAbort::MaxDepthExceeded);
32    }
33    update(&PANIC_COUNT, |count| count + 1);
34    None
35}
36
37pub(crate) fn count_panic_caught() {
38    update(&PANIC_COUNT, |count| count - 1);
39}
40
41fn update<T: Copy>(cell: &Cell<T>, f: impl FnOnce(T) -> T) -> T {
42    let old = cell.get();
43    let new = f(old);
44    cell.set(new);
45    new
46}