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