xref: /netbsd-src/sys/external/bsd/drm2/include/linux/ratelimit.h (revision a9f15c751e2e217d5f372d8c1a63063be6af3730)
1 /*	$NetBSD: ratelimit.h,v 1.6 2022/04/09 23:44:25 riastradh Exp $	*/
2 
3 /*-
4  * Copyright (c) 2013 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Taylor R. Campbell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef _LINUX_RATELIMIT_H_
33 #define _LINUX_RATELIMIT_H_
34 
35 #include <sys/atomic.h>
36 #include <sys/stdbool.h>
37 #include <sys/time.h>
38 
39 #define	ratelimit_state	linux_ratelimit_state
40 
41 struct ratelimit_state {
42 	volatile int		missed;
43 
44 	volatile unsigned	rl_lock;
45 	struct timeval		rl_lasttime;
46 	int			rl_curpps;
47 	unsigned		rl_maxpps;
48 };
49 
50 enum {
51 	RATELIMIT_MSG_ON_RELEASE,
52 };
53 
54 /*
55  * XXX Assumes hz=100 so this works in static initializers, and/or
56  * hopes the caller just uses DEFAULT_RATELIMIT_INTERVAL and doesn't
57  * mention hz.
58  */
59 #define	DEFAULT_RATELIMIT_INTERVAL	(5*100)
60 #define	DEFAULT_RATELIMIT_BURST		10
61 
62 #define	DEFINE_RATELIMIT_STATE(n, i, b)					      \
63 	struct ratelimit_state n = {					      \
64 		.missed = 0,						      \
65 		.rl_lock = 0,						      \
66 		.rl_lasttime = { .tv_sec = 0, .tv_usec = 0 },		      \
67 		.rl_curpps = 0,						      \
68 		.rl_maxpps = (b)/((i)/100),				      \
69 	}
70 
71 static inline void
ratelimit_state_init(struct ratelimit_state * r,int interval,int burst)72 ratelimit_state_init(struct ratelimit_state *r, int interval, int burst)
73 {
74 
75 	memset(r, 0, sizeof(*r));
76 	r->rl_maxpps = burst/(interval/hz);
77 }
78 
79 static inline void
ratelimit_set_flags(struct ratelimit_state * r,unsigned long flags)80 ratelimit_set_flags(struct ratelimit_state *r, unsigned long flags)
81 {
82 }
83 
84 static inline bool
__ratelimit(struct ratelimit_state * r)85 __ratelimit(struct ratelimit_state *r)
86 {
87 	int ok;
88 
89 	if (atomic_swap_uint(&r->rl_lock, 1)) {
90 		ok = false;
91 		goto out;
92 	}
93 	membar_acquire();
94 	ok = ppsratecheck(&r->rl_lasttime, &r->rl_curpps, r->rl_maxpps);
95 	atomic_store_release(&r->rl_lock, 0);
96 
97 out:	if (!ok)
98 		atomic_store_relaxed(&r->missed, 1);
99 	return ok;
100 }
101 
102 #endif  /* _LINUX_RATELIMIT_H_ */
103