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/port/portclock.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 #include "u.h"
    2 #include "../port/lib.h"
    3 #include "mem.h"
    4 #include "dat.h"
    5 #include "fns.h"
    6 #include "io.h"
    7 #include "ureg.h"
    8 
    9 struct Timers
   10 {
   11         Lock;
   12         Timer   *head;
   13 };
   14 
   15 static Timers timers[MAXMACH];
   16 
   17 ulong intrcount[MAXMACH];
   18 ulong fcallcount[MAXMACH];
   19 
   20 static vlong
   21 tadd(Timers *tt, Timer *nt)
   22 {
   23         Timer *t, **last;
   24 
   25         /* Called with tt locked */
   26         assert(nt->tt == nil);
   27         switch(nt->tmode){
   28         default:
   29                 panic("timer");
   30                 break;
   31         case Trelative:
   32                 if(nt->tns <= 0)
   33                         nt->tns = 1;
   34                 nt->twhen = fastticks(nil) + ns2fastticks(nt->tns);
   35                 break;
   36         case Tperiodic:
   37                 assert(nt->tns >= 100000);      /* At least 100 µs period */
   38                 if(nt->twhen == 0){
   39                         /* look for another timer at same frequency for combining */
   40                         for(t = tt->head; t; t = t->tnext){
   41                                 if(t->tmode == Tperiodic && t->tns == nt->tns)
   42                                         break;
   43                         }
   44                         if (t)
   45                                 nt->twhen = t->twhen;
   46                         else
   47                                 nt->twhen = fastticks(nil);
   48                 }
   49                 nt->twhen += ns2fastticks(nt->tns);
   50                 break;
   51         }
   52 
   53         for(last = &tt->head; t = *last; last = &t->tnext){
   54                 if(t->twhen > nt->twhen)
   55                         break;
   56         }
   57         nt->tnext = *last;
   58         *last = nt;
   59         nt->tt = tt;
   60         if(last == &tt->head)
   61                 return nt->twhen;
   62         return 0;
   63 }
   64 
   65 static uvlong
   66 tdel(Timer *dt)
   67 {
   68 
   69         Timer *t, **last;
   70         Timers *tt;
   71 
   72         tt = dt->tt;
   73         if (tt == nil)
   74                 return 0;
   75         for(last = &tt->head; t = *last; last = &t->tnext){
   76                 if(t == dt){
   77                         assert(dt->tt);
   78                         dt->tt = nil;
   79                         *last = t->tnext;
   80                         break;
   81                 }
   82         }
   83         if(last == &tt->head && tt->head)
   84                 return tt->head->twhen;
   85         return 0;
   86 }
   87 
   88 /* add or modify a timer */
   89 void
   90 timeradd(Timer *nt)
   91 {
   92         Timers *tt;
   93         vlong when;
   94 
   95         /* Must lock Timer struct before Timers struct */
   96         ilock(nt);
   97         if(tt = nt->tt){
   98                 ilock(tt);
   99                 tdel(nt);
  100                 iunlock(tt);
  101         }
  102         tt = &timers[m->machno];
  103         ilock(tt);
  104         when = tadd(tt, nt);
  105         if(when)
  106                 timerset(when);
  107         iunlock(tt);
  108         iunlock(nt);
  109 }
  110 
  111 
  112 void
  113 timerdel(Timer *dt)
  114 {
  115         Timers *tt;
  116         uvlong when;
  117 
  118         ilock(dt);
  119         if(tt = dt->tt){
  120                 ilock(tt);
  121                 when = tdel(dt);
  122                 if(when && tt == &timers[m->machno])
  123                         timerset(tt->head->twhen);
  124                 iunlock(tt);
  125         }
  126         iunlock(dt);
  127 }
  128 
  129 void
  130 hzclock(Ureg *ur)
  131 {
  132         m->ticks++;
  133         if(m->proc)
  134                 m->proc->pc = ur->pc;
  135 
  136         if(m->flushmmu){
  137                 if(up)
  138                         flushmmu();
  139                 m->flushmmu = 0;
  140         }
  141 
  142         accounttime();
  143         kmapinval();
  144 
  145         if(kproftimer != nil)
  146                 kproftimer(ur->pc);
  147 
  148         if((active.machs&(1<<m->machno)) == 0)
  149                 return;
  150 
  151         if(active.exiting) {
  152                 print("someone's exiting\n");
  153                 exit(0);
  154         }
  155 
  156         checkalarms();
  157 
  158         if(up && up->state == Running)
  159                 hzsched();      /* in proc.c */
  160 }
  161 
  162 void
  163 timerintr(Ureg *u, Tval)
  164 {
  165         Timer *t;
  166         Timers *tt;
  167         uvlong when, now;
  168         int callhzclock;
  169         static int sofar;
  170 
  171         intrcount[m->machno]++;
  172         callhzclock = 0;
  173         tt = &timers[m->machno];
  174         now = fastticks(nil);
  175         ilock(tt);
  176         while(t = tt->head){
  177                 /*
  178                  * No need to ilock t here: any manipulation of t
  179                  * requires tdel(t) and this must be done with a
  180                  * lock to tt held.  We have tt, so the tdel will
  181                  * wait until we're done
  182                  */
  183                 when = t->twhen;
  184                 if(when > now){
  185                         timerset(when);
  186                         iunlock(tt);
  187                         if(callhzclock)
  188                                 hzclock(u);
  189                         return;
  190                 }
  191                 tt->head = t->tnext;
  192                 assert(t->tt == tt);
  193                 t->tt = nil;
  194                 fcallcount[m->machno]++;
  195                 iunlock(tt);
  196                 if(t->tf)
  197                         (*t->tf)(u, t);
  198                 else
  199                         callhzclock++;
  200                 ilock(tt);
  201                 if(t->tmode == Tperiodic)
  202                         tadd(tt, t);
  203         }
  204         iunlock(tt);
  205 }
  206 
  207 void
  208 timersinit(void)
  209 {
  210         Timer *t;
  211 
  212         /*
  213          * T->tf == nil means the HZ clock for this processor.
  214          */
  215         todinit();
  216         t = malloc(sizeof(*t));
  217         t->tmode = Tperiodic;
  218         t->tt = nil;
  219         t->tns = 1000000000/HZ;
  220         t->tf = nil;
  221         timeradd(t);
  222 }
  223 
  224 Timer*
  225 addclock0link(void (*f)(void), int ms)
  226 {
  227         Timer *nt;
  228         uvlong when;
  229 
  230         /* Synchronize to hztimer if ms is 0 */
  231         nt = malloc(sizeof(Timer));
  232         if(ms == 0)
  233                 ms = 1000/HZ;
  234         nt->tns = (vlong)ms*1000000LL;
  235         nt->tmode = Tperiodic;
  236         nt->tt = nil;
  237         nt->tf = (void (*)(Ureg*, Timer*))f;
  238 
  239         ilock(&timers[0]);
  240         when = tadd(&timers[0], nt);
  241         if(when)
  242                 timerset(when);
  243         iunlock(&timers[0]);
  244         return nt;
  245 }
  246 
  247 /*
  248  *  This tk2ms avoids overflows that the macro version is prone to.
  249  *  It is a LOT slower so shouldn't be used if you're just converting
  250  *  a delta.
  251  */
  252 ulong
  253 tk2ms(ulong ticks)
  254 {
  255         uvlong t, hz;
  256 
  257         t = ticks;
  258         hz = HZ;
  259         t *= 1000L;
  260         t = t/hz;
  261         ticks = t;
  262         return ticks;
  263 }
  264 
  265 ulong
  266 ms2tk(ulong ms)
  267 {
  268         /* avoid overflows at the cost of precision */
  269         if(ms >= 1000000000/HZ)
  270                 return (ms/1000)*HZ;
  271         return (ms*HZ+500)/1000;
  272 }

Cache object: 1d4b116b77d87475b69c5b63a8ea459a


[ 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.