📄 block.c
字号:
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1996
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* BLOCK.C - Directory block buffering routines
Block buffers contain a data block a DDRIVE pointer and a block number.
If the DDRIVE pointer is Non Null the data is valid for the block.
Blocks have three states.
Unused - May be grabbed to use on a block. (PDRIVE == NULL)
Open - May not be re-used until the routine using it lets go
Closed - Data is valid in the buffer but no one is using it.
if there are no Unused blocks this one may be used.
But if someone needs the data in here it will be re-opened
and used.
Routines in this file include:
pc_alloc_blk - Internal to this file.
pc_blkpool - Internal to this file.
pc_free_all_blk - Release all buffers associated with a drive
pc_free_buf - Release a single buffer for possible re-use
pc_init_blk - Initialize a buffer's drive and block #s. Zero its
data buffer
pc_read_blk - Read data from disk into a buffer
pc_write_blk - Write data from the buffer to the disk.
pc_scratch_blk - Allocate a block to use as a scratch buffer
*/
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
RTFS_FILE(allocblk.c, pc_alloc_blk)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
/******************************************************************************
PC_ALLOC_BLK - Find existing or create an empty block in the buffer pool.
Description
Use pdrive and blockno to search for a buffer in the buffer pool.
If not found create a new buffer entry by discarding the Least recently
used buffer in the buffer pool. The buffer is locked in core. A pointer to
the buffer is returned in ppblk. If all buffers are in use it returns
NULL in *ppblk.
Returns
Returns TRUE if the buffer was found in the pool or FALSE if a new
buffer was assigned.
*****************************************************************************/
extern dword useindex; /* See bss.c */
/* This function is used only by functions in this file */
BOOLEAN pc_alloc_blk(BLKBUFF **ppblk, DDRIVE *pdrive, BLOCKT blockno) /*__fn__*/
{
BLKBUFF *pblk;
BLKBUFF *oldest = 0;
BLKBUFF *freeblk = 0;
dword lru = (dword) ~0L;
/* Get or init the block pool */
pblk = pc_blkpool(pdrive);
OS_CLAIM_FSCRITICAL()
useindex += 1;
while (pblk)
{
if (!pblk->pdrive)
{
/* This buffer's free */
freeblk = pblk; /* BUG FIX */
}
else
{
if ( (pblk->pdrive == pdrive) && (pblk->blockno == blockno) )
{
/* Found it */
*ppblk = pblk;
/* Update the last recently used stuf */
pblk->lru = useindex;
pblk->use_count += 1;
OS_RELEASE_FSCRITICAL()
return(TRUE);
}
else
{
/* No match. see if its a candidate for swapping if we run out of
pointers */
if (!pblk->use_count)
{
if (pblk->lru < lru)
{
lru = pblk->lru;
oldest = pblk;
}
}
}
}
pblk = pblk->pnext;
}
/* If off the end of the list we have to bump somebody */
if (freeblk)
pblk = freeblk;
else
pblk = oldest;
if (!pblk)
{
OS_RELEASE_FSCRITICAL()
pc_report_error(PCERR_BLOCKCLAIM);
/* Panic */
*ppblk = 0;
return(FALSE);
}
pblk->lru = useindex;
pblk->pdrive = pdrive;
pblk->blockno = blockno;
pblk->use_count = 1;
OS_RELEASE_FSCRITICAL()
*ppblk = pblk;
/* Return FALSE since we didn't find it in the buffer pool */
return (FALSE);
}
RTFS_FILE(blkpool.c, pc_blkpool)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
/****************************************************************************
PC_BLKBOOLEAN - Return the first element in a drives buffer pool
Description
Return the beginning of the buffer pool for a drive. If the pool
is uninitialized report it. The buffer pool should have been
initialized in pc_memory_init.
Returns
Returns the beginning of the buffer pool or NULL if pc_memory_init was
not first called.
****************************************************************************/
/* Return the beginning of the buffer pool. Report an error if not already
initialized */
BLKBUFF *pc_blkpool(DDRIVE *pdrive) /*__fn__*/
{
ARGSUSED_PVOID(pdrive);
return(mem_block_pool);
}
RTFS_FILE(frealblk.c, pc_free_all_blk)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
/****************************************************************************
PC_FREE_ALL_BLK - Release all buffers associated with a drive
Description
Use pdrive to find all buffers in the buffer pool associated with the
drive. Mark them as unused, called by dsk_close.
If any are locked, print a debug message in debug mode to warn the
programmer.
Returns
Nothing
****************************************************************************/
void pc_free_all_blk(DDRIVE *pdrive) /*__fn__*/
{
BLKBUFF *pblk;
/* Get or init the block pool */
pblk = pc_blkpool(pdrive);
OS_CLAIM_FSCRITICAL()
while (pblk)
{
if (pblk->pdrive == pdrive)
{
if (pblk->use_count)
pc_report_error(PCERR_BLOCKLOCK);
pblk->use_count = 0;
pblk->pdrive = 0;
}
pblk = pblk->pnext;
}
OS_RELEASE_FSCRITICAL()
}
RTFS_FILE(freebuf.c, pc_free_buf)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
/*****************************************************************************
PC_FREE_BUF - Unlock a block buffer.
Description
Give back a buffer to the system buffer pool so that it may
be re-used. If was_err is TRUE this means that the data in the
buffer is invalid so discard the buffer from the buffer pool.
Returns
Nothing
***************************************************************************/
/* Free a buffer by unlocking it. If waserr is true, zero out the
drive number so the erroneous data is not cached. */
void pc_free_buf(BLKBUFF *pblk, BOOLEAN waserr) /*__fn__*/
{
OS_CLAIM_FSCRITICAL()
if (pblk)
{
if (pblk->use_count)
pblk->use_count -= 1;
/* If the buffer is corrupted we null the buffer. This is safe even
in a multitasking environment because the region of the disk
containing the block is always locked exclusively when buffer
writes are taking place */
if (waserr)
pblk->pdrive = 0;
}
OS_RELEASE_FSCRITICAL()
}
RTFS_FILE(initblk.c, pc_init_blk)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if (RTFS_WRITE)
#if (RTFS_SUBDIRS)
/***************************************************************************
PC_INIT_BLK - Zero a BLKBUFF and add it to the buffer pool
Description
Allocate and zero a BLKBUFF and add it to the to the buffer pool.
Note: After initializing you "own" the buffer. You must release it by
calling pc_free_buff() before it may be used for other blocks.
Returns
Returns a valid pointer or NULL if no core.
****************************************************************************/
BLKBUFF *pc_init_blk(DDRIVE *pdrive, BLOCKT blockno) /*__fn__*/
{
BLKBUFF *pblk;
if ( !pdrive || (blockno >= pdrive->numsecs) )
return(0);
else
{
pc_alloc_blk(&pblk, pdrive , blockno );
if (pblk)
pc_memfill(pblk->data, 512, '\0');
return (pblk);
}
}
#endif
#endif
RTFS_FILE(readblk.c, pc_read_blk)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
/****************************************************************************
PC_READ_BLK - Allocate and read a BLKBUFF, or get it from the buffer pool.
Description
Use pdrive and blockno to determine what block to read. Read the block
or get it from the buffer pool and return the buffer.
Note: After reading, you "own" the buffer. You must release it by
calling pc_free_buff() before it may be used for other blocks.
Returns
Returns a valid pointer or NULL if block not found and not readable.
*****************************************************************************/
BLKBUFF *pc_read_blk(DDRIVE *pdrive, BLOCKT blockno) /*__fn__*/
{
BLKBUFF *pblk;
BOOLEAN found_buffer;
if ( !pdrive || (blockno >= pdrive->numsecs) )
return(0);
found_buffer = pc_alloc_blk(&pblk, pdrive , blockno);
if (pblk)
{
if (!found_buffer)
{
/* We allocated a buffer but it doesn't have valid data
read it in. If the read fails throw the buffer away */
if (!devio_read(pdrive->driveno, blockno, pblk->data, (int) 1, FALSE))
{
/* oops: Error, Discard the buffer */
pc_free_buf(pblk, TRUE);
pblk = 0;
}
}
}
return(pblk);
}
RTFS_FILE(writblk.c, pc_write_blk)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
#if (RTFS_WRITE)
/***************************************************************************
PC_WRITE_BLK - Flush a BLKBUFF to disk.
Description
Use pdrive and blockno information in pblk to flush it's data buffer
to disk.
Returns
Returns TRUE if the write succeeded.
****************************************************************************/
/* Write */
BOOLEAN pc_write_blk(BLKBUFF *pblk) /*__fn__*/
{
BOOLEAN ret_val;
if (!pblk || !pblk->pdrive)
{
return(FALSE);
}
ret_val = devio_write(pblk->pdrive->driveno,pblk->blockno, pblk->data, (int) 1, FALSE);
return(ret_val);
}
#endif
RTFS_FILE(scrtchblk.c, pc_scratch_blk)
#ifndef __PCDISK__ /* This allows us to build the lib with subroutines split */
#include <pcdisk.h>
#endif
/***************************************************************************
PC_SCRATCH_BLK - Return a block for scratch purposes.
Description
Use the block buffer pool as a heap of 512 byte memory locations
When done call void pc_free_buf(pblk, TRUE) to clean up
Returns
Returns a blkbuf if one is available or NULL
****************************************************************************/
extern DDRIVE *scratch_pdrive; /* See bss.c */
/* Write */
BLKBUFF *pc_scratch_blk(void) /*__fn__*/
{
BLKBUFF *pblk;
OS_CLAIM_FSCRITICAL()
scratch_pdrive++; /* We want a unique number for the alloc routine */
OS_RELEASE_FSCRITICAL()
pc_alloc_blk(&pblk, scratch_pdrive, BLOCKEQ0);
return (pblk);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -