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