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.
11 #if DEBUG_TIME_LOCKS /* only include code if enabled */
13 /* Data structures to store lock() timing data. */
14 struct lock_timingdata timingdata
[TIMING_CATEGORIES
];
15 static unsigned long starttimes
[TIMING_CATEGORIES
][2];
20 void timer_start(int cat
, char *name
)
26 if (cat
< 0 || cat
>= TIMING_CATEGORIES
) return;
28 for(i
= 0; i
< sizeof(timingdata
[0].names
) && *name
; i
++)
29 timingdata
[cat
].names
[i
] = *name
++;
30 timingdata
[cat
].names
[sizeof(timingdata
[0].names
)-1] = '\0';
32 if (starttimes
[cat
][HIGHCOUNT
]) { return; }
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;
44 read_tsc(&starttimes
[cat
][HIGHCOUNT
], &starttimes
[cat
][LOWCOUNT
]);
47 void timer_end(int cat
)
49 unsigned long h
, l
, d
= 0, binsize
;
53 if (cat
< 0 || cat
>= TIMING_CATEGORIES
) return;
54 if (!starttimes
[cat
][HIGHCOUNT
]) {
55 timingdata
[cat
].misses
++;
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
);
64 timingdata
[cat
].misses
++;
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]) {
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
++;
87 bin
= (d
-timingdata
[cat
].lock_timings_range
[0]) /
88 timingdata
[cat
].binsize
;
89 if (bin
< 0 || bin
>= TIMING_POINTS
) {
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
++;
96 timingdata
[cat
].lock_timings
[bin
]++;
97 timingdata
[cat
].measurements
++;
103 #endif /* DEBUG_TIME_LOCKS */
105 #if DEBUG_SCHED_CHECK /* only include code if enabled */
107 #define MAX_LOOP (NR_PROCS + NR_TASKS)
110 check_runqueues(char *when
)
113 register struct proc
*xp
;
115 for (xp
= BEG_PROC_ADDR
; xp
< END_PROC_ADDR
; ++xp
) {
117 if (l
++ > MAX_LOOP
) { panic("check error", NO_NUM
); }
120 for (q
=l
=0; q
< NR_SCHED_QUEUES
; q
++) {
121 if (rdy_head
[q
] && !rdy_tail
[q
]) {
122 kprintf("head but no tail in %d: %s", q
, when
);
123 panic("scheduling error", NO_NUM
);
125 if (!rdy_head
[q
] && rdy_tail
[q
]) {
126 kprintf("tail but no head in %d: %s", q
, when
);
127 panic("scheduling error", NO_NUM
);
129 if (rdy_tail
[q
] && rdy_tail
[q
]->p_nextready
!= NIL_PROC
) {
130 kprintf("tail and tail->next not null in %d: %s", q
, when
);
131 panic("scheduling error", NO_NUM
);
133 for(xp
= rdy_head
[q
]; xp
!= NIL_PROC
; xp
= xp
->p_nextready
) {
135 kprintf("scheduling error: unready on runq %d proc %d: %s\n",
137 panic("found unready process on run queue", NO_NUM
);
139 if (xp
->p_priority
!= q
) {
140 kprintf("scheduling error: wrong priority q %d proc %d: %s\n",
142 panic("wrong priority", NO_NUM
);
145 kprintf("scheduling error: double sched q %d proc %d: %s\n",
147 panic("proc more than once on scheduling queue", NO_NUM
);
150 if (xp
->p_nextready
== NIL_PROC
&& rdy_tail
[q
] != xp
) {
151 kprintf("sched err: last element not tail q %d proc %d: %s\n",
153 panic("scheduling error", NO_NUM
);
155 if (l
++ > MAX_LOOP
) panic("loop in schedule queue?", NO_NUM
);
160 for (xp
= BEG_PROC_ADDR
; xp
< END_PROC_ADDR
; ++xp
) {
161 if (! isemptyp(xp
) && xp
->p_ready
&& ! xp
->p_found
) {
162 kprintf("sched error: ready proc %d not on queue: %s\n",
164 panic("ready proc not on scheduling queue", NO_NUM
);
165 if (l
++ > MAX_LOOP
) { panic("loop in proc.t?", NO_NUM
); }
170 #endif /* DEBUG_SCHED_CHECK */