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

📄 cache.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"enum{	NHASH		= 128,	MAXCACHE	= 1024*1024,	NFILE		= 4096,	NEXTENT		= 200,		/* extent allocation size */};typedef struct Extent Extent;struct Extent{	int	bid;	ulong	start;	int	len;	Page	*cache;	Extent	*next;};typedef struct Mntcache Mntcache;struct Mntcache{	Qid;	int	dev;	int	type;	QLock;	Extent	 *list;	Mntcache *hash;	Mntcache *prev;	Mntcache *next;};typedef struct Cache Cache;struct Cache{	Lock;	int		pgno;	Mntcache	*head;	Mntcache	*tail;	Mntcache	*hash[NHASH];};typedef struct Ecache Ecache;struct Ecache{	Lock;	int	total;	int	free;	Extent*	head;};static Image fscache;static Cache cache;static Ecache ecache;static int maxcache = MAXCACHE;static voidextentfree(Extent* e){	lock(&ecache);	e->next = ecache.head;	ecache.head = e;	ecache.free++;	unlock(&ecache);}static Extent*extentalloc(void){	Extent *e;	int i;	lock(&ecache);	if(ecache.head == nil){		e = xalloc(NEXTENT*sizeof(Extent));		if(e == nil){			unlock(&ecache);			return nil;		}		for(i = 0; i < NEXTENT; i++){			e->next = ecache.head;			ecache.head = e;			e++;		}		ecache.free += NEXTENT;		ecache.total += NEXTENT;	}	e = ecache.head;	ecache.head = e->next;	memset(e, 0, sizeof(Extent));	ecache.free--;	unlock(&ecache);	return e;}voidcinit(void){	int i;	Mntcache *m;	cache.head = xalloc(sizeof(Mntcache)*NFILE);	m = cache.head;	if(conf.npage*BY2PG > 200*MB)		maxcache = 10*MAXCACHE;	for(i = 0; i < NFILE-1; i++) {		m->next = m+1;		m->prev = m-1;		m++;	}	cache.tail = m;	cache.tail->next = 0;	cache.head->prev = 0;	fscache.notext = 1;}voidcprint(Chan *c, Mntcache *m, char *s){	ulong o;	int nb, ct;	Extent *e;	nb = 0;	ct = 1;	o = 0;	if(m->list)		o = m->list->start;	for(e = m->list; e; e = e->next) {		nb += e->len;		if(o != e->start)			ct = 0;		o = e->start+e->len;	}	pprint("%s: 0x%lux.0x%lux %d %d %s (%d %c)\n",	s, m->path, m->vers, m->type, m->dev, c->name, nb, ct ? 'C' : 'N');	for(e = m->list; e; e = e->next) {		pprint("\t%4d %5d %4d %lux\n",			e->bid, e->start, e->len, e->cache);	}}Page*cpage(Extent *e){	/* Easy consistency check */	if(e->cache->daddr != e->bid)		return 0;	return lookpage(&fscache, e->bid);}voidcnodata(Mntcache *m){	Extent *e, *n;	/*	 * Invalidate all extent data	 * Image lru will waste the pages	 */	for(e = m->list; e; e = n) {		n = e->next;		extentfree(e);	}	m->list = 0;}voidctail(Mntcache *m){	/* Unlink and send to the tail */	if(m->prev)		m->prev->next = m->next;	else		cache.head = m->next;	if(m->next)		m->next->prev = m->prev;	else		cache.tail = m->prev;	if(cache.tail) {		m->prev = cache.tail;		cache.tail->next = m;		m->next = 0;		cache.tail = m;	}	else {		cache.head = m;		cache.tail = m;		m->prev = 0;		m->next = 0;	}}voidcopen(Chan *c){	int h;	Extent *e, *next;	Mntcache *m, *f, **l;	if(c->qid.path&CHDIR)		return;	h = c->qid.path%NHASH;	lock(&cache);	for(m = cache.hash[h]; m; m = m->hash) {		if(m->path == c->qid.path)		if(m->dev == c->dev && m->type == c->type) {			c->mcp = m;			ctail(m);			unlock(&cache);			/* File was updated, invalidate cache */			if(m->vers != c->qid.vers) {				m->vers = c->qid.vers;				qlock(m);				cnodata(m);				qunlock(m);			}			return;		}	}	/* LRU the cache headers */	m = cache.head;	l = &cache.hash[m->path%NHASH];	for(f = *l; f; f = f->hash) {		if(f == m) {			*l = m->hash;			break;		}		l = &f->hash;	}	m->Qid = c->qid;	m->dev = c->dev;	m->type = c->type;	l = &cache.hash[h];	m->hash = *l;	*l = m;	ctail(m);	qlock(m);	c->mcp = m;	e = m->list;	m->list = 0;	unlock(&cache);	while(e) {		next = e->next;		extentfree(e);		e = next;	}	qunlock(m);}static intcdev(Mntcache *m, Chan *c){	if(m->path != c->qid.path)		return 0;	if(m->dev != c->dev)		return 0;	if(m->type != c->type)		return 0;	if(m->vers != c->qid.vers)		return 0;	return 1;}intcread(Chan *c, uchar *buf, int len, vlong off){	KMap *k;	Page *p;	Mntcache *m;	Extent *e, **t;	int o, l, total;	ulong offset;	if(off+len > maxcache)		return 0;	m = c->mcp;	if(m == 0)		return 0;	qlock(m);	if(cdev(m, c) == 0) {		qunlock(m);		return 0;	}	offset = off;	t = &m->list;	for(e = *t; e; e = e->next) {		if(offset >= e->start && offset < e->start+e->len)			break;		t = &e->next;	}	if(e == 0) {		qunlock(m);		return 0;	}	total = 0;	while(len) {		p = cpage(e);		if(p == 0) {			*t = e->next;			extentfree(e);			qunlock(m);			return total;		}		o = offset - e->start;		l = len;		if(l > e->len-o)			l = e->len-o;		k = kmap(p);		if(waserror()) {			kunmap(k);			putpage(p);			qunlock(m);			nexterror();		}		memmove(buf, (uchar*)VA(k) + o, l);		poperror();		kunmap(k);		putpage(p);		buf += l;		len -= l;		offset += l;		total += l;		t = &e->next;		e = e->next;		if(e == 0 || e->start != offset)			break;	}	qunlock(m);	return total;}Extent*cchain(uchar *buf, ulong offset, int len, Extent **tail){	int l;	Page *p;	KMap *k;	Extent *e, *start, **t;	start = 0;	*tail = 0;	t = &start;	while(len) {		e = extentalloc();		if(e == 0)			break;		p = auxpage();		if(p == 0) {			extentfree(e);			break;		}		l = len;		if(l > BY2PG)			l = BY2PG;		e->cache = p;		e->start = offset;		e->len = l;		lock(&cache);		e->bid = cache.pgno;		cache.pgno += BY2PG;		/* wrap the counter; low bits are unused by pghash but checked by lookpage */		if((cache.pgno & ~(BY2PG-1)) == 0){			if(cache.pgno == BY2PG-1){				print("cache wrapped\n");				cache.pgno = 0;			}else				cache.pgno++;		}		unlock(&cache);		p->daddr = e->bid;		k = kmap(p);		if(waserror()) {		/* buf may be virtual */			kunmap(k);			nexterror();		}		memmove((void*)VA(k), buf, l);		poperror();		kunmap(k);		cachepage(p, &fscache);		putpage(p);		buf += l;		offset += l;		len -= l;		*t = e;		*tail = e;		t = &e->next;	}	return start;}intcpgmove(Extent *e, uchar *buf, int boff, int len){	Page *p;	KMap *k;	p = cpage(e);	if(p == 0)		return 0;	k = kmap(p);	if(waserror()) {		/* Since buf may be virtual */		kunmap(k);		nexterror();	}	memmove((uchar*)VA(k)+boff, buf, len);	poperror();	kunmap(k);	putpage(p);	return 1;}voidcupdate(Chan *c, uchar *buf, int len, vlong off){	Mntcache *m;	Extent *tail;	Extent *e, *f, *p;	int o, ee, eblock;	ulong offset;	if(off > maxcache || len == 0)		return;	m = c->mcp;	if(m == 0)		return;	qlock(m);	if(cdev(m, c) == 0) {		qunlock(m);		return;	}	/*	 * Find the insertion point	 */	offset = off;	p = 0;	for(f = m->list; f; f = f->next) {		if(f->start > offset)			break;		p = f;	}	/* trim if there is a successor */	eblock = offset+len;	if(f != 0 && eblock > f->start) {		len -= (eblock - f->start);		if(len <= 0) {			qunlock(m);			return;		}	}	if(p == 0) {		/* at the head */		e = cchain(buf, offset, len, &tail);		if(e != 0) {			m->list = e;			tail->next = f;		}		qunlock(m);		return;	}	/* trim to the predecessor */	ee = p->start+p->len;	if(offset < ee) {		o = ee - offset;		len -= o;		if(len <= 0) {			qunlock(m);			return;		}		buf += o;		offset += o;	}	/* try and pack data into the predecessor */	if(offset == ee && p->len < BY2PG) {		o = len;		if(o > BY2PG - p->len)			o = BY2PG - p->len;		if(cpgmove(p, buf, p->len, o)) {			p->len += o;			buf += o;			len -= o;			offset += o;			if(len <= 0) {if (f && p->start + p->len > f->start) print("CACHE: p->start=%uld p->len=%d f->start=%uld\n", p->start, p->len, f->start);				qunlock(m);				return;			}		}	}	e = cchain(buf, offset, len, &tail);	if(e != 0) {		p->next = e;		tail->next = f;	}	qunlock(m);}voidcwrite(Chan* c, uchar *buf, int len, vlong off){	int o, eo;	Mntcache *m;	ulong eblock, ee;	Extent *p, *f, *e, *tail;	ulong offset;	if(off > maxcache || len == 0)		return;	m = c->mcp;	if(m == 0)		return;	qlock(m);	if(cdev(m, c) == 0) {		qunlock(m);		return;	}	offset = off;	m->vers++;	c->qid.vers++;	p = 0;	for(f = m->list; f; f = f->next) {		if(f->start >= offset)			break;		p = f;	}	if(p != 0) {		ee = p->start+p->len;		eo = offset - p->start;		/* pack in predecessor if there is space */		if(offset <= ee && eo < BY2PG) {			o = len;			if(o > BY2PG - eo)				o = BY2PG - eo;			if(cpgmove(p, buf, eo, o)) {				if(eo+o > p->len)					p->len = eo+o;				buf += o;				len -= o;				offset += o;			}		}	}	/* free the overlap -- it's a rare case */	eblock = offset+len;	while(f && f->start < eblock) {		e = f->next;		extentfree(f);		f = e;	}	/* link the block (if any) into the middle */	e = cchain(buf, offset, len, &tail);	if(e != 0) {		tail->next = f;		f = e;	}	if(p == 0)		m->list = f;	else		p->next = f;	qunlock(m);}

⌨️ 快捷键说明

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