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

📄 posixio.c

📁 一个用来实现偏微分方程中网格的计算库
💻 C
📖 第 1 页 / 共 3 页
字号:
			pxp->bf_offset,			pxp->bf_cnt,			pxp->bf_base,			&pxp->pos);		if(status != ENOERR)			return status;		pxp->bf_rflags = 0;	}pgin:	status = px_pgin(nciop,		 blkoffset,		 blkextent,		 pxp->bf_base,		 &pxp->bf_cnt,		 &pxp->pos);	if(status != ENOERR)		return status;	 pxp->bf_offset = blkoffset;	 pxp->bf_extent = blkextent;done:	extent += diff;	if(pxp->bf_cnt < extent)		pxp->bf_cnt = extent;	assert(pxp->bf_cnt <= pxp->bf_extent);	pxp->bf_rflags |= rflags;	pxp->bf_refcount++;	*vpp = (char *)pxp->bf_base + diff;	return ENOERR;}/* Request that the region (offset, extent) be made available through   *vpp.   This function converts a file region specified by an offset and   extent to a memory pointer. The region may be locked until the   corresponding call to rel().   For POSIX systems, without NC_SHARE. This function gets a page of   size extent?    This is a wrapper for the function px_get, which does all the heavy   lifting.   nciop - pointer to ncio struct for this file.   offset - offset (from beginning of file?) to the data we want to   read.   extent - the number of bytes to read from the file.   rflags - One of the RGN_* flags defined in ncio.h.   vpp - handle to point at data when it's been read.*/static intncio_px_get(ncio *const nciop, 		off_t offset, size_t extent,		int rflags,		void **const vpp){	ncio_px *const pxp = (ncio_px *)nciop->pvt;		if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE))		return EPERM; /* attempt to write readonly file */	/* reclaim space used in move */	if(pxp->slave != NULL)	{		if(pxp->slave->bf_base != NULL)		{			free(pxp->slave->bf_base);			pxp->slave->bf_base = NULL;			pxp->slave->bf_extent = 0;			pxp->slave->bf_offset = OFF_NONE;		}		free(pxp->slave);		pxp->slave = NULL;	}	return px_get(nciop, pxp, offset, extent, rflags, vpp);}/* ARGSUSED */static intpx_double_buffer(ncio *const nciop, off_t to, off_t from,			size_t nbytes, int rflags){	ncio_px *const pxp = (ncio_px *)nciop->pvt;	int status = ENOERR;	void *src;	void *dest;	#if INSTRUMENTfprintf(stderr, "\tdouble_buffr %ld %ld %ld\n",		 (long)to, (long)from, (long)nbytes);#endif	status = px_get(nciop, pxp, to, nbytes, RGN_WRITE,			&dest);	if(status != ENOERR)		return status;	if(pxp->slave == NULL)	{		pxp->slave = (ncio_px *) malloc(sizeof(ncio_px));		if(pxp->slave == NULL)			return ENOMEM;		pxp->slave->blksz = pxp->blksz;		/* pos done below */		pxp->slave->bf_offset = pxp->bf_offset; 		pxp->slave->bf_extent = pxp->bf_extent;		pxp->slave->bf_cnt = pxp->bf_cnt;		pxp->slave->bf_base = malloc(2 * pxp->blksz);		if(pxp->slave->bf_base == NULL)			return ENOMEM;		(void) memcpy(pxp->slave->bf_base, pxp->bf_base,			 pxp->bf_extent);		pxp->slave->bf_rflags = 0;		pxp->slave->bf_refcount = 0;		pxp->slave->slave = NULL;	}		pxp->slave->pos = pxp->pos;	status = px_get(nciop, pxp->slave, from, nbytes, 0,			&src);	if(status != ENOERR)		return status;	if(pxp->pos != pxp->slave->pos)	{		/* position changed, sync */		pxp->pos = pxp->slave->pos;	}	(void) memcpy(dest, src, nbytes);	(void)px_rel(pxp->slave, from, 0);	(void)px_rel(pxp, to, RGN_MODIFIED);		return status;}/* Like memmove(), safely move possibly overlapping data.   Copy one region to another without making anything available to   higher layers. May be just implemented in terms of get() and rel(),   or may be tricky to be efficient. Only used in by nc_enddef()   after redefinition.   nciop - pointer to ncio struct with file info.   to - src for move?   from - dest for move?   nbytes - number of bytes to move.   rflags - One of the RGN_* flags defined in ncio.h. The only   reasonable flag value is RGN_NOLOCK.*/static intncio_px_move(ncio *const nciop, off_t to, off_t from,			size_t nbytes, int rflags){	ncio_px *const pxp = (ncio_px *)nciop->pvt;	int status = ENOERR;	off_t lower;		off_t upper;	char *base;	size_t diff;	size_t extent;	if(to == from)		return ENOERR; /* NOOP */		if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE))		return EPERM; /* attempt to write readonly file */	rflags &= RGN_NOLOCK; /* filter unwanted flags */	if(to > from)	{		/* growing */		lower = from;			upper = to;	}	else	{		/* shrinking */		lower = to;		upper = from;	}	diff = (size_t)(upper - lower);	extent = diff + nbytes;#if INSTRUMENTfprintf(stderr, "ncio_px_move %ld %ld %ld %ld %ld\n",		 (long)to, (long)from, (long)nbytes, (long)lower, (long)extent);#endif	if(extent > pxp->blksz)	{		size_t remaining = nbytes;if(to > from){		off_t frm = from + nbytes;		off_t toh = to + nbytes;		for(;;)		{			size_t loopextent = MIN(remaining, pxp->blksz);			frm -= loopextent;			toh -= loopextent;			status = px_double_buffer(nciop, toh, frm,				 	loopextent, rflags) ;			if(status != ENOERR)				return status;			remaining -= loopextent;			if(remaining == 0)				break; /* normal loop exit */		}}else{		for(;;)		{			size_t loopextent = MIN(remaining, pxp->blksz);			status = px_double_buffer(nciop, to, from,				 	loopextent, rflags) ;			if(status != ENOERR)				return status;			remaining -= loopextent;			if(remaining == 0)				break; /* normal loop exit */			to += loopextent;			from += loopextent;		}}		return ENOERR;	}	#if INSTRUMENTfprintf(stderr, "\tncio_px_move small\n");#endif	status = px_get(nciop, pxp, lower, extent, RGN_WRITE|rflags,			(void **)&base);	if(status != ENOERR)		return status;	if(to > from)		(void) memmove(base + diff, base, nbytes); 	else		(void) memmove(base, base + diff, nbytes); 			(void) px_rel(pxp, lower, RGN_MODIFIED);	return status;}/* Flush any buffers to disk. May be a no-op on if I/O is unbuffered.   This function is used when NC_SHARE is NOT used.*/static intncio_px_sync(ncio *const nciop){	ncio_px *const pxp = (ncio_px *)nciop->pvt;	int status = ENOERR;	if(fIsSet(pxp->bf_rflags, RGN_MODIFIED))	{		assert(pxp->bf_refcount <= 0);		status = px_pgout(nciop, pxp->bf_offset,			pxp->bf_cnt,			pxp->bf_base, &pxp->pos);		if(status != ENOERR)			return status;		pxp->bf_rflags = 0;	}	else if (!fIsSet(pxp->bf_rflags, RGN_WRITE))	{	    /*	     * The dataset is readonly.  Invalidate the buffers so	     * that the next ncio_px_get() will actually read data.	     */	    pxp->bf_offset = OFF_NONE;	    pxp->bf_cnt = 0;	}	return status;}/* Internal function called at close to   free up anything hanging off pvt.*/static voidncio_px_free(void *const pvt){	ncio_px *const pxp = (ncio_px *)pvt;	if(pxp == NULL)		return;	if(pxp->slave != NULL)	{		if(pxp->slave->bf_base != NULL)		{			free(pxp->slave->bf_base);			pxp->slave->bf_base = NULL;			pxp->slave->bf_extent = 0;			pxp->slave->bf_offset = OFF_NONE;		}		free(pxp->slave);		pxp->slave = NULL;	}			if(pxp->bf_base != NULL)	{		free(pxp->bf_base);		pxp->bf_base = NULL;		pxp->bf_extent = 0;		pxp->bf_offset = OFF_NONE;	}}/* This is the second half of the ncio initialization. This is called   after the file has actually been opened.   The most important thing that happens is the allocation of a block   of memory at pxp->bf_base. This is going to be twice the size of   the chunksizehint (rounded up to the nearest sizeof(double)) passed   in from nc__create or nc__open. The rounded chunksizehint (passed   in here in sizehintp) is going to be stored as pxp->blksize.   According to our "contract" we are not allowed to ask for an extent   larger than this chunksize/sizehint/blksize from the ncio get   function.   nciop - pointer to the ncio struct   sizehintp - pointer to a size hint that will be rounded up and   passed back to the caller.   isNew - true if this is being called from ncio_create for a new   file.*/static intncio_px_init2(ncio *const nciop, size_t *sizehintp, int isNew){	ncio_px *const pxp = (ncio_px *)nciop->pvt;	const size_t bufsz = 2 * *sizehintp;	assert(nciop->fd >= 0);	pxp->blksz = *sizehintp;	assert(pxp->bf_base == NULL);	/* this is separate allocation because it may grow */	pxp->bf_base = malloc(bufsz);	if(pxp->bf_base == NULL)		return ENOMEM;	/* else */	pxp->bf_cnt = 0;	if(isNew)	{		/* save a read */		pxp->pos = 0;		pxp->bf_offset = 0;		pxp->bf_extent = bufsz;		(void) memset(pxp->bf_base, 0, pxp->bf_extent);	}	return ENOERR;}/* This is the first of a two-part initialization of the ncio struct.   Here the rel, get, move, sync, and free function pointers are set   to their POSIX non-NC_SHARE functions (ncio_px_*).   The ncio_px struct is also partially initialized.*/static voidncio_px_init(ncio *const nciop){	ncio_px *const pxp = (ncio_px *)nciop->pvt;	*((ncio_relfunc **)&nciop->rel) = ncio_px_rel; /* cast away const */	*((ncio_getfunc **)&nciop->get) = ncio_px_get; /* cast away const */	*((ncio_movefunc **)&nciop->move) = ncio_px_move; /* cast away const */	*((ncio_syncfunc **)&nciop->sync) = ncio_px_sync; /* cast away const */	*((ncio_freefunc **)&nciop->free) = ncio_px_free; /* cast away const */	pxp->blksz = 0;	pxp->pos = -1;	pxp->bf_offset = OFF_NONE;	pxp->bf_extent = 0;	pxp->bf_rflags = 0;	pxp->bf_refcount = 0;	pxp->bf_base = NULL;	pxp->slave = NULL;}/* Begin spx *//* This is the struct that gets hung of ncio->pvt(?) when the NC_SHARE   flag is used.*/typedef struct ncio_spx {	off_t pos;	/* buffer */	off_t	bf_offset; 	size_t	bf_extent;	size_t	bf_cnt;	void	*bf_base;} ncio_spx;/*ARGSUSED*//* This function releases the region specified by offset.   For POSIX system, with NC_SHARE, this becomes the rel function   pointed to by the ncio rel function pointer. It mearly checks for   file write permission, then calls px_rel to do everything.   nciop - pointer to ncio struct.   offset - beginning of region.   rflags - One of the RGN_* flags defined in ncio.h. If set to   RGN_MODIFIED it means that the data in this region were modified,   and it needs to be written out to the disk immediately (since we   are not buffering with NC_SHARE on).*/static intncio_spx_rel(ncio *const nciop, off_t offset, int rflags){	ncio_spx *const pxp = (ncio_spx *)nciop->pvt;	int status = ENOERR;	assert(pxp->bf_offset <= offset);	assert(pxp->bf_cnt != 0);	assert(pxp->bf_cnt <= pxp->bf_extent);#ifdef X_ALIGN	assert(offset < pxp->bf_offset + X_ALIGN);	assert(pxp->bf_cnt % X_ALIGN == 0 );#endif	if(fIsSet(rflags, RGN_MODIFIED))	{		if(!fIsSet(nciop->ioflags, NC_WRITE))			return EPERM; /* attempt to write readonly file */		status = px_pgout(nciop, pxp->bf_offset,			pxp->bf_cnt,			pxp->bf_base, &pxp->pos);		/* if error, invalidate buffer anyway */	}	pxp->bf_offset = OFF_NONE;	pxp->bf_cnt = 0;	return status;}/* Request that the region (offset, extent) be made available through   *vpp.   This function converts a file region specified by an offset and   extent to a memory pointer. The region may be locked until the   corresponding call to rel().   For POSIX systems, with NC_SHARE.   nciop - pointer to ncio struct for this file.   offset - offset (from beginning of file?) to the data we want to   read.   extent - the number of bytes we want.   rflags - One of the RGN_* flags defined in ncio.h. May be RGN_NOLOCK.   vpp - handle to point at data when it's been read.*/static intncio_spx_get(ncio *const nciop,		off_t offset, size_t extent,		int rflags,		void **const vpp){	ncio_spx *const pxp = (ncio_spx *)nciop->pvt;	int status = ENOERR;#ifdef X_ALIGN	size_t rem;#endif		if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE))		return EPERM; /* attempt to write readonly file */	assert(extent != 0);	assert(extent < X_INT_MAX); /* sanity check */	assert(pxp->bf_cnt == 0);#ifdef X_ALIGN	rem = (size_t)(offset % X_ALIGN);	if(rem != 0)	{		offset -= rem;		extent += rem;	}	{		const size_t rndup = extent % X_ALIGN;		if(rndup != 0)			extent += X_ALIGN - rndup;	}	assert(offset % X_ALIGN == 0);	assert(extent % X_ALIGN == 0);#endif	if(pxp->bf_extent < extent)	{		if(pxp->bf_base != NULL)		{			free(pxp->bf_base);			pxp->bf_base = NULL;			pxp->bf_extent = 0;		}		assert(pxp->bf_extent == 0);		pxp->bf_base = malloc(extent);		if(pxp->bf_base == NULL)			return ENOMEM;		pxp->bf_extent = extent;	}	status = px_pgin(nciop, offset,		 extent,		 pxp->bf_base,		 &pxp->bf_cnt, &pxp->pos);	if(status != ENOERR)		return status;	pxp->bf_offset = offset;	if(pxp->bf_cnt < extent)		pxp->bf_cnt = extent;#ifdef X_ALIGN	*vpp = (char *)pxp->bf_base + rem;#else	*vpp = pxp->bf_base;#endif	return ENOERR;}#if 0/*ARGSUSED*/static intstrategy(ncio *const nciop, off_t to, off_t offset,			size_t extent, int rflags){	static ncio_spx pxp[1];	int status = ENOERR;#ifdef X_ALIGN	size_t rem;#endif		assert(extent != 0);	assert(extent < X_INT_MAX); /* sanity check */#if INSTRUMENTfprintf(stderr, "strategy %ld at %ld to %ld\n",	 (long)extent, (long)offset, (long)to);#endif#ifdef X_ALIGN

⌨️ 快捷键说明

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