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/taslock.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 "../port/error.h"
    7 #include "edf.h"
    8 
    9 long maxlockcycles;
   10 long maxilockcycles;
   11 long cumlockcycles;
   12 long cumilockcycles;
   13 ulong maxlockpc;
   14 ulong maxilockpc;
   15 
   16 struct
   17 {
   18         ulong   locks;
   19         ulong   glare;
   20         ulong   inglare;
   21 } lockstats;
   22 
   23 static void
   24 inccnt(Ref *r)
   25 {
   26         _xinc(&r->ref);
   27 }
   28 
   29 static int
   30 deccnt(Ref *r)
   31 {
   32         int x;
   33 
   34         x = _xdec(&r->ref);
   35         if(x < 0)
   36                 panic("deccnt pc=%#p", getcallerpc(&r));
   37         return x;
   38 }
   39 
   40 static void
   41 dumplockmem(char *tag, Lock *l)
   42 {
   43         uchar *cp;
   44         int i;
   45 
   46         iprint("%s: ", tag);
   47         cp = (uchar*)l;
   48         for(i = 0; i < 64; i++)
   49                 iprint("%2.2ux ", cp[i]);
   50         iprint("\n");
   51 }
   52 
   53 void
   54 lockloop(Lock *l, ulong pc)
   55 {
   56         Proc *p;
   57 
   58         p = l->p;
   59         print("lock %#p loop key %#lux pc %#lux held by pc %#lux proc %lud\n",
   60                 l, l->key, pc, l->pc, p ? p->pid : 0);
   61         dumpaproc(up);
   62         if(p != nil)
   63                 dumpaproc(p);
   64 }
   65 
   66 int
   67 lock(Lock *l)
   68 {
   69         int i;
   70         ulong pc;
   71 
   72         pc = getcallerpc(&l);
   73 
   74         lockstats.locks++;
   75         if(up)
   76                 inccnt(&up->nlocks);    /* prevent being scheded */
   77         if(tas(&l->key) == 0){
   78                 if(up)
   79                         up->lastlock = l;
   80                 l->pc = pc;
   81                 l->p = up;
   82                 l->isilock = 0;
   83 #ifdef LOCKCYCLES
   84                 l->lockcycles = -lcycles();
   85 #endif
   86                 return 0;
   87         }
   88         if(up)
   89                 deccnt(&up->nlocks);
   90 
   91         lockstats.glare++;
   92         for(;;){
   93                 lockstats.inglare++;
   94                 i = 0;
   95                 while(l->key){
   96                         if(conf.nmach < 2 && up && up->edf && (up->edf->flags & Admitted)){
   97                                 /*
   98                                  * Priority inversion, yield on a uniprocessor; on a
   99                                  * multiprocessor, the other processor will unlock
  100                                  */
  101                                 print("inversion %#p pc %#lux proc %lud held by pc %#lux proc %lud\n",
  102                                         l, pc, up ? up->pid : 0, l->pc, l->p ? l->p->pid : 0);
  103                                 up->edf->d = todget(nil);       /* yield to process with lock */
  104                         }
  105                         if(i++ > 100000000){
  106                                 i = 0;
  107                                 lockloop(l, pc);
  108                         }
  109                 }
  110                 if(up)
  111                         inccnt(&up->nlocks);
  112                 if(tas(&l->key) == 0){
  113                         if(up)
  114                                 up->lastlock = l;
  115                         l->pc = pc;
  116                         l->p = up;
  117                         l->isilock = 0;
  118 #ifdef LOCKCYCLES
  119                         l->lockcycles = -lcycles();
  120 #endif
  121                         return 1;
  122                 }
  123                 if(up)
  124                         deccnt(&up->nlocks);
  125         }
  126 }
  127 
  128 void
  129 ilock(Lock *l)
  130 {
  131         ulong x;
  132         ulong pc;
  133 
  134         pc = getcallerpc(&l);
  135         lockstats.locks++;
  136 
  137         x = splhi();
  138         if(tas(&l->key) != 0){
  139                 lockstats.glare++;
  140                 /*
  141                  * Cannot also check l->pc, l->m, or l->isilock here
  142                  * because they might just not be set yet, or
  143                  * (for pc and m) the lock might have just been unlocked.
  144                  */
  145                 for(;;){
  146                         lockstats.inglare++;
  147                         splx(x);
  148                         while(l->key)
  149                                 ;
  150                         x = splhi();
  151                         if(tas(&l->key) == 0)
  152                                 goto acquire;
  153                 }
  154         }
  155 acquire:
  156         m->ilockdepth++;
  157         if(up)
  158                 up->lastilock = l;
  159         l->sr = x;
  160         l->pc = pc;
  161         l->p = up;
  162         l->isilock = 1;
  163         l->m = MACHP(m->machno);
  164 #ifdef LOCKCYCLES
  165         l->lockcycles = -lcycles();
  166 #endif
  167 }
  168 
  169 int
  170 canlock(Lock *l)
  171 {
  172         if(up)
  173                 inccnt(&up->nlocks);
  174         if(tas(&l->key)){
  175                 if(up)
  176                         deccnt(&up->nlocks);
  177                 return 0;
  178         }
  179 
  180         if(up)
  181                 up->lastlock = l;
  182         l->pc = getcallerpc(&l);
  183         l->p = up;
  184         l->m = MACHP(m->machno);
  185         l->isilock = 0;
  186 #ifdef LOCKCYCLES
  187         l->lockcycles = -lcycles();
  188 #endif
  189         return 1;
  190 }
  191 
  192 void
  193 unlock(Lock *l)
  194 {
  195 #ifdef LOCKCYCLES
  196         l->lockcycles += lcycles();
  197         cumlockcycles += l->lockcycles;
  198         if(l->lockcycles > maxlockcycles){
  199                 maxlockcycles = l->lockcycles;
  200                 maxlockpc = l->pc;
  201         }
  202 #endif
  203         if(l->key == 0)
  204                 print("unlock: not locked: pc %#p\n", getcallerpc(&l));
  205         if(l->isilock)
  206                 print("unlock of ilock: pc %lux, held by %lux\n", getcallerpc(&l), l->pc);
  207         if(l->p != up)
  208                 print("unlock: up changed: pc %#p, acquired at pc %lux, lock p %#p, unlock up %#p\n", getcallerpc(&l), l->pc, l->p, up);
  209         l->m = nil;
  210         l->key = 0;
  211         coherence();
  212 
  213         if(up && deccnt(&up->nlocks) == 0 && up->delaysched && islo()){
  214                 /*
  215                  * Call sched if the need arose while locks were held
  216                  * But, don't do it from interrupt routines, hence the islo() test
  217                  */
  218                 sched();
  219         }
  220 }
  221 
  222 ulong ilockpcs[0x100] = { [0xff] = 1 };
  223 static int n;
  224 
  225 void
  226 iunlock(Lock *l)
  227 {
  228         ulong sr;
  229 
  230 #ifdef LOCKCYCLES
  231         l->lockcycles += lcycles();
  232         cumilockcycles += l->lockcycles;
  233         if(l->lockcycles > maxilockcycles){
  234                 maxilockcycles = l->lockcycles;
  235                 maxilockpc = l->pc;
  236         }
  237         if(l->lockcycles > 2400)
  238                 ilockpcs[n++ & 0xff]  = l->pc;
  239 #endif
  240         if(l->key == 0)
  241                 print("iunlock: not locked: pc %#p\n", getcallerpc(&l));
  242         if(!l->isilock)
  243                 print("iunlock of lock: pc %#p, held by %#lux\n", getcallerpc(&l), l->pc);
  244         if(islo())
  245                 print("iunlock while lo: pc %#p, held by %#lux\n", getcallerpc(&l), l->pc);
  246 
  247         sr = l->sr;
  248         l->m = nil;
  249         l->key = 0;
  250         coherence();
  251         m->ilockdepth--;
  252         if(up)
  253                 up->lastilock = nil;
  254         splx(sr);
  255 }

Cache object: 8d5acf9b9f5503d326a332e7f811d1d2


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