141 lines
4.3 KiB
C
141 lines
4.3 KiB
C
|
/* =====> SBIGMXP.C */
|
|||
|
/* TIPC Scheme '84 Runtime Support - Memory Allocation Routines
|
|||
|
(C) Copyright 1984, 1985 by Texas Instruments Incorporated.
|
|||
|
All rights reserved.
|
|||
|
|
|||
|
Author: Terry Caudill
|
|||
|
Installation: Texas Instruments Incorporated, Austin, Texas
|
|||
|
Division: Data Systems Group
|
|||
|
Project: PC Scheme
|
|||
|
Comments: This code was lifted from SBIGMEM.C, which was used to
|
|||
|
allocate objects greater than on page in size. It was
|
|||
|
modified to understand expanded memory and is tied closely
|
|||
|
to EXPSMMU.ASM
|
|||
|
Date Written: 4 June 86
|
|||
|
|
|||
|
*/
|
|||
|
#include "scheme.h"
|
|||
|
|
|||
|
/* Turn off assertions in SBIGMXP.C for performance reasons */
|
|||
|
#define ASSERT(arg) /* do nothing */
|
|||
|
#define ENTER(xyz) /* do nothing */
|
|||
|
|
|||
|
extern unsigned first_page; /* paragraph address of first physical page */
|
|||
|
|
|||
|
/************************************************************************/
|
|||
|
/* Allocate a Large BLock in Scheme's Memory */
|
|||
|
/************************************************************************/
|
|||
|
alloc_big_block(reg, type, size)
|
|||
|
int reg[2]; /* register to receive pointer to allocated block */
|
|||
|
int type; /* type code of block to be allocated */
|
|||
|
unsigned size; /* size of block in bytes (including block header) */
|
|||
|
{
|
|||
|
int number_of_pages; /* number of pages required to satisy request */
|
|||
|
int page; /* page number where large block can be allocated */
|
|||
|
|
|||
|
number_of_pages = ((size + (PAGESIZE - 1)) / PAGESIZE);
|
|||
|
if ((page = find_big_block(number_of_pages)) == -1)
|
|||
|
{
|
|||
|
garbage(); /* Invoke Garbage Collector to reclaim memory */
|
|||
|
if ((page = find_big_block(number_of_pages)) == -1)
|
|||
|
{
|
|||
|
gcsquish(); /* Try compacting memory */
|
|||
|
if ((page = find_big_block(number_of_pages)) == -1)
|
|||
|
{
|
|||
|
out_of_memory(); /* attempt to execute SCHEME-RESET */
|
|||
|
/* Note: The above procedure returns control elsewhere */
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
zero_page(page);
|
|||
|
put_ptr(page, 0, type, size);
|
|||
|
nextcell[page] = END_LIST;
|
|||
|
if (size <= psize[page] - BLK_OVHD)
|
|||
|
{
|
|||
|
put_ptr(page, size, FREETYPE, psize[page] - size);
|
|||
|
nextcell[page] = size;
|
|||
|
}
|
|||
|
ptype[page] = type + type;
|
|||
|
w_attrib[page] = pageattr[type];
|
|||
|
pagelink[page] = pagelist[type];
|
|||
|
pagelist[type] = page;
|
|||
|
|
|||
|
reg[C_PAGE] = ADJPAGE(page);
|
|||
|
reg[C_DISP] = 0;
|
|||
|
} /* end of function: alloc_big_block(reg, type, size) */
|
|||
|
|
|||
|
|
|||
|
find_big_block(number_of_pages)
|
|||
|
int number_of_pages; /* number of contiguous pages required */
|
|||
|
{
|
|||
|
int free_pages[NUMPAGES+1]; /* free page table */
|
|||
|
int i,j; /* our old favorite index variables */
|
|||
|
int page; /* working page number */
|
|||
|
int page_found = -1; /* page number of first page in big block */
|
|||
|
int FirstEmmPage; /* First expanded memory page */
|
|||
|
|
|||
|
ENTER(find_big_block);
|
|||
|
|
|||
|
FirstEmmPage = exppage();
|
|||
|
|
|||
|
/* Initialize free_pages table */
|
|||
|
for (i = 0; i <= NUMPAGES; i++)
|
|||
|
free_pages[i] = -1;
|
|||
|
|
|||
|
/* Record the number of all free pages */
|
|||
|
page = freepage;
|
|||
|
while (page != END_LIST)
|
|||
|
{
|
|||
|
ASSERT(page >= 0 && page < NUMPAGES /* subchk? */);
|
|||
|
ASSERT(free_pages[page] == -1 /* infinite loop? */);
|
|||
|
free_pages[page] = page;
|
|||
|
page = pagelink[page];
|
|||
|
}
|
|||
|
|
|||
|
/* Search for a contiguous group of pages to satisfy request */
|
|||
|
for (i = 0; i < NUMPAGES - DEDPAGES - number_of_pages; i++)
|
|||
|
{
|
|||
|
if (free_pages[i] != -1)
|
|||
|
{
|
|||
|
j = 1;
|
|||
|
while (free_pages[i+j] != -1 &&
|
|||
|
(((free_pages[i] < FirstEmmPage) && (free_pages[i+j] < FirstEmmPage)) ||
|
|||
|
((free_pages[i] >= FirstEmmPage) && (free_pages[i+j] >= FirstEmmPage))
|
|||
|
)
|
|||
|
)
|
|||
|
{
|
|||
|
j++;
|
|||
|
if (j >= number_of_pages)
|
|||
|
{
|
|||
|
/* required number of pages found-- adjust page table */
|
|||
|
page_found = free_pages[i];
|
|||
|
psize[page_found] = PAGESIZE * number_of_pages;
|
|||
|
free_pages[i] = -1;
|
|||
|
|
|||
|
for (j = 1; j < number_of_pages; j++)
|
|||
|
{
|
|||
|
page = free_pages[i+j];
|
|||
|
psize[page] = 0;
|
|||
|
attrib[page].nomemory = 1;
|
|||
|
free_pages[i+j] = -1;
|
|||
|
}
|
|||
|
|
|||
|
/* update list of free pages */
|
|||
|
freepage = END_LIST;
|
|||
|
for (i = NUMPAGES; i > DEDPAGES; i--)
|
|||
|
{
|
|||
|
if (free_pages[i] != -1)
|
|||
|
{
|
|||
|
pagelink[(j = free_pages[i])] = freepage;
|
|||
|
freepage = j;
|
|||
|
}
|
|||
|
}
|
|||
|
return(page_found);
|
|||
|
}
|
|||
|
}
|
|||
|
i += j;
|
|||
|
}
|
|||
|
}
|
|||
|
return(-1); /* no pages found */
|
|||
|
} /* end of function: find_big_block(number_of_pages) */
|
|||
|
|