#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" struct { ulong rlock; ulong rlockq; ulong wlock; ulong wlockq; ulong qlock; ulong qlockq; } rwstats; void qlock(QLock *q) { Proc *p, *mp; lock(&q->use); rwstats.qlock++; if(!q->locked) { q->locked = 1; unlock(&q->use); return; } rwstats.qlockq++; p = q->tail; mp = up; if(p == 0) q->head = mp; else p->qnext = mp; q->tail = mp; mp->qnext = 0; mp->state = Queueing; unlock(&q->use); sched(); } int canqlock(QLock *q) { if(!canlock(&q->use)) return 0; if(q->locked){ unlock(&q->use); return 0; } q->locked = 1; unlock(&q->use); return 1; } void qunlock(QLock *q) { Proc *p; lock(&q->use); p = q->head; if(p) { q->head = p->qnext; if(q->head == 0) q->tail = 0; unlock(&q->use); ready(p); return; } q->locked = 0; unlock(&q->use); } void rlock(RWlock *q) { Proc *p, *mp; lock(&q->use); //{int i; //for(i=0; ipidr); i++) //if(q->pidr[i]==up->pid) //print("***already %d\n", up->pid); //} rwstats.rlock++; if(q->writer == 0 && q->head == nil){ /* no writer, go for it */ //{int i; //for(i=0; ipidr); i++) //if(q->pidr[i]==0) { //q->pidr[i]=up->pid; //break; //}} q->readers++; unlock(&q->use); return; } rwstats.rlockq++; p = q->tail; mp = up; if(p == 0) q->head = mp; else p->qnext = mp; q->tail = mp; mp->qnext = 0; mp->state = Queueing; //print("%d rl for w%d\n", up->pid, q->pidw); unlock(&q->use); sched(); } void runlock(RWlock *q) { Proc *p; lock(&q->use); //{int i; //for(i=0; ipidr); i++) //if(q->pidr[i]==up->pid) { //q->pidr[i] = 0; //break; //}} p = q->head; if(--(q->readers) > 0 || p == nil){ unlock(&q->use); return; } /* start waiting writer */ if(p->state != QueueingW) panic("runlock"); q->head = p->qnext; if(q->head == 0) q->tail = 0; q->writer = 1; //q->pidw = p->pid; unlock(&q->use); ready(p); } void wlock(RWlock *q) { Proc *p, *mp; lock(&q->use); rwstats.wlock++; if(q->readers == 0 && q->writer == 0){ /* noone waiting, go for it */ //q->pidw = up->pid; q->writer = 1; unlock(&q->use); return; } /* wait */ //rwstats.wlockq++; p = q->tail; mp = up; if(p == nil) q->head = mp; else p->qnext = mp; q->tail = mp; mp->qnext = 0; mp->state = QueueingW; //print("%d wl for %d%d", up->pid, q->readers, q->writer); //if(q->pidw) print(" w%d", q->pidw); //{int i; //for(i=0; ipidr); i++) //if(q->pidr[i]) //print(" %d", q->pidr[i]); //print("\n"); //} unlock(&q->use); sched(); } void wunlock(RWlock *q) { Proc *p; lock(&q->use); //if(q->pidw!=up->pid) //print("not qw\n"); //q->pidw = 0; p = q->head; if(p == nil){ q->writer = 0; unlock(&q->use); return; } if(p->state == QueueingW){ //q->pidw = p->pid; /* start waiting writer */ q->head = p->qnext; if(q->head == nil) q->tail = nil; unlock(&q->use); ready(p); return; } if(p->state != Queueing) panic("wunlock"); /* waken waiting readers */ while(q->head != nil && q->head->state == Queueing){ //{int i; //for(i=0;ipidr); i++) //if(q->pidr[i]==0) { //q->pidr[i] = p->pid; //break; //}} p = q->head; q->head = p->qnext; q->readers++; ready(p); } if(q->head == nil) q->tail = nil; q->writer = 0; unlock(&q->use); }