]>
Commit | Line | Data |
---|---|---|
715f6251 | 1 | /* |
2 | * This file is part of the SPL: Solaris Porting Layer. | |
3 | * | |
4 | * Copyright (c) 2008 Lawrence Livermore National Security, LLC. | |
5 | * Produced at Lawrence Livermore National Laboratory | |
6 | * Written by: | |
7 | * Brian Behlendorf <behlendorf1@llnl.gov>, | |
8 | * Herb Wartens <wartens2@llnl.gov>, | |
9 | * Jim Garlick <garlick@llnl.gov> | |
10 | * UCRL-CODE-235197 | |
11 | * | |
12 | * This is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by | |
14 | * the Free Software Foundation; either version 2 of the License, or | |
15 | * (at your option) any later version. | |
16 | * | |
17 | * This is distributed in the hope that it will be useful, but WITHOUT | |
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
19 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License along | |
23 | * with this program; if not, write to the Free Software Foundation, Inc., | |
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
25 | */ | |
26 | ||
f4b37741 | 27 | #ifndef _SPL_DEBUG_H |
28 | #define _SPL_DEBUG_H | |
29 | ||
cc7449cc | 30 | #ifdef __cplusplus |
31 | extern "C" { | |
32 | #endif | |
33 | ||
57d1b188 | 34 | #include <linux/sched.h> /* THREAD_SIZE */ |
35 | #include <linux/proc_fs.h> | |
36 | ||
8d0f1ee9 | 37 | extern unsigned long spl_debug_mask; |
38 | extern unsigned long spl_debug_subsys; | |
39 | ||
57d1b188 | 40 | #define S_UNDEFINED 0x00000001 |
41 | #define S_ATOMIC 0x00000002 | |
42 | #define S_KOBJ 0x00000004 | |
43 | #define S_VNODE 0x00000008 | |
44 | #define S_TIME 0x00000010 | |
45 | #define S_RWLOCK 0x00000020 | |
46 | #define S_THREAD 0x00000040 | |
47 | #define S_CONDVAR 0x00000080 | |
48 | #define S_MUTEX 0x00000100 | |
49 | #define S_RNG 0x00000200 | |
50 | #define S_TASKQ 0x00000400 | |
51 | #define S_KMEM 0x00000800 | |
52 | #define S_DEBUG 0x00001000 | |
53 | #define S_GENERIC 0x00002000 | |
54 | #define S_PROC 0x00004000 | |
937879f1 | 55 | #define S_MODULE 0x00008000 |
ec7d53e9 | 56 | #define S_CRED 0x00010000 |
57d1b188 | 57 | |
58 | #define D_TRACE 0x00000001 | |
59 | #define D_INFO 0x00000002 | |
60 | #define D_WARNING 0x00000004 | |
61 | #define D_ERROR 0x00000008 | |
62 | #define D_EMERG 0x00000010 | |
63 | #define D_CONSOLE 0x00000020 | |
64 | #define D_IOCTL 0x00000040 | |
65 | #define D_DPRINTF 0x00000080 | |
66 | #define D_OTHER 0x00000100 | |
67 | ||
68 | #define D_CANTMASK (D_ERROR | D_EMERG | D_WARNING | D_CONSOLE) | |
69 | #define DEBUG_SUBSYSTEM S_UNDEFINED | |
70 | ||
71 | int debug_init(void); | |
72 | void debug_fini(void); | |
73 | int spl_debug_mask2str(char *str, int size, unsigned long mask, int is_subsys); | |
74 | int spl_debug_str2mask(unsigned long *mask, const char *str, int is_subsys); | |
75 | ||
76 | extern unsigned long spl_debug_subsys; | |
77 | extern unsigned long spl_debug_mask; | |
78 | extern unsigned long spl_debug_printk; | |
79 | extern int spl_debug_mb; | |
80 | extern unsigned int spl_debug_binary; | |
81 | extern unsigned int spl_debug_catastrophe; | |
82 | extern unsigned int spl_debug_panic_on_bug; | |
83 | extern char spl_debug_file_path[PATH_MAX]; | |
84 | extern unsigned int spl_console_ratelimit; | |
85 | extern long spl_console_max_delay; | |
86 | extern long spl_console_min_delay; | |
87 | extern unsigned int spl_console_backoff; | |
88 | extern unsigned int spl_debug_stack; | |
89 | ||
b831734a | 90 | #define TCD_MAX_PAGES (5 << (20 - PAGE_SHIFT)) |
91 | #define TCD_STOCK_PAGES (TCD_MAX_PAGES) | |
92 | #define TRACE_CONSOLE_BUFFER_SIZE 1024 | |
57d1b188 | 93 | |
b831734a | 94 | #define SPL_DEFAULT_MAX_DELAY (600 * HZ) |
95 | #define SPL_DEFAULT_MIN_DELAY ((HZ + 1) / 2) | |
96 | #define SPL_DEFAULT_BACKOFF 2 | |
57d1b188 | 97 | |
7fea96c0 | 98 | #define DL_NOTHREAD 0x0001 /* Do not create a new thread */ |
b831734a | 99 | #define DL_SINGLE_CPU 0x0002 /* Collect pages from this CPU */ |
7fea96c0 | 100 | |
101 | typedef struct dumplog_priv { | |
102 | wait_queue_head_t dp_waitq; | |
103 | pid_t dp_pid; | |
104 | int dp_flags; | |
105 | atomic_t dp_done; | |
106 | } dumplog_priv_t; | |
107 | ||
57d1b188 | 108 | typedef struct { |
109 | unsigned long cdls_next; | |
110 | int cdls_count; | |
111 | long cdls_delay; | |
112 | } spl_debug_limit_state_t; | |
113 | ||
114 | /* Three trace data types */ | |
115 | typedef enum { | |
116 | TCD_TYPE_PROC, | |
117 | TCD_TYPE_SOFTIRQ, | |
118 | TCD_TYPE_IRQ, | |
119 | TCD_TYPE_MAX | |
120 | } tcd_type_t; | |
121 | ||
122 | union trace_data_union { | |
123 | struct trace_cpu_data { | |
124 | /* pages with trace records not yet processed by tracefiled */ | |
125 | struct list_head tcd_pages; | |
126 | /* number of pages on ->tcd_pages */ | |
127 | unsigned long tcd_cur_pages; | |
128 | /* Max number of pages allowed on ->tcd_pages */ | |
129 | unsigned long tcd_max_pages; | |
130 | ||
131 | /* | |
132 | * preallocated pages to write trace records into. Pages from | |
133 | * ->tcd_stock_pages are moved to ->tcd_pages by spl_debug_msg(). | |
134 | * | |
135 | * This list is necessary, because on some platforms it's | |
136 | * impossible to perform efficient atomic page allocation in a | |
137 | * non-blockable context. | |
138 | * | |
139 | * Such platforms fill ->tcd_stock_pages "on occasion", when | |
140 | * tracing code is entered in blockable context. | |
141 | * | |
142 | * trace_get_tage_try() tries to get a page from | |
143 | * ->tcd_stock_pages first and resorts to atomic page | |
144 | * allocation only if this queue is empty. ->tcd_stock_pages | |
145 | * is replenished when tracing code is entered in blocking | |
146 | * context (darwin-tracefile.c:trace_get_tcd()). We try to | |
147 | * maintain TCD_STOCK_PAGES (40 by default) pages in this | |
148 | * queue. Atomic allocation is only required if more than | |
149 | * TCD_STOCK_PAGES pagesful are consumed by trace records all | |
150 | * emitted in non-blocking contexts. Which is quite unlikely. | |
151 | */ | |
152 | struct list_head tcd_stock_pages; | |
153 | /* number of pages on ->tcd_stock_pages */ | |
154 | unsigned long tcd_cur_stock_pages; | |
155 | ||
156 | unsigned short tcd_shutting_down; | |
157 | unsigned short tcd_cpu; | |
158 | unsigned short tcd_type; | |
159 | /* The factors to share debug memory. */ | |
160 | unsigned short tcd_pages_factor; | |
f6c81c5e | 161 | |
162 | /* | |
163 | * This spinlock is needed to workaround the problem of | |
164 | * set_cpus_allowed() being GPL-only. Since we cannot | |
165 | * schedule a thread on a specific CPU when dumping the | |
166 | * pages, we must use the spinlock for mutual exclusion. | |
167 | */ | |
168 | spinlock_t tcd_lock; | |
169 | unsigned long tcd_lock_flags; | |
57d1b188 | 170 | } tcd; |
171 | char __pad[L1_CACHE_ALIGN(sizeof(struct trace_cpu_data))]; | |
172 | }; | |
173 | ||
174 | extern union trace_data_union (*trace_data[TCD_TYPE_MAX])[NR_CPUS]; | |
175 | ||
176 | #define tcd_for_each(tcd, i, j) \ | |
ac95d097 | 177 | for (i = 0; i < TCD_TYPE_MAX && trace_data[i]; i++) \ |
57d1b188 | 178 | for (j = 0, ((tcd) = &(*trace_data[i])[j].tcd); \ |
179 | j < num_possible_cpus(); j++, (tcd) = &(*trace_data[i])[j].tcd) | |
180 | ||
f6c81c5e | 181 | #define tcd_for_each_type_lock(tcd, i, cpu) \ |
124ca8a5 | 182 | for (i = 0; i < TCD_TYPE_MAX && trace_data[i] && \ |
f6c81c5e | 183 | (tcd = &(*trace_data[i])[cpu].tcd) && \ |
57d1b188 | 184 | trace_lock_tcd(tcd); trace_unlock_tcd(tcd), i++) |
185 | ||
186 | struct trace_page { | |
187 | struct page * page; /* page itself */ | |
188 | struct list_head linkage; /* Used by lists in trace_data_union */ | |
189 | unsigned int used; /* number of bytes used within this page */ | |
190 | unsigned short cpu; /* cpu that owns this page */ | |
191 | unsigned short type; /* type(context) of this page */ | |
192 | }; | |
193 | ||
194 | struct page_collection { | |
51117639 BB |
195 | struct list_head pc_pages; |
196 | spinlock_t pc_lock; | |
197 | int pc_want_daemon_pages; | |
57d1b188 | 198 | }; |
199 | ||
b831734a | 200 | #define SBUG() spl_debug_bug(__FILE__, __FUNCTION__, __LINE__, 0); |
2fae1b3d | 201 | |
cc7449cc | 202 | #ifdef NDEBUG |
203 | ||
204 | #define CDEBUG_STACK() (0) | |
51117639 BB |
205 | #define CDEBUG_LIMIT(x, y, z, a...) ((void)0) |
206 | #define __CDEBUG_LIMIT(x, y, z, a...) ((void)0) | |
cc7449cc | 207 | #define CDEBUG(mask, format, a...) ((void)0) |
208 | #define CWARN(fmt, a...) ((void)0) | |
209 | #define CERROR(fmt, a...) ((void)0) | |
210 | #define CEMERG(fmt, a...) ((void)0) | |
211 | #define CONSOLE(mask, fmt, a...) ((void)0) | |
212 | ||
213 | #define ENTRY ((void)0) | |
214 | #define EXIT ((void)0) | |
215 | #define RETURN(x) return (x) | |
216 | #define GOTO(x, y) { ((void)(y)); goto x; } | |
217 | ||
218 | #define __ASSERT(x) ((void)0) | |
219 | #define __ASSERT_TAGE_INVARIANT(x) ((void)0) | |
220 | #define ASSERT(x) ((void)0) | |
51117639 | 221 | #define ASSERTF(x, y, z...) ((void)0) |
3a68dc53 | 222 | #define ASSERTV(x) |
c8e60837 | 223 | #define VERIFY(cond) \ |
224 | do { \ | |
225 | if (unlikely(!(cond))) { \ | |
226 | printk(KERN_ERR "VERIFY(" #cond ") failed\n"); \ | |
227 | SBUG(); \ | |
228 | } \ | |
229 | } while (0) | |
cc7449cc | 230 | |
c8e60837 | 231 | #define VERIFY3_IMPL(LEFT, OP, RIGHT, TYPE, FMT, CAST) \ |
232 | do { \ | |
233 | if (!((TYPE)(LEFT) OP (TYPE)(RIGHT))) { \ | |
51117639 BB |
234 | printk(KERN_ERR \ |
235 | "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ | |
236 | "failed (" FMT " " #OP " " FMT ")\n", \ | |
237 | CAST (LEFT), CAST (RIGHT)); \ | |
c8e60837 | 238 | SBUG(); \ |
239 | } \ | |
240 | } while (0) | |
cc7449cc | 241 | |
c8e60837 | 242 | #define VERIFY3S(x,y,z) VERIFY3_IMPL(x, y, z, int64_t, "%lld", (long long)) |
243 | #define VERIFY3U(x,y,z) VERIFY3_IMPL(x, y, z, uint64_t, "%llu", \ | |
244 | (unsigned long long)) | |
cc7449cc | 245 | #define VERIFY3P(x,y,z) VERIFY3_IMPL(x, y, z, uintptr_t, "%p", (void *)) |
246 | ||
c8e60837 | 247 | #define ASSERT3S(x,y,z) ((void)0) |
248 | #define ASSERT3U(x,y,z) ((void)0) | |
249 | #define ASSERT3P(x,y,z) ((void)0) | |
cc7449cc | 250 | |
251 | #else /* NDEBUG */ | |
252 | ||
937879f1 | 253 | #ifdef __ia64__ |
254 | #define CDEBUG_STACK() (THREAD_SIZE - \ | |
255 | ((unsigned long)__builtin_dwarf_cfa() & \ | |
256 | (THREAD_SIZE - 1))) | |
257 | #else | |
258 | #define CDEBUG_STACK() (THREAD_SIZE - \ | |
259 | ((unsigned long)__builtin_frame_address(0) & \ | |
260 | (THREAD_SIZE - 1))) | |
261 | # endif /* __ia64__ */ | |
262 | ||
b831734a | 263 | /* DL_SINGLE_CPU flag is passed to spl_debug_bug() because we are about |
264 | * to over run our stack and likely damage at least one other unknown | |
265 | * thread stack. We must finish generating the needed debug info within | |
266 | * this thread context because once we yeild the CPU its very likely | |
267 | * the system will crash. | |
7fea96c0 | 268 | */ |
937879f1 | 269 | #define __CHECK_STACK(file, func, line) \ |
270 | do { \ | |
b831734a | 271 | if (unlikely(CDEBUG_STACK() > spl_debug_stack)) { \ |
272 | spl_debug_stack = CDEBUG_STACK(); \ | |
937879f1 | 273 | \ |
b831734a | 274 | if (unlikely(CDEBUG_STACK() > (4 * THREAD_SIZE) / 5)) { \ |
275 | spl_debug_msg(NULL, D_TRACE, D_WARNING, \ | |
276 | file, func, line, "Error " \ | |
277 | "exceeded maximum safe stack " \ | |
278 | "size (%lu/%lu)\n", \ | |
279 | CDEBUG_STACK(), THREAD_SIZE); \ | |
280 | spl_debug_bug(file, func, line, DL_SINGLE_CPU); \ | |
281 | } \ | |
937879f1 | 282 | } \ |
283 | } while (0) | |
284 | ||
c65d62d8 BB |
285 | /* NOTE: The run time stack overflow checking is being disabled by default |
286 | * because it is not safe for use with 2.6.29 and latter kernels. These | |
287 | * kernels do now have their own stack overflow checking so this support | |
288 | * has become redundant anyway. It can be re-enabled for older kernels or | |
289 | * arches without stack overflow checking by redefining CHECK_STACK(). | |
290 | * | |
291 | * #define CHECK_STACK() __CHECK_STACK(__FILE__, __func__, __LINE__) | |
292 | */ | |
293 | #define CHECK_STACK() ((void)0) | |
937879f1 | 294 | |
57d1b188 | 295 | /* ASSERTION that is safe to use within the debug system */ |
b831734a | 296 | #define __ASSERT(cond) \ |
297 | do { \ | |
298 | if (unlikely(!(cond))) { \ | |
c8e60837 | 299 | printk(KERN_ERR "ASSERTION(" #cond ") failed\n"); \ |
6e605b6e | 300 | BUG(); \ |
b831734a | 301 | } \ |
57d1b188 | 302 | } while (0) |
303 | ||
b831734a | 304 | #define __ASSERT_TAGE_INVARIANT(tage) \ |
305 | do { \ | |
306 | __ASSERT(tage != NULL); \ | |
307 | __ASSERT(tage->page != NULL); \ | |
308 | __ASSERT(tage->used <= PAGE_SIZE); \ | |
309 | __ASSERT(page_count(tage->page) > 0); \ | |
57d1b188 | 310 | } while(0) |
311 | ||
312 | /* ASSERTION that will debug log used outside the debug sysytem */ | |
313 | #define ASSERT(cond) \ | |
314 | do { \ | |
b831734a | 315 | CHECK_STACK(); \ |
316 | \ | |
57d1b188 | 317 | if (unlikely(!(cond))) { \ |
318 | spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \ | |
319 | __FILE__, __FUNCTION__, __LINE__, \ | |
320 | "ASSERTION(" #cond ") failed\n"); \ | |
b831734a | 321 | SBUG(); \ |
322 | } \ | |
57d1b188 | 323 | } while (0) |
324 | ||
325 | #define ASSERTF(cond, fmt, a...) \ | |
326 | do { \ | |
b831734a | 327 | CHECK_STACK(); \ |
328 | \ | |
57d1b188 | 329 | if (unlikely(!(cond))) { \ |
330 | spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \ | |
331 | __FILE__, __FUNCTION__, __LINE__, \ | |
c30df9c8 | 332 | "ASSERTION(" #cond ") failed: " fmt, \ |
57d1b188 | 333 | ## a); \ |
b831734a | 334 | SBUG(); \ |
57d1b188 | 335 | } \ |
336 | } while (0) | |
337 | ||
338 | #define VERIFY3_IMPL(LEFT, OP, RIGHT, TYPE, FMT, CAST) \ | |
339 | do { \ | |
b831734a | 340 | CHECK_STACK(); \ |
341 | \ | |
342 | if (!((TYPE)(LEFT) OP (TYPE)(RIGHT))) { \ | |
57d1b188 | 343 | spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \ |
344 | __FILE__, __FUNCTION__, __LINE__, \ | |
51117639 BB |
345 | "VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \ |
346 | "failed (" FMT " " #OP " " FMT ")\n", \ | |
b831734a | 347 | CAST (LEFT), CAST (RIGHT)); \ |
348 | SBUG(); \ | |
57d1b188 | 349 | } \ |
350 | } while (0) | |
351 | ||
c8e60837 | 352 | #define VERIFY3S(x,y,z) VERIFY3_IMPL(x, y, z, int64_t, "%lld", (long long)) |
e4f3ea27 | 353 | #define VERIFY3U(x,y,z) VERIFY3_IMPL(x, y, z, uint64_t, "%llu", \ |
c8e60837 | 354 | (unsigned long long)) |
57d1b188 | 355 | #define VERIFY3P(x,y,z) VERIFY3_IMPL(x, y, z, uintptr_t, "%p", (void *)) |
356 | ||
357 | #define ASSERT3S(x,y,z) VERIFY3S(x, y, z) | |
358 | #define ASSERT3U(x,y,z) VERIFY3U(x, y, z) | |
359 | #define ASSERT3P(x,y,z) VERIFY3P(x, y, z) | |
360 | ||
3a68dc53 | 361 | #define ASSERTV(x) x |
b831734a | 362 | #define VERIFY(x) ASSERT(x) |
57d1b188 | 363 | |
57d1b188 | 364 | #define __CDEBUG(cdls, subsys, mask, format, a...) \ |
365 | do { \ | |
366 | CHECK_STACK(); \ | |
367 | \ | |
368 | if (((mask) & D_CANTMASK) != 0 || \ | |
369 | ((spl_debug_mask & (mask)) != 0 && \ | |
370 | (spl_debug_subsys & (subsys)) != 0)) \ | |
371 | spl_debug_msg(cdls, subsys, mask, \ | |
372 | __FILE__, __FUNCTION__, __LINE__, \ | |
373 | format, ## a); \ | |
374 | } while (0) | |
375 | ||
376 | #define CDEBUG(mask, format, a...) \ | |
377 | __CDEBUG(NULL, DEBUG_SUBSYSTEM, mask, format, ## a) | |
378 | ||
379 | #define __CDEBUG_LIMIT(subsys, mask, format, a...) \ | |
380 | do { \ | |
381 | static spl_debug_limit_state_t cdls; \ | |
382 | \ | |
383 | __CDEBUG(&cdls, subsys, mask, format, ## a); \ | |
384 | } while (0) | |
385 | ||
386 | #define CDEBUG_LIMIT(mask, format, a...) \ | |
387 | __CDEBUG_LIMIT(DEBUG_SUBSYSTEM, mask, format, ## a) | |
388 | ||
57d1b188 | 389 | #define CWARN(fmt, a...) CDEBUG_LIMIT(D_WARNING, fmt, ## a) |
390 | #define CERROR(fmt, a...) CDEBUG_LIMIT(D_ERROR, fmt, ## a) | |
391 | #define CEMERG(fmt, a...) CDEBUG_LIMIT(D_EMERG, fmt, ## a) | |
392 | #define CONSOLE(mask, fmt, a...) CDEBUG(D_CONSOLE | (mask), fmt, ## a) | |
393 | ||
394 | #define GOTO(label, rc) \ | |
395 | do { \ | |
396 | long GOTO__ret = (long)(rc); \ | |
397 | CDEBUG(D_TRACE,"Process leaving via %s (rc=%lu : %ld : %lx)\n", \ | |
398 | #label, (unsigned long)GOTO__ret, (signed long)GOTO__ret,\ | |
399 | (signed long)GOTO__ret); \ | |
400 | goto label; \ | |
401 | } while (0) | |
402 | ||
403 | #define RETURN(rc) \ | |
404 | do { \ | |
405 | typeof(rc) RETURN__ret = (rc); \ | |
406 | CDEBUG(D_TRACE, "Process leaving (rc=%lu : %ld : %lx)\n", \ | |
407 | (long)RETURN__ret, (long)RETURN__ret, (long)RETURN__ret);\ | |
408 | return RETURN__ret; \ | |
409 | } while (0) | |
410 | ||
9ab1ac14 | 411 | #define __ENTRY(subsys) \ |
57d1b188 | 412 | do { \ |
9ab1ac14 | 413 | __CDEBUG(NULL, subsys, D_TRACE, "Process entered\n"); \ |
57d1b188 | 414 | } while (0) |
415 | ||
9ab1ac14 | 416 | #define __EXIT(subsys) \ |
57d1b188 | 417 | do { \ |
9ab1ac14 | 418 | __CDEBUG(NULL, subsys, D_TRACE, "Process leaving\n"); \ |
57d1b188 | 419 | } while(0) |
420 | ||
51117639 | 421 | #define ENTRY __ENTRY(DEBUG_SUBSYSTEM) |
9ab1ac14 | 422 | #define EXIT __EXIT(DEBUG_SUBSYSTEM) |
cc7449cc | 423 | #endif /* NDEBUG */ |
424 | ||
425 | #define spl_debug_msg(cdls, subsys, mask, file, fn, line, format, a...) \ | |
426 | spl_debug_vmsg(cdls, subsys, mask, file, fn, \ | |
427 | line, NULL, NULL, format, ##a) | |
9ab1ac14 | 428 | |
57d1b188 | 429 | extern int spl_debug_vmsg(spl_debug_limit_state_t *cdls, int subsys, int mask, |
b831734a | 430 | const char *file, const char *fn, const int line, |
431 | const char *format1, va_list args, const char *format2, ...); | |
57d1b188 | 432 | |
433 | extern unsigned long spl_debug_set_mask(unsigned long mask); | |
434 | extern unsigned long spl_debug_get_mask(void); | |
435 | extern unsigned long spl_debug_set_subsys(unsigned long mask); | |
436 | extern unsigned long spl_debug_get_subsys(void); | |
437 | extern int spl_debug_set_mb(int mb); | |
438 | extern int spl_debug_get_mb(void); | |
439 | ||
7fea96c0 | 440 | extern int spl_debug_dumplog(int flags); |
57d1b188 | 441 | extern void spl_debug_dumpstack(struct task_struct *tsk); |
7fea96c0 | 442 | extern void spl_debug_bug(char *file, const char *func, const int line, int flags); |
57d1b188 | 443 | |
444 | extern int spl_debug_clear_buffer(void); | |
445 | extern int spl_debug_mark_buffer(char *text); | |
8d0f1ee9 | 446 | |
cc7449cc | 447 | #ifdef __cplusplus |
448 | } | |
449 | #endif | |
450 | ||
f4b37741 | 451 | #endif /* SPL_DEBUG_H */ |