The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/debug.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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. */
   14 struct lock_timingdata timingdata[TIMING_CATEGORIES];
   15 static unsigned long starttimes[TIMING_CATEGORIES][2];
   16 
   17 #define HIGHCOUNT       0
   18 #define LOWCOUNT        1
   19 
   20 void 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 
   47 void 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 
  109 PUBLIC void
  110 check_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 */

Cache object: 61f38d0bd139598df921e11ccf9acc8f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.