1use crate::{
8 bindings,
9 prelude::*,
10 types::Opaque, };
12
13#[macro_export]
15macro_rules! ratelimit_state_init {
16 ($name:ident, $interval:expr, $burst:expr $(,)?) => {
17 #[allow(non_upper_case_globals)]
18 static $name: $crate::ratelimit::Ratelimit = {
19 let name = $crate::c_str!(::core::stringify!($name));
20 let interval = $interval;
21 let burst = $burst;
22 unsafe { $crate::ratelimit::Ratelimit::new_static(name, interval, burst) }
24 };
25 };
26}
27pub use ratelimit_state_init;
28
29#[pin_data(PinnedDrop)]
35#[repr(transparent)]
36pub struct Ratelimit {
37 #[pin]
38 inner: Opaque<bindings::ratelimit_state>,
39}
40
41unsafe impl Send for Ratelimit {}
43
44unsafe impl Sync for Ratelimit {}
47
48impl Ratelimit {
49 #[inline]
53 pub fn new(interval: i32, burst: i32) -> impl PinInit<Self> {
54 pin_init!(Self {
56 inner <- Opaque::ffi_init(|slot: *mut bindings::ratelimit_state| {
57 unsafe { bindings::ratelimit_state_init(slot, interval, burst) };
60 }),
61 })
62 }
63
64 #[inline]
66 pub fn new_default() -> impl PinInit<Self> {
67 Ratelimit::new(Ratelimit::DEFAULT_INTERVAL, Ratelimit::DEFAULT_BURST)
68 }
69
70 #[inline]
79 pub const unsafe fn new_static(name: &'static CStr, interval: i32, burst: i32) -> Self {
80 Self {
82 inner: Opaque::new(bindings::ratelimit_state {
83 lock: kernel::sync::lock::spinlock::raw_spin_lock_unlocked(name),
84 interval,
85 burst,
86 ..pin_init::zeroed()
87 }),
88 }
89 }
90
91 pub const DEFAULT_INTERVAL: i32 = bindings::DEFAULT_RATELIMIT_INTERVAL as i32;
93
94 pub const DEFAULT_BURST: i32 = bindings::DEFAULT_RATELIMIT_BURST as i32;
96
97 #[inline]
101 pub fn ratelimit(&self, func: &CStr) -> bool {
102 unsafe { bindings::___ratelimit(self.inner.get(), func.as_char_ptr()) != 0 }
107 }
108}
109
110#[pinned_drop]
111impl PinnedDrop for Ratelimit {
112 #[inline]
113 fn drop(self: Pin<&mut Self>) {
114 unsafe { bindings::ratelimit_state_exit(self.inner.get()) };
117 }
118}
119
120#[macro_export]
122#[doc(hidden)]
123macro_rules! print_ratelimited {
124 ($print_macro:ident, $($arg:tt)*) => {{
125 $crate::ratelimit::ratelimit_state_init!(
126 _rs,
127 $crate::ratelimit::Ratelimit::DEFAULT_INTERVAL,
128 $crate::ratelimit::Ratelimit::DEFAULT_BURST,
129 );
130 let loc = $crate::c_str!(::core::concat!(::core::file!(), ":", ::core::line!()));
131 if $crate::ratelimit::Ratelimit::ratelimit(&_rs, loc) {
132 $crate::$print_macro!($($arg)*);
133 }
134 }};
135}
136
137#[macro_export]
139macro_rules! pr_emerg_ratelimited (
140 ($($arg:tt)*) => (
141 $crate::print_ratelimited!(pr_emerg, $($arg)*)
142 )
143);
144
145#[macro_export]
147macro_rules! pr_alert_ratelimited (
148 ($($arg:tt)*) => (
149 $crate::print_ratelimited!(pr_alert, $($arg)*)
150 )
151);
152
153#[macro_export]
155macro_rules! pr_crit_ratelimited (
156 ($($arg:tt)*) => (
157 $crate::print_ratelimited!(pr_crit, $($arg)*)
158 )
159);
160
161#[macro_export]
163macro_rules! pr_err_ratelimited (
164 ($($arg:tt)*) => (
165 $crate::print_ratelimited!(pr_err, $($arg)*)
166 )
167);
168
169#[macro_export]
171macro_rules! pr_warn_ratelimited (
172 ($($arg:tt)*) => (
173 $crate::print_ratelimited!(pr_warn, $($arg)*)
174 )
175);
176
177#[macro_export]
179macro_rules! pr_notice_ratelimited (
180 ($($arg:tt)*) => (
181 $crate::print_ratelimited!(pr_notice, $($arg)*)
182 )
183);
184
185#[macro_export]
187macro_rules! pr_info_ratelimited (
188 ($($arg:tt)*) => (
189 $crate::print_ratelimited!(pr_info, $($arg)*)
190 )
191);
192
193#[macro_export]
195macro_rules! pr_debug_ratelimited (
196 ($($arg:tt)*) => (
197 if cfg!(debug_assertions) {
198 $crate::print_ratelimited!(pr_debug, $($arg)*)
199 }
200 )
201);