1c0dd49bdSEiji Ota /*
2c0dd49bdSEiji Ota * CDDL HEADER START
3c0dd49bdSEiji Ota *
4c0dd49bdSEiji Ota * The contents of this file are subject to the terms of the
5c0dd49bdSEiji Ota * Common Development and Distribution License (the "License").
6c0dd49bdSEiji Ota * You may not use this file except in compliance with the License.
7c0dd49bdSEiji Ota *
8c0dd49bdSEiji Ota * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c0dd49bdSEiji Ota * or http://www.opensolaris.org/os/licensing.
10c0dd49bdSEiji Ota * See the License for the specific language governing permissions
11c0dd49bdSEiji Ota * and limitations under the License.
12c0dd49bdSEiji Ota *
13c0dd49bdSEiji Ota * When distributing Covered Code, include this CDDL HEADER in each
14c0dd49bdSEiji Ota * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c0dd49bdSEiji Ota * If applicable, add the following below this CDDL HEADER, with the
16c0dd49bdSEiji Ota * fields enclosed by brackets "[]" replaced with your own identifying
17c0dd49bdSEiji Ota * information: Portions Copyright [yyyy] [name of copyright owner]
18c0dd49bdSEiji Ota *
19c0dd49bdSEiji Ota * CDDL HEADER END
20c0dd49bdSEiji Ota */
21c0dd49bdSEiji Ota /*
22c0dd49bdSEiji Ota * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23c0dd49bdSEiji Ota */
24c0dd49bdSEiji Ota #include <sys/types.h>
25c0dd49bdSEiji Ota #include <sys/varargs.h>
26c0dd49bdSEiji Ota #include <sys/cmn_err.h>
27c0dd49bdSEiji Ota #include <sys/ddi.h>
28c0dd49bdSEiji Ota #include <sys/sunddi.h>
29*cadbfdc3SEiji Ota #include <sys/time.h>
30c0dd49bdSEiji Ota #include <sys/ib/clients/rdsv3/rdsv3_debug.h>
31c0dd49bdSEiji Ota
32c0dd49bdSEiji Ota /*
33c0dd49bdSEiji Ota * This file contains the debug defines and routines.
34c0dd49bdSEiji Ota * Debugging information is collected in a circular kernel buffer. Debug
35c0dd49bdSEiji Ota * messages with level lower than rdsv3dbglvl are ignored. The size of the
36c0dd49bdSEiji Ota * of the debug buffer can be changed by setting 'rdsv3_debug_buf_size' in
37c0dd49bdSEiji Ota * bytes in /etc/system.
38c0dd49bdSEiji Ota *
39c0dd49bdSEiji Ota * The debug buffer can be cleared by setting 'rdsv3_clear_debug_buf_flag = 1'
40c0dd49bdSEiji Ota * on a running system.
41c0dd49bdSEiji Ota */
42c0dd49bdSEiji Ota
43c0dd49bdSEiji Ota #define RDSV3_DEBUG_SIZE_EXTRA_ALLOC 8
44c0dd49bdSEiji Ota #define RDSV3_MIN_DEBUG_BUF_SIZE 0x1000
45c0dd49bdSEiji Ota #define RDSV3_FUNCNAME_LEN 40
46c0dd49bdSEiji Ota #define RDSV3_PRINTBUF_LEN 4096
47c0dd49bdSEiji Ota #ifdef DEBUG
48c0dd49bdSEiji Ota #define RDSV3_DEBUG_BUF_SIZE 0x200000 /* 2M size */
49c0dd49bdSEiji Ota #else
50c0dd49bdSEiji Ota #define RDSV3_DEBUG_BUF_SIZE 0x2000
51c0dd49bdSEiji Ota #endif /* DEBUG */
52c0dd49bdSEiji Ota
53c0dd49bdSEiji Ota /* Max length of a debug statement */
54c0dd49bdSEiji Ota #define RDSV3_PRINT_BUF_LEN 4096
55c0dd49bdSEiji Ota
56c0dd49bdSEiji Ota static int rdsv3_suppress_dprintf; /* Suppress debug printing */
57c0dd49bdSEiji Ota static int rdsv3_buffer_dprintf = 1; /* Use debug buffer (0 == console) */
58c0dd49bdSEiji Ota static int rdsv3_debug_buf_size = RDSV3_DEBUG_BUF_SIZE; /* Sz of Debug buf */
59c0dd49bdSEiji Ota static int rdsv3_allow_intr_msgs = 0; /* log "intr" messages */
60c0dd49bdSEiji Ota char *rdsv3_debug_buf = NULL; /* The Debug Buf */
61c0dd49bdSEiji Ota char *rdsv3_buf_sptr, *rdsv3_buf_eptr; /* debug buffer temp pointer */
62c0dd49bdSEiji Ota int rdsv3_clear_debug_buf_flag = 0; /* Clear debug buffer */
63c0dd49bdSEiji Ota uint_t rdsv3dbglvl = RDSV3_LOG_L4;
64c0dd49bdSEiji Ota
65c0dd49bdSEiji Ota /*
66c0dd49bdSEiji Ota * Print Buffer protected by mutex for debug stuff. The mutex also
67c0dd49bdSEiji Ota * ensures serializing debug messages.
68c0dd49bdSEiji Ota */
69c0dd49bdSEiji Ota static kmutex_t rdsv3_debug_mutex;
70c0dd49bdSEiji Ota static char rdsv3_print_buf[RDSV3_PRINT_BUF_LEN];
71c0dd49bdSEiji Ota
72c0dd49bdSEiji Ota /* Function Prototypes */
73c0dd49bdSEiji Ota static void rdsv3_clear_print_buf();
74c0dd49bdSEiji Ota
75c0dd49bdSEiji Ota /* RDS logging init */
76c0dd49bdSEiji Ota void
rdsv3_logging_initialization()77c0dd49bdSEiji Ota rdsv3_logging_initialization()
78c0dd49bdSEiji Ota {
79c0dd49bdSEiji Ota boolean_t flag = B_FALSE;
80c0dd49bdSEiji Ota
81c0dd49bdSEiji Ota mutex_init(&rdsv3_debug_mutex, NULL, MUTEX_DRIVER, NULL);
82c0dd49bdSEiji Ota mutex_enter(&rdsv3_debug_mutex);
83c0dd49bdSEiji Ota
84c0dd49bdSEiji Ota if (rdsv3_debug_buf_size <= RDSV3_DEBUG_SIZE_EXTRA_ALLOC) {
85c0dd49bdSEiji Ota rdsv3_debug_buf_size = RDSV3_MIN_DEBUG_BUF_SIZE;
86c0dd49bdSEiji Ota flag = B_TRUE;
87c0dd49bdSEiji Ota }
88c0dd49bdSEiji Ota
89c0dd49bdSEiji Ota /* if it is less that RDSV3_MIN_DEBUG_BUF_SIZE, adjust it */
90c0dd49bdSEiji Ota rdsv3_debug_buf_size = max(RDSV3_MIN_DEBUG_BUF_SIZE,
91c0dd49bdSEiji Ota rdsv3_debug_buf_size);
92c0dd49bdSEiji Ota
93c0dd49bdSEiji Ota rdsv3_debug_buf = (char *)kmem_alloc(rdsv3_debug_buf_size, KM_SLEEP);
94c0dd49bdSEiji Ota rdsv3_clear_print_buf();
95c0dd49bdSEiji Ota mutex_exit(&rdsv3_debug_mutex);
96c0dd49bdSEiji Ota
97c0dd49bdSEiji Ota if (flag == B_TRUE) {
98c0dd49bdSEiji Ota RDSV3_DPRINTF2("RDS", "rdsv3_debug_buf_size was too small, "
99c0dd49bdSEiji Ota "adjusted to %x", rdsv3_debug_buf_size);
100c0dd49bdSEiji Ota }
101c0dd49bdSEiji Ota }
102c0dd49bdSEiji Ota
103c0dd49bdSEiji Ota
104c0dd49bdSEiji Ota /* RDS logging destroy */
105c0dd49bdSEiji Ota void
rdsv3_logging_destroy()106c0dd49bdSEiji Ota rdsv3_logging_destroy()
107c0dd49bdSEiji Ota {
108c0dd49bdSEiji Ota mutex_enter(&rdsv3_debug_mutex);
109c0dd49bdSEiji Ota if (rdsv3_debug_buf) {
110c0dd49bdSEiji Ota kmem_free(rdsv3_debug_buf, rdsv3_debug_buf_size);
111c0dd49bdSEiji Ota rdsv3_debug_buf = NULL;
112c0dd49bdSEiji Ota }
113c0dd49bdSEiji Ota mutex_exit(&rdsv3_debug_mutex);
114c0dd49bdSEiji Ota mutex_destroy(&rdsv3_debug_mutex);
115c0dd49bdSEiji Ota }
116c0dd49bdSEiji Ota
117c0dd49bdSEiji Ota
118c0dd49bdSEiji Ota /*
119c0dd49bdSEiji Ota * debug, log, and console message handling
120c0dd49bdSEiji Ota */
121c0dd49bdSEiji Ota
122c0dd49bdSEiji Ota /*
123c0dd49bdSEiji Ota * clear the RDS debug buffer
124c0dd49bdSEiji Ota */
125c0dd49bdSEiji Ota static void
rdsv3_clear_print_buf()126c0dd49bdSEiji Ota rdsv3_clear_print_buf()
127c0dd49bdSEiji Ota {
128c0dd49bdSEiji Ota ASSERT(MUTEX_HELD(&rdsv3_debug_mutex));
129c0dd49bdSEiji Ota if (rdsv3_debug_buf) {
130c0dd49bdSEiji Ota rdsv3_buf_sptr = rdsv3_debug_buf;
131c0dd49bdSEiji Ota rdsv3_buf_eptr = rdsv3_debug_buf + rdsv3_debug_buf_size -
132c0dd49bdSEiji Ota RDSV3_DEBUG_SIZE_EXTRA_ALLOC;
133c0dd49bdSEiji Ota
134c0dd49bdSEiji Ota bzero(rdsv3_debug_buf, rdsv3_debug_buf_size);
135c0dd49bdSEiji Ota }
136c0dd49bdSEiji Ota }
137c0dd49bdSEiji Ota
138c0dd49bdSEiji Ota
139c0dd49bdSEiji Ota static void
rdsv3_vlog(char * name,uint_t level,char * fmt,va_list ap)140c0dd49bdSEiji Ota rdsv3_vlog(char *name, uint_t level, char *fmt, va_list ap)
141c0dd49bdSEiji Ota {
142c0dd49bdSEiji Ota char *label = (name == NULL) ? "rds" : name;
143c0dd49bdSEiji Ota char *msg_ptr;
144c0dd49bdSEiji Ota size_t len;
145c0dd49bdSEiji Ota
146c0dd49bdSEiji Ota mutex_enter(&rdsv3_debug_mutex);
147c0dd49bdSEiji Ota
148c0dd49bdSEiji Ota /* if not using logging scheme; quit */
149c0dd49bdSEiji Ota if (rdsv3_suppress_dprintf || (rdsv3_debug_buf == NULL)) {
150c0dd49bdSEiji Ota mutex_exit(&rdsv3_debug_mutex);
151c0dd49bdSEiji Ota return;
152c0dd49bdSEiji Ota }
153c0dd49bdSEiji Ota
154c0dd49bdSEiji Ota /* If user requests to clear debug buffer, go ahead */
155c0dd49bdSEiji Ota if (rdsv3_clear_debug_buf_flag != 0) {
156c0dd49bdSEiji Ota rdsv3_clear_print_buf();
157c0dd49bdSEiji Ota rdsv3_clear_debug_buf_flag = 0;
158c0dd49bdSEiji Ota }
159c0dd49bdSEiji Ota
160c0dd49bdSEiji Ota /*
161c0dd49bdSEiji Ota * put "label" into the buffer
162c0dd49bdSEiji Ota */
163c0dd49bdSEiji Ota len = snprintf(rdsv3_print_buf, RDSV3_FUNCNAME_LEN, "%s:\t", label);
164c0dd49bdSEiji Ota
165c0dd49bdSEiji Ota msg_ptr = rdsv3_print_buf + len;
166c0dd49bdSEiji Ota len += vsnprintf(msg_ptr, RDSV3_PRINT_BUF_LEN - len - 2, fmt, ap);
167c0dd49bdSEiji Ota
168c0dd49bdSEiji Ota len = min(len, RDSV3_PRINT_BUF_LEN - 2);
169c0dd49bdSEiji Ota ASSERT(len == strlen(rdsv3_print_buf));
170c0dd49bdSEiji Ota rdsv3_print_buf[len++] = '\n';
171c0dd49bdSEiji Ota rdsv3_print_buf[len] = '\0';
172c0dd49bdSEiji Ota
173c0dd49bdSEiji Ota /*
174c0dd49bdSEiji Ota * stuff the message in the debug buf
175c0dd49bdSEiji Ota */
176c0dd49bdSEiji Ota if (rdsv3_buffer_dprintf) {
177c0dd49bdSEiji Ota
178c0dd49bdSEiji Ota /*
179c0dd49bdSEiji Ota * overwrite >>>> that might be over the end of the
180c0dd49bdSEiji Ota * the buffer
181c0dd49bdSEiji Ota */
182c0dd49bdSEiji Ota *rdsv3_buf_sptr = '\0';
183c0dd49bdSEiji Ota
184c0dd49bdSEiji Ota if (rdsv3_buf_sptr + len > rdsv3_buf_eptr) {
185c0dd49bdSEiji Ota size_t left = (uintptr_t)rdsv3_buf_eptr -
186c0dd49bdSEiji Ota (uintptr_t)rdsv3_buf_sptr;
187c0dd49bdSEiji Ota
188c0dd49bdSEiji Ota bcopy((caddr_t)rdsv3_print_buf,
189c0dd49bdSEiji Ota (caddr_t)rdsv3_buf_sptr, left);
190c0dd49bdSEiji Ota bcopy((caddr_t)rdsv3_print_buf + left,
191c0dd49bdSEiji Ota (caddr_t)rdsv3_debug_buf, len - left);
192c0dd49bdSEiji Ota rdsv3_buf_sptr = rdsv3_debug_buf + len - left;
193c0dd49bdSEiji Ota } else {
194c0dd49bdSEiji Ota bcopy((caddr_t)rdsv3_print_buf, rdsv3_buf_sptr, len);
195c0dd49bdSEiji Ota rdsv3_buf_sptr += len;
196c0dd49bdSEiji Ota }
197c0dd49bdSEiji Ota
198c0dd49bdSEiji Ota /* add marker */
199c0dd49bdSEiji Ota (void) sprintf(rdsv3_buf_sptr, ">>>>");
200c0dd49bdSEiji Ota }
201c0dd49bdSEiji Ota
202c0dd49bdSEiji Ota /*
203c0dd49bdSEiji Ota * LINTR, L5-L2 message may go to the rdsv3_debug_buf
204c0dd49bdSEiji Ota * L1 messages will go to the /var/adm/messages (debug & non-debug).
205c0dd49bdSEiji Ota * L0 messages will go to console (debug & non-debug).
206c0dd49bdSEiji Ota */
207c0dd49bdSEiji Ota switch (level) {
208c0dd49bdSEiji Ota case RDSV3_LOG_LINTR:
209c0dd49bdSEiji Ota case RDSV3_LOG_L5:
210c0dd49bdSEiji Ota case RDSV3_LOG_L4:
211c0dd49bdSEiji Ota case RDSV3_LOG_L3:
212c0dd49bdSEiji Ota case RDSV3_LOG_L2:
213c0dd49bdSEiji Ota if (!rdsv3_buffer_dprintf) {
214c0dd49bdSEiji Ota cmn_err(CE_CONT, "^%s", rdsv3_print_buf);
215c0dd49bdSEiji Ota }
216c0dd49bdSEiji Ota break;
217c0dd49bdSEiji Ota case RDSV3_LOG_L1:
218c0dd49bdSEiji Ota if (!rdsv3_buffer_dprintf) {
219c0dd49bdSEiji Ota cmn_err(CE_CONT, "^%s", rdsv3_print_buf);
220c0dd49bdSEiji Ota } else {
221c0dd49bdSEiji Ota /* go to messages file */
222c0dd49bdSEiji Ota cmn_err(CE_CONT, "!%s", rdsv3_print_buf);
223c0dd49bdSEiji Ota }
224c0dd49bdSEiji Ota break;
225c0dd49bdSEiji Ota case RDSV3_LOG_L0:
226c0dd49bdSEiji Ota /* Strip the "\n" added earlier */
227c0dd49bdSEiji Ota if (rdsv3_print_buf[len - 1] == '\n') {
228c0dd49bdSEiji Ota rdsv3_print_buf[len - 1] = '\0';
229c0dd49bdSEiji Ota }
230c0dd49bdSEiji Ota if (msg_ptr[len - 1] == '\n') {
231c0dd49bdSEiji Ota msg_ptr[len - 1] = '\0';
232c0dd49bdSEiji Ota }
233c0dd49bdSEiji Ota /* go to console */
234c0dd49bdSEiji Ota cmn_err(CE_CONT, "^%s", rdsv3_print_buf);
235c0dd49bdSEiji Ota break;
236c0dd49bdSEiji Ota }
237c0dd49bdSEiji Ota
238c0dd49bdSEiji Ota mutex_exit(&rdsv3_debug_mutex);
239c0dd49bdSEiji Ota }
240c0dd49bdSEiji Ota
241c0dd49bdSEiji Ota void
rdsv3_dprintf_intr(char * name,char * fmt,...)242c0dd49bdSEiji Ota rdsv3_dprintf_intr(char *name, char *fmt, ...)
243c0dd49bdSEiji Ota {
244c0dd49bdSEiji Ota va_list ap;
245c0dd49bdSEiji Ota
246c0dd49bdSEiji Ota va_start(ap, fmt);
247c0dd49bdSEiji Ota rdsv3_vlog(name, RDSV3_LOG_LINTR, fmt, ap);
248c0dd49bdSEiji Ota va_end(ap);
249c0dd49bdSEiji Ota }
250c0dd49bdSEiji Ota
251c0dd49bdSEiji Ota /*
252c0dd49bdSEiji Ota * Check individual subsystem err levels
253c0dd49bdSEiji Ota */
254c0dd49bdSEiji Ota #define RDSV3_CHECK_ERR_LEVEL(level) \
255c0dd49bdSEiji Ota if (rdsv3dbglvl < level) \
256c0dd49bdSEiji Ota return; \
257c0dd49bdSEiji Ota
258c0dd49bdSEiji Ota void
rdsv3_dprintf5(char * name,char * fmt,...)259c0dd49bdSEiji Ota rdsv3_dprintf5(char *name, char *fmt, ...)
260c0dd49bdSEiji Ota {
261c0dd49bdSEiji Ota va_list ap;
262c0dd49bdSEiji Ota
263c0dd49bdSEiji Ota RDSV3_CHECK_ERR_LEVEL(RDSV3_LOG_L5);
264c0dd49bdSEiji Ota
265c0dd49bdSEiji Ota va_start(ap, fmt);
266c0dd49bdSEiji Ota rdsv3_vlog(name, RDSV3_LOG_L5, fmt, ap);
267c0dd49bdSEiji Ota va_end(ap);
268c0dd49bdSEiji Ota }
269c0dd49bdSEiji Ota
270c0dd49bdSEiji Ota void
rdsv3_dprintf4(char * name,char * fmt,...)271c0dd49bdSEiji Ota rdsv3_dprintf4(char *name, char *fmt, ...)
272c0dd49bdSEiji Ota {
273c0dd49bdSEiji Ota va_list ap;
274c0dd49bdSEiji Ota
275c0dd49bdSEiji Ota RDSV3_CHECK_ERR_LEVEL(RDSV3_LOG_L4);
276c0dd49bdSEiji Ota
277c0dd49bdSEiji Ota va_start(ap, fmt);
278c0dd49bdSEiji Ota rdsv3_vlog(name, RDSV3_LOG_L4, fmt, ap);
279c0dd49bdSEiji Ota va_end(ap);
280c0dd49bdSEiji Ota }
281c0dd49bdSEiji Ota
282c0dd49bdSEiji Ota void
rdsv3_dprintf3(char * name,char * fmt,...)283c0dd49bdSEiji Ota rdsv3_dprintf3(char *name, char *fmt, ...)
284c0dd49bdSEiji Ota {
285c0dd49bdSEiji Ota va_list ap;
286c0dd49bdSEiji Ota
287c0dd49bdSEiji Ota RDSV3_CHECK_ERR_LEVEL(RDSV3_LOG_L3);
288c0dd49bdSEiji Ota
289c0dd49bdSEiji Ota va_start(ap, fmt);
290c0dd49bdSEiji Ota rdsv3_vlog(name, RDSV3_LOG_L3, fmt, ap);
291c0dd49bdSEiji Ota va_end(ap);
292c0dd49bdSEiji Ota }
293c0dd49bdSEiji Ota
294c0dd49bdSEiji Ota void
rdsv3_dprintf2(char * name,char * fmt,...)295c0dd49bdSEiji Ota rdsv3_dprintf2(char *name, char *fmt, ...)
296c0dd49bdSEiji Ota {
297c0dd49bdSEiji Ota va_list ap;
298c0dd49bdSEiji Ota
299c0dd49bdSEiji Ota RDSV3_CHECK_ERR_LEVEL(RDSV3_LOG_L2);
300c0dd49bdSEiji Ota
301c0dd49bdSEiji Ota va_start(ap, fmt);
302c0dd49bdSEiji Ota rdsv3_vlog(name, RDSV3_LOG_L2, fmt, ap);
303c0dd49bdSEiji Ota va_end(ap);
304c0dd49bdSEiji Ota }
305c0dd49bdSEiji Ota
306c0dd49bdSEiji Ota void
rdsv3_dprintf1(char * name,char * fmt,...)307c0dd49bdSEiji Ota rdsv3_dprintf1(char *name, char *fmt, ...)
308c0dd49bdSEiji Ota {
309c0dd49bdSEiji Ota va_list ap;
310c0dd49bdSEiji Ota
311c0dd49bdSEiji Ota va_start(ap, fmt);
312c0dd49bdSEiji Ota rdsv3_vlog(name, RDSV3_LOG_L1, fmt, ap);
313c0dd49bdSEiji Ota va_end(ap);
314c0dd49bdSEiji Ota }
315c0dd49bdSEiji Ota
316c0dd49bdSEiji Ota
317c0dd49bdSEiji Ota /*
318c0dd49bdSEiji Ota * Function:
319c0dd49bdSEiji Ota * rdsv3_dprintf0
320c0dd49bdSEiji Ota * Input:
321c0dd49bdSEiji Ota * name - Name of the function generating the debug message
322c0dd49bdSEiji Ota * fmt - The message to be displayed.
323c0dd49bdSEiji Ota * Output:
324c0dd49bdSEiji Ota * none
325c0dd49bdSEiji Ota * Returns:
326c0dd49bdSEiji Ota * none
327c0dd49bdSEiji Ota * Description:
328c0dd49bdSEiji Ota * A generic log function to display RDS debug messages.
329c0dd49bdSEiji Ota */
330c0dd49bdSEiji Ota void
rdsv3_dprintf0(char * name,char * fmt,...)331c0dd49bdSEiji Ota rdsv3_dprintf0(char *name, char *fmt, ...)
332c0dd49bdSEiji Ota {
333c0dd49bdSEiji Ota va_list ap;
334c0dd49bdSEiji Ota
335c0dd49bdSEiji Ota va_start(ap, fmt);
336c0dd49bdSEiji Ota rdsv3_vlog(name, RDSV3_LOG_L0, fmt, ap);
337c0dd49bdSEiji Ota va_end(ap);
338c0dd49bdSEiji Ota }
339c0dd49bdSEiji Ota
340c0dd49bdSEiji Ota /* For ofed rdstrace */
341c0dd49bdSEiji Ota void
rdsv3_trace(char * name,uint8_t lvl,char * fmt,...)342c0dd49bdSEiji Ota rdsv3_trace(char *name, uint8_t lvl, char *fmt, ...)
343c0dd49bdSEiji Ota {
344c0dd49bdSEiji Ota va_list ap;
345c0dd49bdSEiji Ota
346c0dd49bdSEiji Ota va_start(ap, fmt);
347c0dd49bdSEiji Ota rdsv3_vlog(name, lvl, fmt, ap);
348c0dd49bdSEiji Ota va_end(ap);
349c0dd49bdSEiji Ota }
350*cadbfdc3SEiji Ota
351*cadbfdc3SEiji Ota #define DEFAULT_RATELIMIT_INTERVAL 5
352*cadbfdc3SEiji Ota #define DEFAULT_RATELIMIT_BURST 10
353*cadbfdc3SEiji Ota
354*cadbfdc3SEiji Ota struct ratelimit_state {
355*cadbfdc3SEiji Ota clock_t interval;
356*cadbfdc3SEiji Ota int burst;
357*cadbfdc3SEiji Ota int printed;
358*cadbfdc3SEiji Ota int missed;
359*cadbfdc3SEiji Ota hrtime_t begin;
360*cadbfdc3SEiji Ota kmutex_t lock;
361*cadbfdc3SEiji Ota };
362*cadbfdc3SEiji Ota
363*cadbfdc3SEiji Ota #define DEFINE_RATELIMIT_STATE(name, interval, burst) \
364*cadbfdc3SEiji Ota static struct ratelimit_state name = {interval, burst, }
365*cadbfdc3SEiji Ota
366*cadbfdc3SEiji Ota DEFINE_RATELIMIT_STATE(rdsv3_printk_ratelimit_state,
367*cadbfdc3SEiji Ota DEFAULT_RATELIMIT_INTERVAL,
368*cadbfdc3SEiji Ota DEFAULT_RATELIMIT_BURST);
369*cadbfdc3SEiji Ota
370*cadbfdc3SEiji Ota int
rdsv3_printk_ratelimit(void)371*cadbfdc3SEiji Ota rdsv3_printk_ratelimit(void)
372*cadbfdc3SEiji Ota {
373*cadbfdc3SEiji Ota struct ratelimit_state *rs = &rdsv3_printk_ratelimit_state;
374*cadbfdc3SEiji Ota hrtime_t current = gethrtime();
375*cadbfdc3SEiji Ota int rtn = 0;
376*cadbfdc3SEiji Ota
377*cadbfdc3SEiji Ota if (rs->interval) {
378*cadbfdc3SEiji Ota return (1);
379*cadbfdc3SEiji Ota }
380*cadbfdc3SEiji Ota mutex_enter(&rs->lock);
381*cadbfdc3SEiji Ota if (!rs->begin) {
382*cadbfdc3SEiji Ota rs->begin = current;
383*cadbfdc3SEiji Ota }
384*cadbfdc3SEiji Ota if (current < rs->begin + TICK_TO_NSEC(rs->interval)) {
385*cadbfdc3SEiji Ota if (rs->missed) {
386*cadbfdc3SEiji Ota RDSV3_DPRINTF0("rdsv3_printk_ratelimit: ",
387*cadbfdc3SEiji Ota "%d callbacks suppressed\n", rs->missed);
388*cadbfdc3SEiji Ota rs->begin = 0;
389*cadbfdc3SEiji Ota rs->printed = 0;
390*cadbfdc3SEiji Ota rs->missed = 0;
391*cadbfdc3SEiji Ota }
392*cadbfdc3SEiji Ota }
393*cadbfdc3SEiji Ota if (rs->burst && rs->burst > rs->printed) {
394*cadbfdc3SEiji Ota rs->printed++;
395*cadbfdc3SEiji Ota rtn = 1;
396*cadbfdc3SEiji Ota } else {
397*cadbfdc3SEiji Ota rs->missed++;
398*cadbfdc3SEiji Ota }
399*cadbfdc3SEiji Ota mutex_exit(&rs->lock);
400*cadbfdc3SEiji Ota return (rtn);
401*cadbfdc3SEiji Ota }
402