ifq: Switch to drop-head for default enqueue method.
[dragonfly.git] / sys / kern / kern_ktr.c
bloba2698dfb43c02b493e89f25d370291ababc66ff4
1 /*
2 * Copyright (c) 2005 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
35 * The following copyright applies to the DDB command code:
37 * Copyright (c) 2000 John Baldwin <jhb@FreeBSD.org>
38 * All rights reserved.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the author nor the names of any co-contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
66 * Kernel tracepoint facility.
69 #include "opt_ddb.h"
70 #include "opt_ktr.h"
72 #include <sys/param.h>
73 #include <sys/cons.h>
74 #include <sys/kernel.h>
75 #include <sys/libkern.h>
76 #include <sys/proc.h>
77 #include <sys/sysctl.h>
78 #include <sys/ktr.h>
79 #include <sys/systm.h>
80 #include <sys/time.h>
81 #include <sys/malloc.h>
82 #include <sys/spinlock.h>
83 #include <sys/kbio.h>
84 #include <sys/ctype.h>
85 #include <sys/limits.h>
87 #include <sys/thread2.h>
88 #include <sys/spinlock2.h>
90 #include <machine/cpu.h>
91 #include <machine/cpufunc.h>
92 #include <machine/specialreg.h>
93 #include <machine/md_var.h>
95 #include <ddb/ddb.h>
97 #ifndef KTR_ENTRIES
98 #define KTR_ENTRIES 2048
99 #elif (KTR_ENTRIES & KTR_ENTRIES - 1)
100 #error KTR_ENTRIES must be a power of two
101 #endif
102 #define KTR_ENTRIES_MASK (KTR_ENTRIES - 1)
105 * Used by earlier boot; default value consumes ~64K BSS.
107 * NOTE:
108 * We use a small value here; this prevents kernel or module loading
109 * failure due to excessive BSS usage if KTR_ENTRIES is large.
111 #if (KTR_ENTRIES < 256)
112 #define KTR_ENTRIES_BOOT0 KTR_ENTRIES
113 #else
114 #define KTR_ENTRIES_BOOT0 256
115 #endif
116 #define KTR_ENTRIES_BOOT0_MASK (KTR_ENTRIES_BOOT0 - 1)
119 * test logging support. When ktr_testlogcnt is non-zero each synchronization
120 * interrupt will issue six back-to-back ktr logging messages on cpu 0
121 * so the user can determine KTR logging overheads.
123 #if !defined(KTR_TESTLOG)
124 #define KTR_TESTLOG KTR_ALL
125 #endif
126 KTR_INFO_MASTER(testlog);
127 #if KTR_TESTLOG
128 KTR_INFO(KTR_TESTLOG, testlog, charfmt, 0,
129 "charfmt %hhd %hhi %#hho %hhu %#hhx %#hhX\n",
130 signed char d1, signed char d2,
131 unsigned char d3, unsigned char d4,
132 unsigned char d5, unsigned char d6);
133 KTR_INFO(KTR_TESTLOG, testlog, shortfmt, 1,
134 "shortfmt %hd %hi %#ho %hu %#hx %#hX\n",
135 short d1, short d2,
136 unsigned short d3, unsigned short d4,
137 unsigned short d5, unsigned short d6);
138 KTR_INFO(KTR_TESTLOG, testlog, longfmt, 2,
139 "longfmt %ld %li %#lo %lu %#lx %#lX\n",
140 long d1, long d2,
141 unsigned long d3, unsigned long d4,
142 unsigned long d5, unsigned long d6);
143 KTR_INFO(KTR_TESTLOG, testlog, longlongfmt, 3,
144 "longlongfmt %lld %lli %#llo %llu %#llx %#llX\n",
145 long long d1, long long d2,
146 unsigned long long d3, unsigned long long d4,
147 unsigned long long d5, unsigned long long d6);
148 KTR_INFO(KTR_TESTLOG, testlog, intmaxfmt, 4,
149 "intmaxfmt %jd %ji %#jo %ju %#jx %#jX\n",
150 intmax_t d1, intmax_t d2,
151 uintmax_t d3, uintmax_t d4,
152 uintmax_t d5, uintmax_t d6);
153 KTR_INFO(KTR_TESTLOG, testlog, ptrdifffmt, 5,
154 "ptrdifffmt %td %ti\n",
155 ptrdiff_t d1, ptrdiff_t d2);
156 KTR_INFO(KTR_TESTLOG, testlog, sizefmt, 6,
157 "sizefmt %zd %zi %#zo %zu %#zx %#zX\n",
158 ssize_t d1, ssize_t d2,
159 size_t d3, size_t d4,
160 size_t d5, size_t d6);
161 KTR_INFO(KTR_TESTLOG, testlog, pingpong, 17, "pingpong");
162 KTR_INFO(KTR_TESTLOG, testlog, pipeline, 18, "pipeline");
163 KTR_INFO(KTR_TESTLOG, testlog, crit_beg, 19, "crit_beg");
164 KTR_INFO(KTR_TESTLOG, testlog, crit_end, 20, "crit_end");
165 KTR_INFO(KTR_TESTLOG, testlog, spin_beg, 21, "spin_beg");
166 KTR_INFO(KTR_TESTLOG, testlog, spin_end, 22, "spin_end");
167 #define logtest_noargs(name) KTR_LOG(testlog_ ## name)
168 #endif
170 MALLOC_DEFINE(M_KTR, "ktr", "ktr buffers");
172 SYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RW, 0, "ktr");
174 static int ktr_entries = KTR_ENTRIES_BOOT0;
175 SYSCTL_INT(_debug_ktr, OID_AUTO, entries, CTLFLAG_RD, &ktr_entries, 0,
176 "Size of the event buffer");
177 static int ktr_entries_mask = KTR_ENTRIES_BOOT0_MASK;
179 static int ktr_version = KTR_VERSION;
180 SYSCTL_INT(_debug_ktr, OID_AUTO, version, CTLFLAG_RD, &ktr_version, 0, "");
182 static int ktr_stacktrace = 1;
183 SYSCTL_INT(_debug_ktr, OID_AUTO, stacktrace, CTLFLAG_RD, &ktr_stacktrace, 0, "");
185 static int ktr_resynchronize = 0;
186 SYSCTL_INT(_debug_ktr, OID_AUTO, resynchronize, CTLFLAG_RW,
187 &ktr_resynchronize, 0, "Resynchronize TSC 10 times a second");
189 #if KTR_TESTLOG
190 static int ktr_testlogcnt = 0;
191 SYSCTL_INT(_debug_ktr, OID_AUTO, testlogcnt, CTLFLAG_RW, &ktr_testlogcnt, 0, "");
192 static int ktr_testipicnt = 0;
193 static int ktr_testipicnt_remainder;
194 SYSCTL_INT(_debug_ktr, OID_AUTO, testipicnt, CTLFLAG_RW, &ktr_testipicnt, 0, "");
195 static int ktr_testcritcnt = 0;
196 SYSCTL_INT(_debug_ktr, OID_AUTO, testcritcnt, CTLFLAG_RW, &ktr_testcritcnt, 0, "");
197 static int ktr_testspincnt = 0;
198 SYSCTL_INT(_debug_ktr, OID_AUTO, testspincnt, CTLFLAG_RW, &ktr_testspincnt, 0, "");
199 #endif
202 * Give cpu0 a static buffer so the tracepoint facility can be used during
203 * early boot (note however that we still use a critical section, XXX).
205 static struct ktr_entry ktr_buf0[KTR_ENTRIES_BOOT0];
207 struct ktr_cpu ktr_cpu[MAXCPU] = {
208 { .core.ktr_buf = &ktr_buf0[0] }
211 static int64_t ktr_sync_tsc;
212 struct callout ktr_resync_callout;
214 #ifdef KTR_VERBOSE
215 int ktr_verbose = KTR_VERBOSE;
216 TUNABLE_INT("debug.ktr.verbose", &ktr_verbose);
217 SYSCTL_INT(_debug_ktr, OID_AUTO, verbose, CTLFLAG_RW, &ktr_verbose, 0,
218 "Log events to the console as well");
219 #endif
221 static void ktr_resync_callback(void *dummy __unused);
223 extern int64_t tsc_offsets[];
225 static void
226 ktr_sysinit(void *dummy)
228 struct ktr_cpu_core *kcpu;
229 int i;
231 for (i = 0; i < ncpus; ++i) {
232 kcpu = &ktr_cpu[i].core;
233 kcpu->ktr_buf = kmalloc(KTR_ENTRIES * sizeof(struct ktr_entry),
234 M_KTR, M_WAITOK | M_ZERO);
235 if (i == 0) {
236 /* Migrate ktrs on CPU0 to the new location */
237 memcpy(kcpu->ktr_buf, ktr_buf0, sizeof(ktr_buf0));
240 cpu_sfence();
241 ktr_entries = KTR_ENTRIES;
242 ktr_entries_mask = KTR_ENTRIES_MASK;
244 callout_init_mp(&ktr_resync_callout);
245 callout_reset(&ktr_resync_callout, hz / 10, ktr_resync_callback, NULL);
247 SYSINIT(ktr_sysinit, SI_BOOT2_KLD, SI_ORDER_ANY, ktr_sysinit, NULL);
250 * Try to resynchronize the TSC's for all cpus. This is really, really nasty.
251 * We have to send an IPIQ message to all remote cpus, wait until they
252 * get into their IPIQ processing code loop, then do an even stricter hard
253 * loop to get the cpus as close to synchronized as we can to get the most
254 * accurate reading.
256 * This callback occurs on cpu0.
258 #if KTR_TESTLOG
259 static void ktr_pingpong_remote(void *dummy);
260 static void ktr_pipeline_remote(void *dummy);
261 #endif
263 #ifdef _RDTSC_SUPPORTED_
265 static void ktr_resync_remote(void *dummy);
268 * We use a callout callback instead of a systimer because we cannot afford
269 * to preempt anyone to do this, or we might deadlock a spin-lock or
270 * serializer between two cpus.
272 static
273 void
274 ktr_resync_callback(void *dummy __unused)
276 struct lwkt_cpusync cs;
277 #if KTR_TESTLOG
278 int count;
279 #endif
281 KKASSERT(mycpu->gd_cpuid == 0);
283 #if KTR_TESTLOG
285 * Test logging
287 if (ktr_testlogcnt) {
288 --ktr_testlogcnt;
289 cpu_disable_intr();
290 KTR_LOG(testlog_charfmt,
291 (signed char)UCHAR_MAX, (signed char)UCHAR_MAX,
292 (unsigned char)-1, (unsigned char)-1,
293 (unsigned char)-1, (unsigned char)-1);
294 KTR_LOG(testlog_shortfmt,
295 (short)USHRT_MAX, (short)USHRT_MAX,
296 (unsigned short)-1, (unsigned short)-1,
297 (unsigned short)-1, (unsigned short)-1);
298 KTR_LOG(testlog_longfmt,
299 (long)ULONG_MAX, (long)ULONG_MAX,
300 (unsigned long)-1, (unsigned long)-1,
301 (unsigned long)-1, (unsigned long)-1);
302 KTR_LOG(testlog_longlongfmt,
303 (long long)ULLONG_MAX, (long long)ULLONG_MAX,
304 (unsigned long long)-1, (unsigned long long)-1,
305 (unsigned long long)-1, (unsigned long long)-1);
306 KTR_LOG(testlog_intmaxfmt,
307 (intmax_t)UINTMAX_MAX, (intmax_t)UINTMAX_MAX,
308 (uintmax_t)-1, (uintmax_t)-1,
309 (uintmax_t)-1, (uintmax_t)-1);
310 KTR_LOG(testlog_ptrdifffmt,
311 (ptrdiff_t)PTRDIFF_MAX, (ptrdiff_t)PTRDIFF_MAX);
312 KTR_LOG(testlog_sizefmt,
313 (ssize_t)SIZE_T_MAX, (ssize_t)SIZE_T_MAX,
314 (size_t)-1, (size_t)-1,
315 (size_t)-1, (size_t)-1);
316 cpu_enable_intr();
320 * Test IPI messaging
322 if (ktr_testipicnt && ktr_testipicnt_remainder == 0 && ncpus > 1) {
323 ktr_testipicnt_remainder = ktr_testipicnt;
324 ktr_testipicnt = 0;
325 lwkt_send_ipiq_bycpu(1, ktr_pingpong_remote, NULL);
329 * Test critical sections
331 if (ktr_testcritcnt) {
332 crit_enter();
333 crit_exit();
334 logtest_noargs(crit_beg);
335 for (count = ktr_testcritcnt; count; --count) {
336 crit_enter();
337 crit_exit();
339 logtest_noargs(crit_end);
340 ktr_testcritcnt = 0;
344 * Test spinlock sections
346 if (ktr_testspincnt) {
347 struct spinlock spin;
349 spin_init(&spin, "ktrresync");
350 spin_lock(&spin);
351 spin_unlock(&spin);
352 logtest_noargs(spin_beg);
353 for (count = ktr_testspincnt; count; --count) {
354 spin_lock(&spin);
355 spin_unlock(&spin);
357 logtest_noargs(spin_end);
358 ktr_testspincnt = 0;
360 #endif
363 * Resynchronize the TSC
365 if (ktr_resynchronize == 0)
366 goto done;
367 if ((cpu_feature & CPUID_TSC) == 0)
368 return;
370 crit_enter();
371 lwkt_cpusync_init(&cs, smp_active_mask, ktr_resync_remote,
372 (void *)(intptr_t)mycpu->gd_cpuid);
373 lwkt_cpusync_interlock(&cs);
374 ktr_sync_tsc = rdtsc();
375 lwkt_cpusync_deinterlock(&cs);
376 crit_exit();
377 done:
378 callout_reset(&ktr_resync_callout, hz / 10, ktr_resync_callback, NULL);
382 * The remote-end of the KTR synchronization protocol runs on all cpus.
383 * The one we run on the controlling cpu updates its tsc continuously
384 * until the others have finished syncing (theoretically), but we don't
385 * loop forever.
387 * This is a bit ad-hoc but we need to avoid livelocking inside an IPI
388 * callback. rdtsc() is a synchronizing instruction (I think).
390 static void
391 ktr_resync_remote(void *arg)
393 globaldata_t gd = mycpu;
394 int64_t delta;
395 int i;
397 if (gd->gd_cpuid == (int)(intptr_t)arg) {
398 for (i = 0; i < 2000; ++i)
399 ktr_sync_tsc = rdtsc();
400 } else {
401 delta = rdtsc() - ktr_sync_tsc;
402 if (tsc_offsets[gd->gd_cpuid] == 0)
403 tsc_offsets[gd->gd_cpuid] = delta;
404 tsc_offsets[gd->gd_cpuid] =
405 (tsc_offsets[gd->gd_cpuid] * 7 + delta) / 8;
409 #if KTR_TESTLOG
411 static
412 void
413 ktr_pingpong_remote(void *dummy __unused)
415 int other_cpu;
417 logtest_noargs(pingpong);
418 other_cpu = 1 - mycpu->gd_cpuid;
419 if (ktr_testipicnt_remainder) {
420 --ktr_testipicnt_remainder;
421 lwkt_send_ipiq_bycpu(other_cpu, ktr_pingpong_remote, NULL);
422 } else {
423 lwkt_send_ipiq_bycpu(other_cpu, ktr_pipeline_remote, NULL);
424 lwkt_send_ipiq_bycpu(other_cpu, ktr_pipeline_remote, NULL);
425 lwkt_send_ipiq_bycpu(other_cpu, ktr_pipeline_remote, NULL);
426 lwkt_send_ipiq_bycpu(other_cpu, ktr_pipeline_remote, NULL);
427 lwkt_send_ipiq_bycpu(other_cpu, ktr_pipeline_remote, NULL);
431 static
432 void
433 ktr_pipeline_remote(void *dummy __unused)
435 logtest_noargs(pipeline);
438 #endif
440 #else /* !_RDTSC_SUPPORTED_ */
443 * The resync callback for UP doesn't do anything other then run the test
444 * log messages. If test logging is not enabled, don't bother resetting
445 * the callout.
447 static
448 void
449 ktr_resync_callback(void *dummy __unused)
451 #if KTR_TESTLOG
453 * Test logging
455 if (ktr_testlogcnt) {
456 --ktr_testlogcnt;
457 cpu_disable_intr();
458 KTR_LOG(testlog_charfmt,
459 (signed char)UCHAR_MAX, (signed char)UCHAR_MAX,
460 (unsigned char)-1, (unsigned char)-1,
461 (unsigned char)-1, (unsigned char)-1);
462 KTR_LOG(testlog_shortfmt,
463 (short)USHRT_MAX, (short)USHRT_MAX,
464 (unsigned short)-1, (unsigned short)-1,
465 (unsigned short)-1, (unsigned short)-1);
466 KTR_LOG(testlog_longfmt,
467 (long)ULONG_MAX, (long)ULONG_MAX,
468 (unsigned long)-1, (unsigned long)-1,
469 (unsigned long)-1, (unsigned long)-1);
470 KTR_LOG(testlog_longlongfmt,
471 (long long)ULLONG_MAX, (long long)ULLONG_MAX,
472 (unsigned long long)-1, (unsigned long long)-1,
473 (unsigned long long)-1, (unsigned long long)-1);
474 KTR_LOG(testlog_intmaxfmt,
475 (intmax_t)UINTMAX_MAX, (intmax_t)UINTMAX_MAX,
476 (uintmax_t)-1, (uintmax_t)-1,
477 (uintmax_t)-1, (uintmax_t)-1);
478 KTR_LOG(testlog_ptrdifffmt,
479 (ptrdiff_t)PTRDIFF_MAX, (ptrdiff_t)PTRDIFF_MAX);
480 KTR_LOG(testlog_sizefmt,
481 (ssize_t)SIZE_T_MAX, (ssize_t)SIZE_T_MAX,
482 (size_t)-1, (size_t)-1,
483 (size_t)-1, (size_t)-1);
484 cpu_enable_intr();
486 callout_reset(&ktr_resync_callout, hz / 10, ktr_resync_callback, NULL);
487 #endif
490 #endif
493 * Setup the next empty slot and return it to the caller to store the data
494 * directly.
496 struct ktr_entry *
497 ktr_begin_write_entry(struct ktr_info *info, const char *file, int line)
499 struct ktr_cpu_core *kcpu;
500 struct ktr_entry *entry;
501 int cpu;
503 cpu = mycpu->gd_cpuid;
504 kcpu = &ktr_cpu[cpu].core;
505 if (panicstr) /* stop logging during panic */
506 return NULL;
507 if (kcpu->ktr_buf == NULL) /* too early in boot */
508 return NULL;
510 crit_enter();
511 entry = kcpu->ktr_buf + (kcpu->ktr_idx & ktr_entries_mask);
512 ++kcpu->ktr_idx;
513 #ifdef _RDTSC_SUPPORTED_
514 if (cpu_feature & CPUID_TSC) {
515 entry->ktr_timestamp = rdtsc() - tsc_offsets[cpu];
516 } else
517 #endif
519 entry->ktr_timestamp = get_approximate_time_t();
521 entry->ktr_info = info;
522 entry->ktr_file = file;
523 entry->ktr_line = line;
524 crit_exit();
525 return entry;
529 ktr_finish_write_entry(struct ktr_info *info, struct ktr_entry *entry)
531 if (ktr_stacktrace)
532 cpu_ktr_caller(entry);
533 #ifdef KTR_VERBOSE
534 if (ktr_verbose && info->kf_format) {
535 kprintf("cpu%d ", mycpu->gd_cpuid);
536 if (ktr_verbose > 1) {
537 kprintf("%s.%d\t", entry->ktr_file, entry->ktr_line);
539 return !0;
541 #endif
542 return 0;
545 #ifdef DDB
547 #define NUM_LINES_PER_PAGE 19
549 struct tstate {
550 int cur;
551 int first;
554 static int db_ktr_verbose;
555 static int db_mach_vtrace(int cpu, struct ktr_entry *kp, int idx);
557 DB_SHOW_COMMAND(ktr, db_ktr_all)
559 struct ktr_cpu_core *kcpu;
560 int a_flag = 0;
561 int c;
562 int nl = 0;
563 int i;
564 struct tstate tstate[MAXCPU];
565 int printcpu = -1;
567 for(i = 0; i < ncpus; i++) {
568 kcpu = &ktr_cpu[i].core;
569 tstate[i].first = -1;
570 tstate[i].cur = (kcpu->ktr_idx - 1) & ktr_entries_mask;
572 db_ktr_verbose = 0;
573 while ((c = *(modif++)) != '\0') {
574 if (c == 'v') {
575 db_ktr_verbose = 1;
577 else if (c == 'a') {
578 a_flag = 1;
580 else if (c == 'c') {
581 printcpu = 0;
582 while ((c = *(modif++)) != '\0') {
583 if (isdigit(c)) {
584 printcpu *= 10;
585 printcpu += c - '0';
587 else {
588 modif++;
589 break;
592 modif--;
595 if (printcpu > ncpus - 1) {
596 db_printf("Invalid cpu number\n");
597 return;
600 * Loop throug all the buffers and print the content of them, sorted
601 * by the timestamp.
603 while (1) {
604 int counter;
605 u_int64_t highest_ts;
606 struct ktr_entry *kp;
607 int highest_cpu;
608 int c;
610 if (a_flag == 1) {
611 c = cncheckc();
612 if (c != -1 && c != NOKEY)
613 return;
615 highest_ts = 0;
616 highest_cpu = -1;
618 * Find the lowest timestamp
620 for (i = 0, counter = 0; i < ncpus; i++) {
621 kcpu = &ktr_cpu[i].core;
622 if (kcpu->ktr_buf == NULL)
623 continue;
624 if (printcpu != -1 && printcpu != i)
625 continue;
626 if (tstate[i].cur == -1) {
627 counter++;
628 if (counter == ncpus) {
629 db_printf("--- End of trace buffer ---\n");
630 return;
632 continue;
634 if (kcpu->ktr_buf[tstate[i].cur].ktr_timestamp > highest_ts) {
635 highest_ts = kcpu->ktr_buf[tstate[i].cur].ktr_timestamp;
636 highest_cpu = i;
639 if (highest_cpu < 0) {
640 db_printf("no KTR data available\n");
641 break;
643 i = highest_cpu;
644 kcpu = &ktr_cpu[i].core;
645 kp = &kcpu->ktr_buf[tstate[i].cur];
646 if (tstate[i].first == -1)
647 tstate[i].first = tstate[i].cur;
648 if (--tstate[i].cur < 0)
649 tstate[i].cur = ktr_entries - 1;
650 if (tstate[i].first == tstate[i].cur) {
651 db_mach_vtrace(i, kp, tstate[i].cur + 1);
652 tstate[i].cur = -1;
653 continue;
655 if (kcpu->ktr_buf[tstate[i].cur].ktr_info == NULL)
656 tstate[i].cur = -1;
657 if (db_more(&nl) == -1)
658 break;
659 if (db_mach_vtrace(i, kp, tstate[i].cur + 1) == 0)
660 tstate[i].cur = -1;
664 static int
665 db_mach_vtrace(int cpu, struct ktr_entry *kp, int idx)
667 if (kp->ktr_info == NULL)
668 return(0);
669 db_printf("cpu%d ", cpu);
670 db_printf("%d: ", idx);
671 if (db_ktr_verbose) {
672 db_printf("%10.10lld %s.%d\t", (long long)kp->ktr_timestamp,
673 kp->ktr_file, kp->ktr_line);
675 db_printf("%s\t", kp->ktr_info->kf_name);
676 db_printf("from(%p,%p) ", kp->ktr_caller1, kp->ktr_caller2);
677 db_printf("\n");
679 return(1);
682 #endif /* DDB */