⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qlock.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#define _LOCK_EXTENSION#define _QLOCK_EXTENSION#define _RESEARCH_SOURCE#include <u.h>#include <lock.h>#include <qlock.h>#include <stdlib.h>#include "sys9.h"#define rendezvous _RENDEZVOUS#define _rendezvousp rendezvous#define _tas tas#define nelem(x) (sizeof(x)/sizeof((x)[0]))static struct {	QLp	*p;	QLp	x[1024];} ql = {	ql.x};enum{	Queuing,	QueuingR,	QueuingW,	Sleeping,};/* find a free shared memory location to queue ourselves in */static QLp*getqlp(void){	QLp *p, *op;	op = ql.p;	for(p = op+1; ; p++){		if(p == &ql.x[nelem(ql.x)])			p = ql.x;		if(p == op)			abort();		if(_tas(&(p->inuse)) == 0){			ql.p = p;			p->next = nil;			break;		}	}	return p;}voidqlock(QLock *q){	QLp *p, *mp;	lock(&q->lock);	if(!q->locked){		q->locked = 1;		unlock(&q->lock);		return;	}	/* chain into waiting list */	mp = getqlp();	p = q->tail;	if(p == nil)		q->head = mp;	else		p->next = mp;	q->tail = mp;	mp->state = Queuing;	unlock(&q->lock);	/* wait */	while((*_rendezvousp)((ulong)mp, 1) == ~0)		;	mp->inuse = 0;}voidqunlock(QLock *q){	QLp *p;	lock(&q->lock);	p = q->head;	if(p != nil){		/* wakeup head waiting process */		q->head = p->next;		if(q->head == nil)			q->tail = nil;		unlock(&q->lock);		while((*_rendezvousp)((ulong)p, 0x12345) == ~0)			;		return;	}	q->locked = 0;	unlock(&q->lock);}intcanqlock(QLock *q){	if(!canlock(&q->lock))		return 0;	if(!q->locked){		q->locked = 1;		unlock(&q->lock);		return 1;	}	unlock(&q->lock);	return 0;}#if 0voidrlock(RWLock *q){	QLp *p, *mp;	lock(&q->lock);	if(q->writer == 0 && q->head == nil){		/* no writer, go for it */		q->readers++;		unlock(&q->lock);		return;	}	mp = getqlp();	p = q->tail;	if(p == 0)		q->head = mp;	else		p->next = mp;	q->tail = mp;	mp->next = nil;	mp->state = QueuingR;	unlock(&q->lock);	/* wait in kernel */	while((*_rendezvousp)((ulong)mp, 1) == ~0)		;	mp->inuse = 0;}intcanrlock(RWLock *q){	lock(&q->lock);	if (q->writer == 0 && q->head == nil) {		/* no writer; go for it */		q->readers++;		unlock(&q->lock);		return 1;	}	unlock(&q->lock);	return 0;}voidrunlock(RWLock *q){	QLp *p;	lock(&q->lock);	if(q->readers <= 0)		abort();	p = q->head;	if(--(q->readers) > 0 || p == nil){		unlock(&q->lock);		return;	}	/* start waiting writer */	if(p->state != QueuingW)		abort();	q->head = p->next;	if(q->head == 0)		q->tail = 0;	q->writer = 1;	unlock(&q->lock);	/* wakeup waiter */	while((*_rendezvousp)((ulong)p, 0) == ~0)		;}voidwlock(RWLock *q){	QLp *p, *mp;	lock(&q->lock);	if(q->readers == 0 && q->writer == 0){		/* noone waiting, go for it */		q->writer = 1;		unlock(&q->lock);		return;	}	/* wait */	p = q->tail;	mp = getqlp();	if(p == nil)		q->head = mp;	else		p->next = mp;	q->tail = mp;	mp->next = nil;	mp->state = QueuingW;	unlock(&q->lock);	/* wait in kernel */	while((*_rendezvousp)((ulong)mp, 1) == ~0)		;	mp->inuse = 0;}intcanwlock(RWLock *q){	lock(&q->lock);	if (q->readers == 0 && q->writer == 0) {		/* no one waiting; go for it */		q->writer = 1;		unlock(&q->lock);		return 1;	}	unlock(&q->lock);	return 0;}voidwunlock(RWLock *q){	QLp *p;	lock(&q->lock);	if(q->writer == 0)		abort();	p = q->head;	if(p == nil){		q->writer = 0;		unlock(&q->lock);		return;	}	if(p->state == QueuingW){		/* start waiting writer */		q->head = p->next;		if(q->head == nil)			q->tail = nil;		unlock(&q->lock);		while((*_rendezvousp)((ulong)p, 0) == ~0)			;		return;	}	if(p->state != QueuingR)		abort();	/* wake waiting readers */	while(q->head != nil && q->head->state == QueuingR){		p = q->head;		q->head = p->next;		q->readers++;		while((*_rendezvousp)((ulong)p, 0) == ~0)			;	}	if(q->head == nil)		q->tail = nil;	q->writer = 0;	unlock(&q->lock);}voidrsleep(Rendez *r){	QLp *t, *me;	if(!r->l)		abort();	lock(&r->l->lock);	/* we should hold the qlock */	if(!r->l->locked)		abort();	/* add ourselves to the wait list */	me = getqlp();	me->state = Sleeping;	if(r->head == nil)		r->head = me;	else		r->tail->next = me;	me->next = nil;	r->tail = me;	/* pass the qlock to the next guy */	t = r->l->head;	if(t){		r->l->head = t->next;		if(r->l->head == nil)			r->l->tail = nil;		unlock(&r->l->lock);		while((*_rendezvousp)((ulong)t, 0x12345) == ~0)			;	}else{		r->l->locked = 0;		unlock(&r->l->lock);	}	/* wait for a wakeup */	while((*_rendezvousp)((ulong)me, 1) == ~0)		;	me->inuse = 0;}intrwakeup(Rendez *r){	QLp *t;	/*	 * take off wait and put on front of queue	 * put on front so guys that have been waiting will not get starved	 */		if(!r->l)		abort();	lock(&r->l->lock);	if(!r->l->locked)		abort();	t = r->head;	if(t == nil){		unlock(&r->l->lock);		return 0;	}	r->head = t->next;	if(r->head == nil)		r->tail = nil;	t->next = r->l->head;	r->l->head = t;	if(r->l->tail == nil)		r->l->tail = t;	t->state = Queuing;	unlock(&r->l->lock);	return 1;}intrwakeupall(Rendez *r){	int i;	for(i=0; rwakeup(r); i++)		;	return i;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -