369 lines · 5.4 KB · C
RawDownload
 #include	"u.h"#include	"lib.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"mem.h" void	_xinc(long*);long	_xdec(long*); #define deccnt(x)	if(x)  _xdec(&x->nlock)#define inccnt(x) if(x)  _xinc(&x->nlock) voidprintlocks(User *up){	int i; 	for(i = 0; i < up->nlock; i++){		print("%p:%p", up->lstack[i], up->pstack[i]);		if((i%4) == 0)			print("\n");	}	if(i>0 && i%4) 		print("\n");} voidlock(Lock *l){	int /*i,*/ nl;	ulong pc; 	pc = getcallerpc(&l);	nl = 0;	if(u)		nl = u->nlock;loop:	inccnt(u);		/* prevent being scheded */	if(tas(l) == 0) {		l->pc = pc;		if(u){			u->lstack[nl] = l;			u->pstack[nl] = pc;		}		return;	}	deccnt(u); #ifdef multiprocessor	for(i = 0; i < 1000000; i++){		if(l->sbsem)			continue; 		inccnt(u);   		if(tas(l) == 0) {			l->pc = pc;			if(u){				u->lstack[nl] = l;				u->pstack[nl] = pc;			}			return;		}		deccnt(u);	}#endif	l->sbsem = 0;	// BOTCH 	print("lock loop %d:%#p called by %#p held by pc %#p\n", u?u->pid:-1, l, pc, l->pc);	if(u)		dumpstack(u);	dotrace(0);	if(getstatus() & IFLAG)		sched();	else		print("ilock deadlock\n");	goto loop;} voidunlock(Lock *l){	if(l->sbsem == 0)		print("unlock: not locked: pc %#p\n", getcallerpc(&l));	l->pc = 0;	l->sbsem = 0;	coherence(); 	if(u && _xdec(&u->nlock) == 0)	if(u->delaysched)	if(getstatus() & IFLAG){		/*		 * Call sched if the need arose while locks were held		 * But, don't do it from interrupt routines, hence the islo() test		 */		u->delaysched = 0;		sched();	}} intcanlock(Lock *l){	inccnt(u);	if(tas(l)){		deccnt(u);		return 0;	}	l->pc = getcallerpc(&l);	return 1;} voidilock(Lock *l){	ulong x, pc; 	pc = getcallerpc(&l); 	x = splhi();	if(tas(l) == 0)		goto acquire; 	if(!l->isilock)		panic("ilock: not ilock %p", pc);	if(l->m == MACHP(m->machno))		panic("ilock: deadlock cpu%d pc %p lpc %p\n", m->machno, pc, l->pc);	for(;;){		splx(x);#ifdef multiprocessor		while(l->sbsem)			;#else		if(getstatus() & IFLAG)			sched();		else			panic("ilock: locked & splhi\n");#endif		x = splhi();		if(tas(l) == 0)			goto acquire;	}acquire://	m->ilockdepth++;//	if(u)//		u->lastilock = l;	l->sr = x;	l->pc = pc;	l->p = u;	l->isilock = 1;	l->m = MACHP(m->machno);} voidiunlock(Lock *l){	ulong sr; 	if(l->sbsem == 0)		panic("iunlock nolock: pc %p", getcallerpc(&l));	if(l->isilock == 0)		print("iunlock lock: pc %p held by %p\n", getcallerpc(&l), l->pc);	if((getstatus()&IFLAG) != 0)		print("iunlock lo: %p held by %p\n", getcallerpc(&l), l->pc); 	sr = l->sr;	l->m = 0;	l->sbsem = 0;//	m->ilockdepth--;		coherence(); //	if(u)//		u->lastilock = 0;	splx(sr);} voidqlock(QLock *q){	User *p;	int i; 	lock(q);	if(!q->locked){		q->locked = 1;		unlock(q);		goto out;	}	if(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(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);	}} intcanqlock(QLock *q){	int i; 	lock(q);	if(q->locked){		unlock(q);		return 0;	}	q->locked = 1;	unlock(q); 	if(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;} voidqunlock(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(u){		for(i=0; i<NHAS; i++)			if(u->has.q[i] == q) {				u->has.q[i] = 0;				return;			}		panic("qunlock: not there %p, called from %p\n",			q, getcallerpc(&q));	}} /* * readers/writers lock * allows 1 writer or many readers */voidrlock(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(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);	}} voidrunlock(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(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 %p, called from %p\n",			(ulong)q, getcallerpc(&l));	}} voidwlock(RWlock *l){	qlock(&l->wr);			/* wait here for writers and exclusion */	qlock(&l->rd);			/* wait here for last reader */} voidwunlock(RWlock *l){	qunlock(&l->rd);	qunlock(&l->wr);}