source: trunk/minix/kernel/debug.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 4.6 KB
Line 
1/* This file implements kernel debugging functionality that is not included
2 * in the standard kernel. Available functionality includes timing of lock
3 * functions and sanity checking of the scheduling queues.
4 */
5
6#include "kernel.h"
7#include "proc.h"
8#include "debug.h"
9#include <limits.h>
10
11#if DEBUG_TIME_LOCKS /* only include code if enabled */
12
13/* Data structures to store lock() timing data. */
14struct lock_timingdata timingdata[TIMING_CATEGORIES];
15static unsigned long starttimes[TIMING_CATEGORIES][2];
16
17#define HIGHCOUNT 0
18#define LOWCOUNT 1
19
20void timer_start(int cat, char *name)
21{
22 static int init = 0;
23 unsigned long h, l;
24 int i;
25
26 if (cat < 0 || cat >= TIMING_CATEGORIES) return;
27
28 for(i = 0; i < sizeof(timingdata[0].names) && *name; i++)
29 timingdata[cat].names[i] = *name++;
30 timingdata[0].names[sizeof(timingdata[0].names)-1] = '\0';
31
32 if (starttimes[cat][HIGHCOUNT]) { return; }
33
34 if (!init) {
35 int t, f;
36 init = 1;
37 for(t = 0; t < TIMING_CATEGORIES; t++) {
38 timingdata[t].lock_timings_range[0] = 0;
39 timingdata[t].resets = timingdata[t].misses =
40 timingdata[t].measurements = 0;
41 }
42 }
43
44 read_tsc(&starttimes[cat][HIGHCOUNT], &starttimes[cat][LOWCOUNT]);
45}
46
47void timer_end(int cat)
48{
49 unsigned long h, l, d = 0, binsize;
50 int bin;
51
52 read_tsc(&h, &l);
53 if (cat < 0 || cat >= TIMING_CATEGORIES) return;
54 if (!starttimes[cat][HIGHCOUNT]) {
55 timingdata[cat].misses++;
56 return;
57 }
58 if (starttimes[cat][HIGHCOUNT] == h) {
59 d = (l - starttimes[cat][1]);
60 } else if (starttimes[cat][HIGHCOUNT] == h-1 &&
61 starttimes[cat][LOWCOUNT] > l) {
62 d = ((ULONG_MAX - starttimes[cat][LOWCOUNT]) + l);
63 } else {
64 timingdata[cat].misses++;
65 return;
66 }
67 starttimes[cat][HIGHCOUNT] = 0;
68 if (!timingdata[cat].lock_timings_range[0] ||
69 d < timingdata[cat].lock_timings_range[0] ||
70 d > timingdata[cat].lock_timings_range[1]) {
71 int t;
72 if (!timingdata[cat].lock_timings_range[0] ||
73 d < timingdata[cat].lock_timings_range[0])
74 timingdata[cat].lock_timings_range[0] = d;
75 if (!timingdata[cat].lock_timings_range[1] ||
76 d > timingdata[cat].lock_timings_range[1])
77 timingdata[cat].lock_timings_range[1] = d;
78 for(t = 0; t < TIMING_POINTS; t++)
79 timingdata[cat].lock_timings[t] = 0;
80 timingdata[cat].binsize =
81 (timingdata[cat].lock_timings_range[1] -
82 timingdata[cat].lock_timings_range[0])/(TIMING_POINTS+1);
83 if (timingdata[cat].binsize < 1)
84 timingdata[cat].binsize = 1;
85 timingdata[cat].resets++;
86 }
87 bin = (d-timingdata[cat].lock_timings_range[0]) /
88 timingdata[cat].binsize;
89 if (bin < 0 || bin >= TIMING_POINTS) {
90 int t;
91 /* this indicates a bug, but isn't really serious */
92 for(t = 0; t < TIMING_POINTS; t++)
93 timingdata[cat].lock_timings[t] = 0;
94 timingdata[cat].misses++;
95 } else {
96 timingdata[cat].lock_timings[bin]++;
97 timingdata[cat].measurements++;
98 }
99
100 return;
101}
102
103#endif /* DEBUG_TIME_LOCKS */
104
105#if DEBUG_SCHED_CHECK /* only include code if enabled */
106
107#define PROCLIMIT 10000
108
109PUBLIC void
110check_runqueues(char *when)
111{
112 int q, l = 0;
113 register struct proc *xp;
114
115 for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
116 xp->p_found = 0;
117 if (l++ > PROCLIMIT) { panic("check error", NO_NUM); }
118 }
119
120 for (q=0; q < NR_SCHED_QUEUES; q++) {
121 if (rdy_head[q] && !rdy_tail[q]) {
122 kprintf("head but no tail: %s", when);
123 panic("scheduling error", NO_NUM);
124 }
125 if (!rdy_head[q] && rdy_tail[q]) {
126 kprintf("tail but no head: %s", when);
127 panic("scheduling error", NO_NUM);
128 }
129 if (rdy_tail[q] && rdy_tail[q]->p_nextready != NIL_PROC) {
130 kprintf("tail and tail->next not null; %s", when);
131 panic("scheduling error", NO_NUM);
132 }
133 for(xp = rdy_head[q]; xp != NIL_PROC; xp = xp->p_nextready) {
134 if (!xp->p_ready) {
135 kprintf("scheduling error: unready on runq: %s\n", when);
136
137 panic("found unready process on run queue", NO_NUM);
138 }
139 if (xp->p_priority != q) {
140 kprintf("scheduling error: wrong priority: %s\n", when);
141
142 panic("wrong priority", NO_NUM);
143 }
144 if (xp->p_found) {
145 kprintf("scheduling error: double scheduling: %s\n", when);
146 panic("proc more than once on scheduling queue", NO_NUM);
147 }
148 xp->p_found = 1;
149 if (xp->p_nextready == NIL_PROC && rdy_tail[q] != xp) {
150 kprintf("scheduling error: last element not tail: %s\n", when);
151 panic("scheduling error", NO_NUM);
152 }
153 if (l++ > PROCLIMIT) panic("loop in schedule queue?", NO_NUM);
154 }
155 }
156
157 for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
158 if (! isemptyp(xp) && xp->p_ready && ! xp->p_found) {
159 kprintf("scheduling error: ready not on queue: %s\n", when);
160 panic("ready proc not on scheduling queue", NO_NUM);
161 if (l++ > PROCLIMIT) { panic("loop in proc.t?", NO_NUM); }
162 }
163 }
164}
165
166#endif /* DEBUG_SCHED_CHECK */
Note: See TracBrowser for help on using the repository browser.