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

📄 9fid.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "stdinc.h"#include "9.h"static struct {	VtLock*	lock;	Fid*	free;	int	nfree;	int	inuse;} fbox;static voidfidLock(Fid* fid, int flags){	if(flags & FidFWlock){		vtLock(fid->lock);		fid->flags = flags;	}	else		vtRLock(fid->lock);	/*	 * Callers of file* routines are expected to lock fsys->fs->elk	 * before making any calls in order to make sure the epoch doesn't	 * change underfoot. With the exception of Tversion and Tattach,	 * that implies all 9P functions need to lock on entry and unlock	 * on exit. Fortunately, the general case is the 9P functions do	 * fidGet on entry and fidPut on exit, so this is a convenient place	 * to do the locking.	 * No fsys->fs->elk lock is required if the fid is being created	 * (Tauth, Tattach and Twalk). FidFCreate is always accompanied by	 * FidFWlock so the setting and testing of FidFCreate here and in	 * fidUnlock below is always done under fid->lock.	 * A side effect is that fidFree is called with the fid locked, and	 * must call fidUnlock only after it has disposed of any File	 * resources still held.	 */	if(!(flags & FidFCreate))		fsysFsRlock(fid->fsys);}static voidfidUnlock(Fid* fid){	if(!(fid->flags & FidFCreate))		fsysFsRUnlock(fid->fsys);	if(fid->flags & FidFWlock){		fid->flags = 0;		vtUnlock(fid->lock);		return;	}	vtRUnlock(fid->lock);}static Fid*fidAlloc(void){	Fid *fid;	vtLock(fbox.lock);	if(fbox.nfree > 0){		fid = fbox.free;		fbox.free = fid->hash;		fbox.nfree--;	}	else{		fid = vtMemAllocZ(sizeof(Fid));		fid->lock = vtLockAlloc();		fid->alock = vtLockAlloc();	}	fbox.inuse++;	vtUnlock(fbox.lock);	fid->con = nil;	fid->fidno = NOFID;	fid->ref = 0;	fid->flags = 0;	fid->open = FidOCreate;	assert(fid->fsys == nil);	assert(fid->file == nil);	fid->qid = (Qid){0, 0, 0};	assert(fid->uid == nil);	assert(fid->uname == nil);	assert(fid->db == nil);	assert(fid->excl == nil);	assert(fid->rpc == nil);	assert(fid->cuname == nil);	fid->hash = fid->next = fid->prev = nil;	return fid;}static voidfidFree(Fid* fid){	if(fid->file != nil){		fileDecRef(fid->file);		fid->file = nil;	}	if(fid->db != nil){		dirBufFree(fid->db);		fid->db = nil;	}	fidUnlock(fid);	if(fid->uid != nil){		vtMemFree(fid->uid);		fid->uid = nil;	}	if(fid->uname != nil){		vtMemFree(fid->uname);		fid->uname = nil;	}	if(fid->excl != nil)		exclFree(fid);	if(fid->rpc != nil){		close(fid->rpc->afd);		auth_freerpc(fid->rpc);		fid->rpc = nil;	}	if(fid->fsys != nil){		fsysPut(fid->fsys);		fid->fsys = nil;	}	if(fid->cuname != nil){		vtMemFree(fid->cuname);		fid->cuname = nil;	}	vtLock(fbox.lock);	fbox.inuse--;	if(fbox.nfree < 10){		fid->hash = fbox.free;		fbox.free = fid;		fbox.nfree++;	}	else{		vtLockFree(fid->alock);		vtLockFree(fid->lock);		vtMemFree(fid);	}	vtUnlock(fbox.lock);}static voidfidUnHash(Fid* fid){	Fid *fp, **hash;	assert(fid->ref == 0);	hash = &fid->con->fidhash[fid->fidno % NFidHash];	for(fp = *hash; fp != nil; fp = fp->hash){		if(fp == fid){			*hash = fp->hash;			break;		}		hash = &fp->hash;	}	assert(fp == fid);	if(fid->prev != nil)		fid->prev->next = fid->next;	else		fid->con->fhead = fid->next;	if(fid->next != nil)		fid->next->prev = fid->prev;	else		fid->con->ftail = fid->prev;	fid->prev = fid->next = nil;	fid->con->nfid--;}Fid*fidGet(Con* con, u32int fidno, int flags){	Fid *fid, **hash;	if(fidno == NOFID)		return nil;	hash = &con->fidhash[fidno % NFidHash];	vtLock(con->fidlock);	for(fid = *hash; fid != nil; fid = fid->hash){		if(fid->fidno != fidno)			continue;		/*		 * Already in use is an error		 * when called from attach, clone or walk.		 */		if(flags & FidFCreate){			vtUnlock(con->fidlock);			vtSetError("fid in use");			return nil;		}		fid->ref++;		vtUnlock(con->fidlock);		fidLock(fid, flags);		if((fid->open & FidOCreate) || fid->fidno == NOFID){			fidPut(fid);			vtSetError("fid invalid");			return nil;		}		return fid;	}	if((flags & FidFCreate) && (fid = fidAlloc()) != nil){		assert(flags & FidFWlock);		fid->con = con;		fid->fidno = fidno;		fid->ref = 1;		fid->hash = *hash;		*hash = fid;		if(con->ftail != nil){			fid->prev = con->ftail;			con->ftail->next = fid;		}		else{			con->fhead = fid;			fid->prev = nil;		}		con->ftail = fid;		fid->next = nil;		con->nfid++;		vtUnlock(con->fidlock);		/*		 * The FidOCreate flag is used to prevent any		 * accidental access to the Fid between unlocking the		 * hash and acquiring the Fid lock for return.		 */		fidLock(fid, flags);		fid->open &= ~FidOCreate;		return fid;	}	vtUnlock(con->fidlock);	vtSetError("fid not found");	return nil;}voidfidPut(Fid* fid){	vtLock(fid->con->fidlock);	assert(fid->ref > 0);	fid->ref--;	vtUnlock(fid->con->fidlock);	if(fid->ref == 0 && fid->fidno == NOFID){		fidFree(fid);		return;	}	fidUnlock(fid);}voidfidClunk(Fid* fid){	assert(fid->flags & FidFWlock);	vtLock(fid->con->fidlock);	assert(fid->ref > 0);	fid->ref--;	fidUnHash(fid);	fid->fidno = NOFID;	vtUnlock(fid->con->fidlock);	if(fid->ref > 0){		fidUnlock(fid);		return;	}	fidFree(fid);}voidfidClunkAll(Con* con){	Fid *fid;	u32int fidno;	vtLock(con->fidlock);	while(con->fhead != nil){		fidno = con->fhead->fidno;		vtUnlock(con->fidlock);		if((fid = fidGet(con, fidno, FidFWlock)) != nil)			fidClunk(fid);		vtLock(con->fidlock);	}	vtUnlock(con->fidlock);}voidfidInit(void){	fbox.lock = vtLockAlloc();}

⌨️ 快捷键说明

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