mirror of
https://github.com/antoinevignau/source.git
synced 2025-01-22 14:30:24 +00:00
1 line
6.2 KiB
C
Executable File
1 line
6.2 KiB
C
Executable File
/***********************************************************************\
|
|
|
|
Filename: memory.c
|
|
|
|
\***********************************************************************/
|
|
|
|
#include <memory.h>
|
|
#include "proxlib.h"
|
|
#include "proxio.h"
|
|
#include "spmemory.h"
|
|
#include "scdef.h"
|
|
#include "sp.h"
|
|
#include "spdef.h"
|
|
|
|
#ifndef MM_NBLKS
|
|
#define MM_NBLKS 4 /* Default number of blocks to use */
|
|
#endif
|
|
|
|
/* Control structure for each buffer. */
|
|
|
|
typedef struct mb_struct {
|
|
HANDLE mb_file; /* file the block came from */
|
|
UCHAR *mb_blk; /* block-sized buffer (actual data) */
|
|
int mb_blknum; /* block's block number in the file */
|
|
UCHAR mb_flags; /* priority and usage requested */
|
|
UCHAR mb_age; /* how long block has been in list */
|
|
struct mb_struct *mb_newer;/* pointer to newer block */
|
|
struct mb_struct *mb_older;/* pointer to older block */
|
|
} MEMBLK;
|
|
|
|
int Memup[] = { 0 }; /* Memory is initialized */
|
|
static MEMBLK Memlist[MM_NBLKS];/* Memory headers */
|
|
static MEMBLK *Memnewest[1]; /* Newest memory block */
|
|
|
|
/* Initialize the block buffering system. */
|
|
|
|
meminit()
|
|
{
|
|
register MEMBLK *mp;
|
|
|
|
/* If this has already been done, return. */
|
|
|
|
if (Memup[0])
|
|
return(1);
|
|
|
|
/* Allocate space for each memory block; initialize each control
|
|
structure. */
|
|
|
|
for (mp = Memlist + MM_NBLKS; --mp >= Memlist; )
|
|
{
|
|
if (!(mp->mb_blk = (char *) zalloc(_SPTHID[0], MM_BLKSIZE)))
|
|
return(0);
|
|
mp->mb_file = H_ERROR;
|
|
mp->mb_flags = 0;
|
|
mp->mb_newer = mp - 1;
|
|
mp->mb_older = mp + 1;
|
|
}
|
|
|
|
/* Make the linked list into a circular queue. */
|
|
|
|
Memlist[0].mb_newer = &Memlist[MM_NBLKS - 1];
|
|
Memlist[MM_NBLKS - 1].mb_older = Memlist;
|
|
|
|
/* Initialize the top of memory pointer. */
|
|
|
|
Memnewest[0] = Memlist;
|
|
|
|
/* Memory has been initialized */
|
|
|
|
Memup[0] = 1;
|
|
return(1);
|
|
}
|
|
|
|
/* See if a block for a given file is in memory. */
|
|
|
|
MEMBLK *memcheck(file, blknum)
|
|
HANDLE file; /* The file the block is in. */
|
|
int blknum; /* The block number. */
|
|
{
|
|
register MEMBLK *mp;
|
|
|
|
mp = Memnewest[0];
|
|
while (mp->mb_file != file || mp->mb_blknum != blknum)
|
|
{
|
|
mp = mp->mb_older;
|
|
if (mp == Memnewest[0])
|
|
return (NULL);
|
|
}
|
|
return (mp);
|
|
}
|
|
|
|
/* Put a buffer at the top of the list. This is the only routine that
|
|
changes the memory control links. */
|
|
|
|
void
|
|
memlink(mp)
|
|
register MEMBLK *mp;
|
|
{
|
|
register MEMBLK *new;
|
|
|
|
/* Do nothing if the buffer is already at the top of the list. */
|
|
|
|
new = Memnewest[0];
|
|
if (new == mp)
|
|
return;
|
|
|
|
/* Unlink the buffer from the list. */
|
|
|
|
mp->mb_newer->mb_older = mp->mb_older;
|
|
mp->mb_older->mb_newer = mp->mb_newer;
|
|
|
|
/* Add it to the top of the list. */
|
|
|
|
Memnewest[0] = mp;
|
|
mp->mb_newer = new->mb_newer;
|
|
mp->mb_older = new;
|
|
new->mb_newer->mb_older = mp;
|
|
new->mb_newer = mp;
|
|
}
|
|
|
|
/* Make a buffer unused. If the buffer contained modified data, write that
|
|
data to disk. */
|
|
|
|
memdel(mp)
|
|
register MEMBLK *mp;
|
|
{
|
|
/* Write the block, if it was modified. */
|
|
|
|
if (!memwrite(mp))
|
|
return (FALSE);
|
|
|
|
/* make the buffer unused. */
|
|
|
|
mp->mb_file = H_ERROR;
|
|
mp->mb_flags = 0;
|
|
|
|
/* Make this buffer the newest; since the list is circular, moving
|
|
the newest pointer down to the next oldest will make this block
|
|
the oldest. */
|
|
|
|
memlink(mp);
|
|
Memnewest[0] = (Memnewest[0])->mb_older;
|
|
return (TRUE);
|
|
}
|
|
|
|
/* Write a block to disk. */
|
|
|
|
memwrite(mp)
|
|
register MEMBLK *mp;
|
|
{
|
|
/* Do not write it if it was not modified. */
|
|
|
|
if (!(mp->mb_flags & MM_WRITE))
|
|
return (TRUE);
|
|
|
|
/* Seek to the proper place and then write the buffer. */
|
|
|
|
if (stdseek((long)mp->mb_blknum * MM_BLKSIZE, mp->mb_file)
|
|
|| stdwrite((char *)mp->mb_blk, MM_BLKSIZE, mp->mb_file)
|
|
!= MM_BLKSIZE)
|
|
return (FALSE);
|
|
|
|
/* Mark the buffer as no longer modified. */
|
|
|
|
mp->mb_flags &= ~MM_WRITE;
|
|
return (TRUE);
|
|
}
|
|
|
|
/* Get a buffer for a block. */
|
|
|
|
UCHAR *
|
|
memread(blknum, file, flags)
|
|
int blknum; /* Block number in file. */
|
|
HANDLE file; /* File to read. */
|
|
int flags; /* Read flags. */
|
|
{
|
|
MEMBLK *mp;
|
|
|
|
/* Look for the block in memory. If it is not in memory then read
|
|
it. */
|
|
|
|
if ((mp = memcheck(file, blknum)) == NULL)
|
|
{
|
|
/* Find a buffer to read into. */
|
|
|
|
mp = Memnewest[0];
|
|
while (1)
|
|
{
|
|
mp = mp->mb_newer;
|
|
if (mp == Memnewest[0])
|
|
{
|
|
mp = mp->mb_newer;
|
|
break;
|
|
}
|
|
if (mp->mb_age >= (flags & MM_PRMASK))
|
|
break;
|
|
}
|
|
/* Free the buffer. */
|
|
|
|
if (!memdel(mp))
|
|
return (NULL);
|
|
|
|
/* if MM_READ was specified, read the block from the file */
|
|
|
|
if (flags & MM_READ)
|
|
{
|
|
if (stdseek((long)blknum * MM_BLKSIZE, file) || stdread((char *)
|
|
mp->mb_blk, MM_BLKSIZE, file) != MM_BLKSIZE)
|
|
return (NULL);
|
|
}
|
|
|
|
/* Initialize the memory data. */
|
|
|
|
mp->mb_file = file;
|
|
mp->mb_blknum = blknum;
|
|
mp->mb_flags = flags;
|
|
}
|
|
else
|
|
/* Make this block the newest; update its modify flag; store its
|
|
priority and return the block. */
|
|
|
|
mp->mb_flags |= flags & MM_WRITE;
|
|
mp->mb_age = flags & MM_PRMASK;
|
|
memlink(mp);
|
|
|
|
return (mp->mb_blk);
|
|
}
|
|
|
|
/* If file is NULLPTR write all modified blocks to disk. If not, release
|
|
all memory associated with the file. */
|
|
|
|
memflush(file)
|
|
HANDLE file; /* The file to flush. */
|
|
{
|
|
MEMBLK *mp;
|
|
|
|
for (mp = Memlist + MM_NBLKS; --mp >= Memlist; )
|
|
{
|
|
if (!file)
|
|
{
|
|
if (!memwrite(mp))
|
|
return (ERROR);
|
|
}
|
|
else if (mp->mb_file == file && !memdel(mp))
|
|
return (ERROR);
|
|
}
|
|
return (OKAY);
|
|
}
|
|
|
|
/* Change the block number associated with a block already in memory. */
|
|
|
|
int
|
|
memswitch(file, oldnum, newnum)
|
|
HANDLE file; /* The file to do it to. */
|
|
int oldnum; /* The old block number */
|
|
int newnum; /* The new block number */
|
|
{
|
|
register MEMBLK *mp;
|
|
|
|
if ((mp = memcheck(file, oldnum)) == NULL) {
|
|
return (FALSE);
|
|
}
|
|
mp->mb_blknum = newnum;
|
|
return (TRUE);
|
|
}
|