231 lines
7.1 KiB
C
231 lines
7.1 KiB
C
/* =====> SBIGMXT.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 extended memory and is tied closely
|
||
to EXTSMMU.ASM
|
||
Date Written: 4 June 86
|
||
|
||
*/
|
||
#include "scheme.h"
|
||
|
||
/* The following are specified in EXTSMMU.ASM and must be the same here */
|
||
#define FIXED 0x0080
|
||
#define SWAPPED 0x0001
|
||
|
||
/* Turn off assertions in SBIGMXT.C for performance reasons */
|
||
#define ASSERT(arg) /* do nothing */
|
||
#define ENTER(xyz) /* do nothing */
|
||
|
||
/************************************************************************/
|
||
/* 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 */
|
||
again:
|
||
if ((page = find_big_block(number_of_pages)) == -1)
|
||
{
|
||
out_of_memory(); /* attempt to execute SCHEME-RESET */
|
||
goto again;
|
||
}
|
||
}
|
||
}
|
||
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 real_pages[NUMPAGES+1]; /* real memory page table */
|
||
int i,j,k,l; /* our old favorite index variables */
|
||
int gap,temp; /* used for sort algorithm */
|
||
int page; /* working page number */
|
||
int page_found = -1; /* page number of first page in big block */
|
||
|
||
ENTER(find_big_block);
|
||
|
||
/* 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 real memory pages to satisfy request */
|
||
for (i = 0; i < NUMPAGES - DEDPAGES - number_of_pages; i++)
|
||
{
|
||
if ((free_pages[i] != -1) && ((pagetabl[free_pages[i]] & SWAPPED) == 0))
|
||
{
|
||
j = 1;
|
||
while ((free_pages[i+j] != -1) &&
|
||
((pagetabl[free_pages[i+j]] & SWAPPED) == 0) &&
|
||
((pagetabl[free_pages[i+j]] - pagetabl[free_pages[i+j-1]]) == PAGESIZE/16))
|
||
{
|
||
j++;
|
||
if (j >= number_of_pages)
|
||
{
|
||
/* required number of real memory pages found-- adjust page table */
|
||
page_found = free_pages[i];
|
||
update_pages(free_pages,i,number_of_pages);
|
||
return(page_found);
|
||
}
|
||
}
|
||
i += j;
|
||
}
|
||
}
|
||
|
||
/* At this point, there are no contiguous pages in real/conventional */
|
||
/* memory. Get a list of all the swappable real memory pages and sort */
|
||
/* them according to their paragraph address */
|
||
|
||
for (i=0; i <= NUMPAGES; i++)
|
||
if ((i <= DEDPAGES) || ((pagetabl[i] & FIXED+SWAPPED) != 0))
|
||
real_pages[i] = 1000;
|
||
else
|
||
real_pages[i] = i;
|
||
|
||
for (gap = NUMPAGES/2; gap > 0; gap /=2)
|
||
for(i=gap; i<NUMPAGES; i++)
|
||
for(j=i-gap;j>=0 && ((real_pages[j] == 1000) ? 65536 : pagetabl[real_pages[j]]) >
|
||
((real_pages[j+gap] == 1000) ? 65536 : pagetabl[real_pages[j+gap]]);j-=gap)
|
||
{
|
||
temp = real_pages[j];
|
||
real_pages[j] = real_pages[j+gap];
|
||
real_pages[j+gap] = temp;
|
||
}
|
||
|
||
/* Search for a contiguous group of extended memory pages to satisfy */
|
||
/* request. Once a group of potential pages is found, search the */
|
||
/* sorted real_pages for a contiguous group of real memory pages, ie */
|
||
/* consecutive paragraph addresses, for pages which may be swapped to */
|
||
/* extended memory. Swap them out, and use their prior paragraph */
|
||
/* addresses to allocate the big block. */
|
||
|
||
for (i = 0; i < NUMPAGES - DEDPAGES - number_of_pages; i++)
|
||
{
|
||
if ((free_pages[i] != -1) && ((pagetabl[free_pages[i]] & SWAPPED) == SWAPPED))
|
||
{
|
||
j = 1;
|
||
/* Lets look for consecutive extended memory pages */
|
||
while ((free_pages[i+j] != -1) &&
|
||
((pagetabl[free_pages[i+j]] & SWAPPED) == SWAPPED) &&
|
||
((free_pages[i+j] - free_pages[i+j-1]) == 1))
|
||
{
|
||
j++;
|
||
if (j >= number_of_pages)
|
||
{
|
||
page_found = free_pages[i];
|
||
|
||
l=0;
|
||
/* Now lets look for contiguous real memory pages */
|
||
while (real_pages[l] != 1000)
|
||
{
|
||
k=1;
|
||
/* Note : Can't swap current code block page - CB_pag */
|
||
if ((real_pages[l]*2) != CB_pag)
|
||
{
|
||
while ((real_pages[l+k] != 1000) &&
|
||
((real_pages[l+k]*2) != CB_pag) &&
|
||
((pagetabl[real_pages[l+k]] - pagetabl[real_pages[l+k-1]]) == PAGESIZE/16))
|
||
{
|
||
k++;
|
||
if (k > number_of_pages)
|
||
{
|
||
/* Move each real memory page to extended memory */
|
||
for (k=0; k<number_of_pages; k++)
|
||
move_page(real_pages[l+k]*2,free_pages[i+k]*2);
|
||
update_pages(free_pages,i,number_of_pages);
|
||
return(page_found);
|
||
}
|
||
}
|
||
}
|
||
l += k;
|
||
}
|
||
return(-1); /* No contiguous real memory pages - exit */
|
||
}
|
||
}
|
||
i += j;
|
||
}
|
||
}
|
||
return(-1); /* no pages found */
|
||
} /* end of function: find_big_block(number_of_pages) */
|
||
|
||
|
||
update_pages(free_pages,index,num_pages)
|
||
int free_pages[];
|
||
int index,num_pages;
|
||
{
|
||
int i,j,page;
|
||
|
||
ENTER(update_pages);
|
||
|
||
page = free_pages[index];
|
||
pagetabl[page] = pagetabl[page] | FIXED;
|
||
psize[page] = PAGESIZE * num_pages;
|
||
free_pages[index] = -1;
|
||
|
||
for (j = 1; j < num_pages; j++)
|
||
{
|
||
page = free_pages[index+j];
|
||
pagetabl[page] = pagetabl[page] | FIXED;
|
||
psize[page] = 0;
|
||
attrib[page].nomemory = 1;
|
||
free_pages[index+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;
|
||
}
|
||
}
|
||
} /* end of function update_pages */
|
||
|