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

📄 buf.cc

📁 南京航空航天大学开发的一个类Unix和Linux的操作系统,好不好看看就知道了,
💻 CC
字号:
#include <lib/config.h>#include <lib/root.h>#include <lib/errno.h>#include <lib/gcc.h>#include <lib/ostream.h>#include <init/ctor.h>#include <dev/blk/dev.h>#include "buf.h"#include "inode.h" /* for BNOTALLOC */static ulong nfind;static ulong nfindsucc;static int nbuf;static Q(all,buf_t) allq;static Q(free,buf_t) freeq;static int hsize;static int hmask;typedef Q(hash,buf_t) hashq_t;static hashq_t * hashtab;static bno_t nullbno;static inline hashq_t * hashfunc(dev_t dev, bno_t bno){	return hashtab + ((dev + bno) & hmask);}void dumpb(){//	printf("total buffer number:%d\n", nbuf);	printf("free buffer number:%d\n", freeq.count());//	printf("bcache hit rate:lookup=%ld, succeed=%ld\n", nfind, nfindsucc);}void dumpb(ostream_t * os){	os->write("total buffer number:%d\n", nbuf);	os->write("free buffer number:%d\n", freeq.count());	os->write("bcache hit rate:lookup=%ld, succeed=%ld\n", nfind, nfindsucc);}__ctor(PRIFS, SUBANY, buffercache){	construct(&allq);	construct(&freeq);	hsize = nbuf = roundup2p2(128 * nphysmeg);	hmask = hsize - 1;	hashtab = (hashq_t*) allocbm(hsize * sizeof(hashq_t));	construct(hashtab, hsize);	buf_t * b = (buf_t*) allocbm(nbuf * sizeof(buf_t));	char * data = (char *) allocbm(nbuf * MINIXBSIZE, MINIXBSIZE);	for (int i = 0; i < nbuf; i++, b++, data += MINIXBSIZE) {		b->nextall = b->prevall = NULL;		b->nexthash = b->prevhash = NULL;		b->nextfree = b->prevfree = NULL;		b->nextreq = b->prevreq = NULL;		b->state = BINVAL;		b->refcnt = 0;		b->dev = mkdev(NULLMAJOR,0);		b->bno = nullbno++;		b->bsize = MINIXBSIZE;		b->data = data;		construct(&b->iolock);		hashfunc(b->dev, b->bno)->enqtail(b);		freeq.enqtail(b);		allq.enqtail(b);	}}static buf_t * findb(dev_t dev, bno_t bno, int bsize = MINIXBSIZE){	buf_t * b;	hashq_t * hashq = hashfunc(dev, bno); 	nfind++;	foreach (b, *hashq) {		if ((b->dev == dev) && (b->bno == bno)) {			assert(b->bsize == bsize);			nfindsucc++;			return b;		}	}	return NULL;}static inline int ideal(buf_t * b){	return !(b->locked()) && (b->state == BDIRTY);}/* write async buf cluster */static void writeb(buf_t * core){#if !RWAHEAD	llwriteab(&core, 1);#else	if (major(core->dev) == NULLMAJOR)		return;	buf_t * cluster[MAXBUFPERIO];	dev_t dev = core->dev;	bno_t bno = core->bno;	buf_t ** p = cluster + MAXBUFPERIO/2;	buf_t ** end = cluster + MAXBUFPERIO;	int total = 0;	buf_t * b = core;		/* find neighbour on right */	do {		(*p = b)->hold();		total++, p++, bno++;	} while ((p < end) && (b = findb(dev, bno)) && ideal(b));	/* find neighbour on left */	p = cluster + MAXBUFPERIO/2 - 1;	end = cluster - 1;	bno = core->bno - 1;	while ((p > end) && (b = findb(dev, bno)) && ideal(b)) {		(*p = b)->hold();		total++, p--, bno--;	}	p++;	/* write them all */	llwriteb(p, total);	while (total--)		(*p++)->lose();#endif}/* getblk always succeed, it will return a non-null and unlocked b; */buf_t * getb(dev_t dev, bno_t bno){	buf_t * b;	int candidates = 8;	assert(bno != BNOTALLOC);repeat: if (b = findb(dev, bno, MINIXBSIZE)) {		b->hold();		b->wait();		if (b->nextfree) /* b may not in the freeq */			freeq.unlink(b);		return b;	}	foreach(b, freeq) { /* search from lru to mru */		if (b->refcnt)			continue;		if (candidates > 0)			candidates--; 		if (b->locked()) {			if (candidates)				continue;/* NOTE!! While we slept waiting for this block, somebody else might   already have added "this" block to the cache. check it */			b->wait();			goto repeat;		}		if (b->state == BDIRTY) {			b->hold();			writeb(b);			if (!candidates)				b->wait();			b->lose();			goto repeat;		}		/* !b->refcnt && !b->locked() && b->state != BDIRTY */		b->hold();		freeq.unlink(b); /* b must in the freeq */		b->unlinkhash(); /* remove from old hashq */		hashfunc(dev, bno)->enqtail(b); /* join the new hashq */		b->state = BINVAL;		b->dev = dev;		b->bno = bno;		return b;	}	panic("no free block buffer in bcache\n");	return NULL;}/* brelse */void buf_t::lose(){	assert(refcnt > 0);	assert(findb(dev, bno, bsize));	if (--refcnt)		return;	if (!nextfree)		freeq.enqtail(this); /* put at mru */}int readb(dev_t dev, bno_t bno, buf_t ** b){	if (!validdev(dev)) {		warn("read on invalid block device %x\n", dev);		(*b) = NULL;		return EINVAL;	}	*b = getb(dev, bno);	if ((*b)->state != BINVAL)		return 0;	llreadb(b, 1);	if ((*b)->state == BINVAL) { /* may be IO error */		(*b)->lose();		(*b) = NULL;		return EIO;	}	return 0;}void readab(dev_t dev, bno_t start, int nr){#if !RWAHEAD	buf_t * b[nr];	assert(nr < 64);	for (int i = 0; i < nr; i++)		b[i] = getb(dev, start + i);	llreadab(b, nr);	for (int i = 0; i < nr; i++)		b[i]->lose();#endif}extern void prempt();void syncb(dev_t dev){	buf_t * b;		foreach (b, allq) {		if ((dev != 0xffff) && (dev != b->dev))			continue;		b->hold();		writeb(b);		b->lose();		prempt();	}}void syncb(){	syncb(0xffff);}extern void synci();asmlinkage int syssync(){	for (int i = 0; i < 2; i++) {		synci();		syncb();	}	return 0;}void llrwab(int rw, buf_t * b[], int nr){	if (!nr)		return;	if (major(b[0]->dev) == NULLMAJOR)		return;	blkdev_t * dev = getblkdev(b[0]->dev);	if (!dev) {		warn("invlaid block device:%x\n", b[0]->dev);		return;	}	int count = 0;	for (int i = 0; i < nr; i++) {		assert(b[i]->dev == b[0]->dev);		assert(b[i]->bsize = b[0]->bsize);		assert(b[i]->refcnt > 0);		b[i]->lock();		if (rw == BREAD) {			if (b[i]->state != BINVAL) {				b[i]->unlock();				continue;			}		} else {			if (b[i]->state != BDIRTY) {				b[i]->unlock();				continue;			}		}		count++;		dev->addreq(rw, b[i]);	}	if (count)		dev->doreq();}

⌨️ 快捷键说明

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