1#![no_std]
6
7mod bindings;
8
9pub const SMP_MAX_CPUS: usize =
12 zr::parse_usize(env!("SMP_MAX_CPUS")).expect("SMP_MAX_CPUS invalid");
13
14pub use zr::to_array;
15
16#[repr(u64)]
21pub enum Type {
22 Padding = 0,
24 Sum = 1,
26 Min = 2,
28 Max = 3,
30}
31
32#[repr(C, align(8))]
38pub struct Descriptor {
39 name: [u8; 56],
40 type_: u64,
41}
42
43zr::static_assert!(
44 core::mem::size_of::<Descriptor>() == core::mem::size_of::<bindings::counters_Descriptor>()
45);
46zr::static_assert!(
47 core::mem::align_of::<Descriptor>() == core::mem::align_of::<bindings::counters_Descriptor>()
48);
49zr::static_assert!(
50 core::mem::offset_of!(Descriptor, name)
51 == core::mem::offset_of!(bindings::counters_Descriptor, name)
52);
53zr::static_assert!(
54 core::mem::offset_of!(Descriptor, type_)
55 == core::mem::offset_of!(bindings::counters_Descriptor, type_)
56);
57zr::static_assert!(Type::Padding as u64 == bindings::counters_Type_kPadding as u64);
58zr::static_assert!(Type::Sum as u64 == bindings::counters_Type_kSum as u64);
59zr::static_assert!(Type::Min as u64 == bindings::counters_Type_kMin as u64);
60zr::static_assert!(Type::Max as u64 == bindings::counters_Type_kMax as u64);
61
62impl Descriptor {
63 pub const fn new(name: [u8; 56], type_: u64) -> Self {
65 Self { name, type_ }
66 }
67}
68
69unsafe extern "C" {
70 fn kcounter_add_ffi(desc: *const Descriptor, delta: i64);
71 fn kcounter_min_ffi(desc: *const Descriptor, value: i64);
72 fn kcounter_max_ffi(desc: *const Descriptor, value: i64);
73}
74
75pub struct Counter {
81 descriptor: *const Descriptor,
82}
83
84unsafe impl Sync for Counter {}
85unsafe impl Send for Counter {}
86
87impl Counter {
88 pub const unsafe fn new_with_ptr(descriptor: *const Descriptor) -> Self {
94 Self { descriptor }
95 }
96
97 #[inline]
99 pub fn add(&self, delta: i64) {
100 unsafe {
101 kcounter_add_ffi(self.descriptor, delta);
102 }
103 }
104
105 #[inline]
108 pub fn min(&self, value: i64) {
109 unsafe {
110 kcounter_min_ffi(self.descriptor, value);
111 }
112 }
113
114 #[inline]
117 pub fn max(&self, value: i64) {
118 unsafe {
119 kcounter_max_ffi(self.descriptor, value);
120 }
121 }
122}
123
124#[macro_export]
135macro_rules! define_kcounter {
136 ($rust_var:ident, $name:expr, $type:ident) => {
137 pub static $rust_var: $crate::Counter = {
138 #[unsafe(link_section = concat!(".bss.kcounter.", $name))]
139 #[used]
140 static mut ARENA: [i64; $crate::SMP_MAX_CPUS] = [0; $crate::SMP_MAX_CPUS];
141
142 #[unsafe(link_section = concat!("kcountdesc.", $name))]
143 #[used]
144 static DESC: $crate::Descriptor =
145 $crate::Descriptor::new($crate::to_array::<56>($name), $crate::Type::$type as u64);
146
147 unsafe { $crate::Counter::new_with_ptr(&DESC as *const $crate::Descriptor) }
148 };
149 };
150}