123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- #include "u.h"
- #include "lib.h"
- #include "dat.h"
- #include "fns.h"
- #include "io.h"
- #include "mem.h"
- void
- lock(Lock *l)
- {
- int i;
- /*
- * Try the fast grab first
- */
- loop:
- if(tas(l) == 0)
- return;
- for(i = 0; i < 1000000; i++) {
- if(tas(l) == 0)
- return;
- /* If we are spl low resched */
- if(getstatus() & IFLAG)
- sched();
- }
- l->sbsem = 0;
- print("lock loop 0x%lux called by 0x%lux held by pc 0x%lux\n", (ulong)l,
- getcallerpc(&l), l->pc);
- goto loop;
- }
- void
- ilock(Lock *l)
- {
- l->sr = splhi();
- lock(l);
- }
- void
- iunlock(Lock *l)
- {
- ulong sr;
- sr = l->sr;
- l->sbsem = 0;
- l->pc = 0;
- splx(sr);
- }
- int
- canlock(Lock *l)
- {
- if (tas(l) == 0)
- return 1;
- return 0;
- }
- void
- unlock(Lock *l)
- {
- l->pc = 0;
- l->sbsem = 0;
- }
- void
- qlock(QLock *q)
- {
- User *p;
- int i;
- lock(q);
- if(!q->locked){
- q->locked = 1;
- unlock(q);
- goto out;
- }
- if(1 && u) {
- for(i=0; i<NHAS; i++)
- if(u->has.q[i] == q) {
- print("circular qlock by %d at 0x%lux (other 0x%lux, 0x%lux)\n",
- u->pid, getcallerpc(&q), u->has.pc[i], q->pc);
- dumpstack(u);
- break;
- }
- }
- p = q->tail;
- if(p == 0)
- q->head = u;
- else
- p->qnext = u;
- q->tail = u;
- u->qnext = 0;
- u->state = Queueing;
- u->has.want = q;
- unlock(q);
- sched();
- u->has.want = 0;
- out:
- if(1 && u) {
- for(i=0; i<NHAS; i++)
- if(u->has.q[i] == 0) {
- u->has.q[i] = q;
- u->has.pc[i] = getcallerpc(&q);
- return;
- }
- print("NHAS(%d) too small\n", NHAS);
- }
- }
- int
- canqlock(QLock *q)
- {
- int i;
- lock(q);
- if(q->locked){
- unlock(q);
- return 0;
- }
- q->locked = 1;
- unlock(q);
- if(1 && u) {
- for(i=0; i<NHAS; i++)
- if(u->has.q[i] == 0) {
- u->has.q[i] = q;
- u->has.pc[i] = getcallerpc(&q);
- return 1;
- }
- print("NHAS(%d) too small\n", NHAS);
- }
- return 1;
- }
- void
- qunlock(QLock *q)
- {
- User *p;
- int i;
- lock(q);
- p = q->head;
- if(p) {
- q->head = p->qnext;
- if(q->head == 0)
- q->tail = 0;
- unlock(q);
- ready(p);
- } else {
- q->locked = 0;
- unlock(q);
- }
- if(1 && u) {
- for(i=0; i<NHAS; i++)
- if(u->has.q[i] == q) {
- u->has.q[i] = 0;
- return;
- }
- panic("qunlock: not there %lux, called from %lux\n",
- (ulong)q, getcallerpc(&q));
- }
- }
- /*
- * readers/writers lock
- * allows 1 writer or many readers
- */
- void
- rlock(RWlock *l)
- {
- QLock *q;
- qlock(&l->wr); /* wait here for writers and exclusion */
- q = &l->rd; /* first reader in, qlock(&l->rd) */
- lock(q);
- q->locked = 1;
- l->nread++;
- unlock(q);
- qunlock(&l->wr);
- if(1 && u) {
- int i;
- int found;
- found = 0;
- for(i=0; i<NHAS; i++){
- if(u->has.q[i] == q){
- print("circular rlock by %d at 0x%lux (other 0x%lux)\n",
- u->pid, getcallerpc(&l), u->has.pc[i]);
- dumpstack(u);
- }
- if(!found && u->has.q[i] == 0) {
- u->has.q[i] = q;
- u->has.pc[i] = getcallerpc(&l);
- found = 1;
- }
- }
- if(!found)
- print("NHAS(%d) too small\n", NHAS);
- }
- }
- void
- runlock(RWlock *l)
- {
- QLock *q;
- User *p;
- int n;
- q = &l->rd;
- lock(q);
- n = l->nread - 1;
- l->nread = n;
- if(n == 0) { /* last reader out, qunlock(&l->rd) */
- p = q->head;
- if(p) {
- q->head = p->qnext;
- if(q->head == 0)
- q->tail = 0;
- unlock(q);
- ready(p);
- goto accounting;
- }
- q->locked = 0;
- }
- unlock(q);
- accounting:
- if(1 && u) {
- int i;
- for(i=0; i<NHAS; i++)
- if(u->has.q[i] == q) {
- u->has.q[i] = 0;
- return;
- }
- panic("runlock: not there %lux, called from %lux\n",
- (ulong)q, getcallerpc(&l));
- }
- }
- void
- wlock(RWlock *l)
- {
- qlock(&l->wr); /* wait here for writers and exclusion */
- qlock(&l->rd); /* wait here for last reader */
- }
- void
- wunlock(RWlock *l)
- {
- qunlock(&l->rd);
- qunlock(&l->wr);
- }
|