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

📄 dskalloc.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if ( keep <= TSD_FRF_VAL_2 ) {		/* Unable to allocate when there remains only 2 bytes or less of free area at the end of the block. */		return min(keep, size);	}	bp = fmpMapLogBlk(lblk, ofcb, &mid, fsinfo);	if ( bp == NULL ) {		err = (ER)mid;		goto err_ret1;	}	/* Obtain the free size. */	free = (W)getBorder((UH*)(bp + use), fsinfo);	err = fmpCheckDiskError(ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret2;	}	/* Obtain the size that can be allocated. */	if ( free >= size ) {		keep = size;	} else {		if ( (use + free + TSD_FRF_OF_2) == fsinfo->sblk ) {			/* In the case of the end of the block. */			free += TSD_FRF_SZ_2;			keep = min(free, size);		} else {			keep = 0;		}	}	if ( keep > 0 ) {		DskAdr	oldfrag, newfrag;		/* Location of the fragment */		oldfrag = fmpLBlkToDAdr(lblk, fsinfo);		oldfrag.offset = (VP)((VB*)oldfrag.offset + use + TSD_FRF_OF_2);		newfrag.offset = (VP)((VB*)oldfrag.offset + keep);		newfrag.lblk   = oldfrag.lblk;		use  += keep;		free -= keep;		if ( use <= (fsinfo->sblk - TSD_FRF_VAL_2) ) {			W	freeEnd = use + free + TSD_FRF_SZ_2;			/* Update the separator. */			setBorder((UH*)(bp + use), (UH)free, fsinfo);			if ( freeEnd <= (fsinfo->sblk - TSD_FRF_VAL_2) ) {				setBorder((UH*)(bp + freeEnd), (UH)free, fsinfo);			}			mflag = MD_WRITE;		}		/* Change the fragment size. */		err = fmpChangeFragment(oldfrag, newfrag, free, ofcb);		if ( err < E_OK ) {			goto err_ret2;		}	}	fmpUnmapDisk(mid, mflag);	err = fmpCheckDiskError(ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret1;	}	return keep;err_ret2:	fmpUnmapDisk(mid, mflag);err_ret1:	DEBUG_PRINT(("fmpResizeFragment err = %d\n", err));	return err;}/* * Merge the free areas. *	Define the area from the start th byte to just before the end th byte of the logical block *	lblk as a free space, and merge the space with the free areas before and after it. *	If lblk is already mapped, set madr to the address. *	Otherwise, set madr to NULL. *	Return MD_WRITE when writing is performed to lblk. *	Otherwise, return MD_RDONLY. *	When err < E_OK, it is handled as MD_RDONLY. */EXPORT WER fmpMergeFragment( UW lblk, VP madr, W start, W end, OFCB *ofcb ){	FsInfo	*fsinfo = ofcb->fsinfo;	DskAdr	dadr;	VB	*mp;	DskAdr	frag;	W	freeTop, freeEnd;	W	free;	ID	mid;	UW	mflag = MD_RDONLY;	ER	err;	dadr = fmpLBlkToDAdr(lblk, fsinfo);	if ( madr == NULL ) {		mp = fmpMapLogBlk(lblk, ofcb, &mid, fsinfo);		if ( mp == NULL ) {			err = (ER)mid;			goto err_ret1;		}	} else {		mp = (VB*)madr;	}	/* Obtain the range of the merged free area. */	if ( start < TSD_MEF_VAL_2 ) {		freeTop = 0;	} else {		free = (W)getBorder((UH*)(mp + start - TSD_MEF_VAL_2), fsinfo);		freeTop = start - free - TSD_MEF_VAL_2;	}	if ( end > (fsinfo->sblk - TSD_MEF_VAL_2) ) {		freeEnd = (W)fsinfo->sblk;	} else {		free = (W)getBorder((UH*)(mp + end), fsinfo);		freeEnd = end + free + TSD_MEF_SZ_2;	}	free = freeEnd - freeTop;	err = fmpCheckDiskError(ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret2;	}	if ( free < fsinfo->sblk ) {		/* Change the fragment table. */		if ( (end + TSD_MEF_OF_2) < fsinfo->sblk ) {			/* Deregister the lower fragment. */			frag.lblk   = dadr.lblk;			frag.offset = (VB*)dadr.offset + end + TSD_MEF_OF_2;			err = fmpChangeFragment(frag,					fmpLBlkToDAdr(0, fsinfo), 0, ofcb);			if ( err < E_OK ) {				goto err_ret2;			}		}		/* Change the upper fragment. */		frag.lblk   = dadr.lblk;		frag.offset = (VB*)dadr.offset + freeTop;		err = fmpChangeFragment(frag, frag, free, ofcb);		if ( err < E_OK ) {			goto err_ret2;		}		/* Set the separator code. */		if ( freeTop >= TSD_MEF_VAL_2 ) {			setBorder((UH*)(mp + freeTop - TSD_MEF_VAL_2), (UH)free, fsinfo);			mflag = MD_WRITE;		}		if ( freeEnd <= (fsinfo->sblk - TSD_MEF_VAL_2) ) {			setBorder((UH*)(mp + freeEnd), (UH)free, fsinfo);			mflag = MD_WRITE;		}	} else {		/* Release whole block. */		LLogBlk	fb;		fb.cnt = 1;		fb.adr = lblk;		err = fmpFreeBlock(fb, ofcb);		if ( err < E_OK ) {			goto err_ret2;		}	}	if ( madr == NULL ) {		fmpUnmapDisk(mid, mflag);	}	return (WER)mflag;err_ret2:	if ( madr == NULL ) {		fmpUnmapDisk(mid, mflag);	}err_ret1:	DEBUG_PRINT(("fmpMergeFragment err = %d\n", err));	return err;}/* * Register the free area. *	Register the area from use th byte to just before end th byte of blk *	in the fragment table as a free area. *	When end is not a boundary of the logical block, *	it must be a position of separator code of the fragment. */LOCAL ER fmpAddFragment( UW blk, W use, W end, OFCB *ofcb){	FsInfo	*fsinfo = ofcb->fsinfo;	DskAdr	newfrag, oldfrag;	W	free;	VB	*bp;	ID	mid;	ER	err;	oldfrag = fmpLBlkToDAdr(blk, fsinfo);	oldfrag.offset = (VP)((VB*)oldfrag.offset + use + TSD_MAF_OF_2);	newfrag = oldfrag;	bp = fmpMapLogBlk(blk, ofcb, &mid, fsinfo);	if ( bp == NULL ) {		err = (ER)mid;		goto err_ret;	}	if ( end <= (fsinfo->sblk - TSD_MAF_VAL_2) ) {		/* Merge the free spaces after end. */		oldfrag = fmpLBlkToDAdr(blk, fsinfo);		oldfrag.offset = (VP)((VB*)oldfrag.offset + end + TSD_MAF_OF_2);		end += getBorder((UH*)(bp + end), fsinfo) + TSD_MAF_OF_2;	}	free = end - use - TSD_MAF_VAL_2;	/* Set the separator code. */	if ( use <= (fsinfo->sblk - TSD_MAF_VAL_2) ) {		setBorder((UH*)(bp + use), (UH)free, fsinfo);		if ( end <= (fsinfo->sblk - TSD_MAF_VAL_2) ) {			setBorder((UH*)(bp + end), (UH)free, fsinfo);		}	}	fmpUnmapDisk(mid, MD_WRITE);	err = fmpCheckDiskError(ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret;	}	/* Update the fragment table. */	err = fmpChangeFragment(oldfrag, newfrag, free, ofcb);	if ( err < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("fmpAddFragment err = %d\n", err));	return err;}/* * Deregister the entry of top <= locate < end from the fragment table. */LOCAL ER fmpDeleteFragment( DskAdr top, DskAdr end, OFCB *ofcb ){	FsInfo			*fsinfo = ofcb->fsinfo;	DfFileHeaderBlock	*fh;	Fragment		frag;	W			i, j, nent;	ID			mid;	UW			mflag = MD_RDONLY;	ER			err;	/* Map the fragment table (File header). */	fh = fmpMapDskAdr(ofcb->fhead, (W)ofcb->ridxofs, ofcb, &mid, fsinfo);	if ( fh == NULL ) {		err = (ER)mid;		goto err_ret;	}	/* The number of entries of the fragment table. */	nent = N_FragEnt(ofcb);	/* While deleting target entries, close the following entries. */	j = 0;	for ( i = 0; i < nent; ++i ) {		getFragment(&frag, fh, i, fsinfo);		if ( frag.size == 0 ) {			break;		}		if ( i > j ) {			setFragment(fh, j, &frag, fsinfo);		}		if ( (CmpDskAdr(frag.locate, top) < 0)		  || (CmpDskAdr(frag.locate, end) >= 0) ) {			j++;		}	}	if ( j < nent ) {		mflag = MD_WRITE;	}	frag.locate.offset = 0;	frag.locate.lblk   = 0;	frag.size          = 0;	while ( j < nent ) {		setFragment(fh, j++, &frag, fsinfo);	}	fmpUnmapDisk(mid, mflag);	err = fmpCheckDiskError(ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("fmpDeleteFragment err = %d\n", err));	return err;}/* ======================================================================== *//* *	Use block bit map related *//* * Start to access the block bit map. *	Prepare to access the block bit map that has the size of nbmp bytes *	starting from the position bmadr on the disk. *	Set bm to the information for access. *	The call side must prepare the area for bm and hold the area *	until closeBitMap() is executed. */LOCAL ER openBitMap( BitMapIO *bm, DskAdrS bmadr, W nbmp, FsInfo *fsinfo ){	memset(bm, 0, (size_t)sizeof(BitMapIO));	bm->fsinfo = fsinfo;	bm->bmadr  = bmadr;	bm->nbmp   = nbmp;	bm->idx    = N_BM_MAPINFO - 1;	return E_OK;}/* * Obtain one byte from the block bit map. *	Return the address at offset th byte from the start of the block bit map. *	This address is the memory address of the data on the disk being mapped to the memory. *	Only the one byte width can be accessed validly. The access to the bytes before and *	after it is not permitted. This address is valid until bitMap() is called next time and *	can not be accessed after that. *	When writing to the returned address, it must be that mflag = MD_WRITE. *	Otherwise, mflag = MD_RDONLY.  An error is not returned in this call. *	If an error occurs, the information is held, and the error is returned *	when closeBitMap() is executed. */LOCAL UB* bitMap( BitMapIO *bm, W offset, UW mflag ){	struct bm_mapinfo *mi;	W	n, nb;	DskAdrS	mapadr;	FsInfo	*fsinfo = bm->fsinfo;	ER	err;	/* Find from the ones already mapped. */	for ( mi = bm->mi; mi < &bm->mi[N_BM_MAPINFO]; mi++ ) {		if ( mi->mid == 0 ) {			continue;		}		n = offset - mi->offset;		if ( (n >= 0) && (n < mi->nbyte) ) {			/* Some are already mapped. */			mi->mflag |= mflag;			return mi->mapbase + n;		}	}	/* Nothing is mapped. */	bm->idx = (bm->idx + 1) % N_BM_MAPINFO;	mi = &bm->mi[bm->idx];	if ( mi->mid != 0 ) {		/* Unmap the ones already mapped now. */		fmpUnmapDisk(mi->mid, mi->mflag);		mi->mid = 0;	}	/* Perform a new mapping. */	nb = (W)(fsinfo->sblk - ((UW)bm->bmadr % fsinfo->sblk));	if ( offset < nb ) {		/* First logical block  */		mapadr = bm->bmadr;	} else {		/* Logical blocks after the first one */		nb = (W)fsinfo->sblk;		mapadr = (UB*)bm->bmadr + offset;		mapadr = (DskAdrS)((UB*)mapadr - ((UW)mapadr % fsinfo->sblk));	}	mi->offset = (UB*)mapadr - (UB*)bm->bmadr;	n = bm->nbmp - mi->offset;	if ( nb > n ) {		nb = n;	}	mi->nbyte = nb;	mi->mapbase = fmpMapDskAdrS(mapadr, nb, MAP_SYS(fsinfo), &err, fsinfo);	if ( mi->mapbase == NULL ) {		goto err_ret;	}	mi->mid   = (ID)err;	mi->mflag = mflag;	return mi->mapbase + (offset - mi->offset);err_ret:	bm->error = err;	DEBUG_PRINT(("bitMap err = %d\n", err));	return &bm->dummy;}/* * Finish accessing the block bit map. */LOCAL ER closeBitMap( BitMapIO *bm ){	struct bm_mapinfo *mi;	ER	err;	/* Unmap all. */	for ( mi = bm->mi; mi < &bm->mi[N_BM_MAPINFO]; mi++ ) {		if ( mi->mid == 0 ) {			continue;		}		fmpUnmapDisk(mi->mid, mi->mflag);	}	err = fmpCheckDiskError(NULL, bm->fsinfo);	if ( err < E_OK ) {		bm->error = err;		DEBUG_PRINT(("closeBitMap err = %d\n", err));	}	return bm->error;}/* * Search the width bits from bno th bit of the block bit map bm, * and return the position where bit 0 is first found. If not found, return -1. * It must be that width > 0. */LOCAL W bitSearch0( BitMapIO *bm, W bno, W width ){	W	end = bno + width;	UB	b, m;	if ( bm->fsinfo->bigEndian != 0U ) {		for ( ;; ) {			b = *bitMap(bm, (W)((UW)bno >> TSD_DAM_BSU_3), MD_RDONLY);			m = (UB)(TSD_DAM_BIT_0X80 >> ((UW)bno & TSD_DAM_RSF_7));			do {				if ( (b & m) == 0U ) {					return bno;				}				if ( ++bno >= end ) {					return TSD_DB0_RTN_M1;				}			} while ( (m >>= 1U) != 0U );		}	} else {		for ( ;; ) {			b = *bitMap(bm, (W)((UW)bno >> TSD_DAM_BS_3), MD_RDONLY);			m = (UB)(TSD_DAM_BIT_0X01 << ((UW)bno & TSD_DAM_LSF_7));			do {				if ( (b & m) == 0U ) {					return bno;				}				if ( ++bno >= end ) {					return TSD_DB0_RTN_M1;				}			} while ( (m <<= 1U) != 0U );		}	}}/* * Search the width bits from bno th bit of the block bit map bm, * and return the position where bit 1 is first found. If not found, return -1. * It must be that width > 0. */LOCAL W bitSearch1( BitMapIO *bm, W bno, W width ){	W	end = bno + width;	UB	b, m;	if ( bm->fsinfo->bigEndian != 0U ) {		for ( ;; ) {			b = *bitMap(bm, (W)((UW)bno >> TSD_DAM_BS_3), MD_RDONLY);			m = (UB)(TSD_DAM_BIT_0X80 >> ((UW)bno & TSD_DAM_RSF_7));			do {				if ( (b & m) != 0U ) {

⌨️ 快捷键说明

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