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/qlock.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 
    7 struct {
    8         ulong rlock;
    9         ulong rlockq;
   10         ulong wlock;
   11         ulong wlockq;
   12         ulong qlock;
   13         ulong qlockq;
   14 } rwstats;
   15 
   16 void
   17 qlock(QLock *q)
   18 {
   19         Proc *p;
   20 
   21         if(m->ilockdepth != 0)
   22                 print("qlock: %#p: ilockdepth %d\n", getcallerpc(&q), m->ilockdepth);
   23         if(up != nil && up->nlocks.ref)
   24                 print("qlock: %#p: nlocks %lud\n", getcallerpc(&q), up->nlocks.ref);
   25 
   26         if(q->use.key == 0x55555555)
   27                 panic("qlock: q %#p, key 5*\n", q);
   28         lock(&q->use);
   29         rwstats.qlock++;
   30         if(!q->locked) {
   31                 q->locked = 1;
   32                 unlock(&q->use);
   33                 return;
   34         }
   35         if(up == 0)
   36                 panic("qlock");
   37         rwstats.qlockq++;
   38         p = q->tail;
   39         if(p == 0)
   40                 q->head = up;
   41         else
   42                 p->qnext = up;
   43         q->tail = up;
   44         up->qnext = 0;
   45         up->state = Queueing;
   46         up->qpc = getcallerpc(&q);
   47         unlock(&q->use);
   48         sched();
   49 }
   50 
   51 int
   52 canqlock(QLock *q)
   53 {
   54         if(!canlock(&q->use))
   55                 return 0;
   56         if(q->locked){
   57                 unlock(&q->use);
   58                 return 0;
   59         }
   60         q->locked = 1;
   61         unlock(&q->use);
   62         return 1;
   63 }
   64 
   65 void
   66 qunlock(QLock *q)
   67 {
   68         Proc *p;
   69 
   70         lock(&q->use);
   71         if (q->locked == 0)
   72                 print("qunlock called with qlock not held, from %#p\n",
   73                         getcallerpc(&q));
   74         p = q->head;
   75         if(p){
   76                 q->head = p->qnext;
   77                 if(q->head == 0)
   78                         q->tail = 0;
   79                 unlock(&q->use);
   80                 ready(p);
   81                 return;
   82         }
   83         q->locked = 0;
   84         unlock(&q->use);
   85 }
   86 
   87 void
   88 rlock(RWlock *q)
   89 {
   90         Proc *p;
   91 
   92         lock(&q->use);
   93         rwstats.rlock++;
   94         if(q->writer == 0 && q->head == nil){
   95                 /* no writer, go for it */
   96                 q->readers++;
   97                 unlock(&q->use);
   98                 return;
   99         }
  100 
  101         rwstats.rlockq++;
  102         p = q->tail;
  103         if(up == nil)
  104                 panic("rlock");
  105         if(p == 0)
  106                 q->head = up;
  107         else
  108                 p->qnext = up;
  109         q->tail = up;
  110         up->qnext = 0;
  111         up->state = QueueingR;
  112         unlock(&q->use);
  113         sched();
  114 }
  115 
  116 void
  117 runlock(RWlock *q)
  118 {
  119         Proc *p;
  120 
  121         lock(&q->use);
  122         p = q->head;
  123         if(--(q->readers) > 0 || p == nil){
  124                 unlock(&q->use);
  125                 return;
  126         }
  127 
  128         /* start waiting writer */
  129         if(p->state != QueueingW)
  130                 panic("runlock");
  131         q->head = p->qnext;
  132         if(q->head == 0)
  133                 q->tail = 0;
  134         q->writer = 1;
  135         unlock(&q->use);
  136         ready(p);
  137 }
  138 
  139 void
  140 wlock(RWlock *q)
  141 {
  142         Proc *p;
  143 
  144         lock(&q->use);
  145         rwstats.wlock++;
  146         if(q->readers == 0 && q->writer == 0){
  147                 /* noone waiting, go for it */
  148                 q->wpc = getcallerpc(&q);
  149                 q->wproc = up;
  150                 q->writer = 1;
  151                 unlock(&q->use);
  152                 return;
  153         }
  154 
  155         /* wait */
  156         rwstats.wlockq++;
  157         p = q->tail;
  158         if(up == nil)
  159                 panic("wlock");
  160         if(p == nil)
  161                 q->head = up;
  162         else
  163                 p->qnext = up;
  164         q->tail = up;
  165         up->qnext = 0;
  166         up->state = QueueingW;
  167         unlock(&q->use);
  168         sched();
  169 }
  170 
  171 void
  172 wunlock(RWlock *q)
  173 {
  174         Proc *p;
  175 
  176         lock(&q->use);
  177         p = q->head;
  178         if(p == nil){
  179                 q->writer = 0;
  180                 unlock(&q->use);
  181                 return;
  182         }
  183         if(p->state == QueueingW){
  184                 /* start waiting writer */
  185                 q->head = p->qnext;
  186                 if(q->head == nil)
  187                         q->tail = nil;
  188                 unlock(&q->use);
  189                 ready(p);
  190                 return;
  191         }
  192 
  193         if(p->state != QueueingR)
  194                 panic("wunlock");
  195 
  196         /* waken waiting readers */
  197         while(q->head != nil && q->head->state == QueueingR){
  198                 p = q->head;
  199                 q->head = p->qnext;
  200                 q->readers++;
  201                 ready(p);
  202         }
  203         if(q->head == nil)
  204                 q->tail = nil;
  205         q->writer = 0;
  206         unlock(&q->use);
  207 }
  208 
  209 /* same as rlock but punts if there are any writers waiting */
  210 int
  211 canrlock(RWlock *q)
  212 {
  213         lock(&q->use);
  214         rwstats.rlock++;
  215         if(q->writer == 0 && q->head == nil){
  216                 /* no writer, go for it */
  217                 q->readers++;
  218                 unlock(&q->use);
  219                 return 1;
  220         }
  221         unlock(&q->use);
  222         return 0;
  223 }

Cache object: 4f93b74b8e1a214be37bf70c9d315712


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