home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************/
- /* */
- /* Module: MEMINTRL.INC */
- /* */
- /* This module contains the internal routines used by MEMLIB.C. */
- /* These functions are designed to be called by the functions */
- /* contained in MEMLIB.C only and are not for use by an */
- /* application. */
- /* */
- /**********************************************************************/
-
- /*$PAGE*/
- /*====================================================================*/
- /* INCLUDE FILES */
- /*====================================================================*/
-
- #include <stddef.h>
- #include <malloc.h>
- #include <dos.h>
-
- /*******************************************************************/
- /* Error code definitions for MEMLIB. Since MEMLIB makes calls to */
- /* EMMLIB you may get EMM specific errors. These errors can be */
- /* found in table A-2 in the EMS manual. */
- /*******************************************************************/
-
- #include "errors.h"
-
- /********************************/
- /* External Function prototypes */
- /********************************/
-
- #include "memlib.h"
- #include "emmlib.h"
-
- /********************************/
- /* Internal Function prototypes */
- /********************************/
-
- unsigned int init_exp_mem (void);
- unsigned int break_overlap (unsigned int *);
- unsigned int check_best_fit (unsigned int, unsigned int *, long *);
- unsigned int split_block (unsigned int, unsigned int);
- unsigned int search_after (unsigned int, unsigned int *, unsigned int *);
- unsigned int search_before (unsigned int, unsigned int *, unsigned int *);
- unsigned int coalesce_block (unsigned int, unsigned int, unsigned int *);
- unsigned int map_dir_page (unsigned int, unsigned int);
- unsigned int check_token (unsigned int);
- unsigned int find_new_dir_start (void);
- unsigned int restore_memlib_context (unsigned int);
- unsigned int allocate_new_directory_page (void);
- unsigned int allocate_new_block (unsigned int, unsigned int);
- unsigned int check_if_all_blocks_free (unsigned int *);
- unsigned int prepare_dir_mapping (unsigned int *);
-
- /*$PAGE*/
- /*====================================================================*/
- /* DEFINES */
- /*====================================================================*/
-
- #define TRUE (unsigned int) 1
- #define FALSE (unsigned int) 0
- #define PASSED (unsigned int) 0
- #define K64K (unsigned long) (64L * 1024L)
- #define K16K (unsigned int) (16 * 1024)
-
- #define PAGE_SIZE (unsigned int) K16K
- #define MAX_PAGE_FRAME_SIZE (unsigned int) 24
- #define LARGEST_ALLOCATABLE_BLOCK (unsigned int) (K64K - 1)
- #define MAX_ALLOCATABLE_PAGES (unsigned int) 4
- #define MAX_CONTEXTS_AVAILABLE (unsigned int) 10
- #define MAX_DIR_ENTRIES (unsigned int) (K64K - 1)
-
- #define FIRST_PHYS_PAGE (unsigned int) 0
- #define SECOND_PHYS_PAGE (unsigned int) 1
-
- #define UNASSIGNED_TOKEN (unsigned int) 0xFFFF
- #define OFFSET_SIZE (unsigned int) 0x0400
- #define UNMAPPED (unsigned int) 0xFFFF
- #define NO_CONTEXTS (unsigned int) 0xFFFF
-
- #define EMM_NOT_ENOUGH_PAGES (unsigned int) 0x88
-
- #define DIR_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(DIRECTORY_NODE))
-
- /*$PAGE*/
- /*====================================================================*/
- /* TYPEDEFS */
- /*====================================================================*/
-
- /**********************************************************************/
- /* This structure stores the housekeeping information used to */
- /* uniquely identify a block of memory and to do garbage collection. */
- /* The directory is an array of these structures. */
- /* */
- /* token - An identifier to a block of memory which is an */
- /* index in the directory array. */
- /* size - The size of the memory block. */
- /* logical_page - The array of logical pages that the block uses. */
- /* offset - The offset into this block's first logical page. */
- /* We only need to keep track of the offset since the */
- /* segment is set by seteptrs when access is desired. */
- /* */
- /* We must keep track of the directory entries in two ways (an entry */
- /* meaning the index into the directory array which gives us access */
- /* to the structure above). One is in which the token is used as an */
- /* index into the directory array, giving us a range of 0 - 65535 */
- /* directory entries. Second is when we actually want to access a */
- /* directory entry. Since we cannot map in the entire directory, due */
- /* to its size, we must find what logical page an entry belongs to, */
- /* map that page in, and access that entry by using an index into */
- /* that page. This index has a range of 0 to the number of entries */
- /* possible in a page. */
- /* */
- /* Note: The token has two uses -- one for identifying a block of */
- /* memory and other as an index into the full directory array which */
- /* gives us acces to a DIRECTORY_NODE structure. The user of MEMLIB */
- /* always keeps track of his blocks of memory with the token value */
- /* and does not have to worry about the directory array. */
- /* */
- /* In order to know which logical page to map in we use the following */
- /* formula: */
- /* */
- /* directory_log_page = token / DIR_ENTRIES_PER_PAGE */
- /* */
- /* Token is the actual entry into the directory that identifies a */
- /* block. NUM_DIR_ENTRIES is a macro that returns the number of */
- /* directory entries possible in a given number of pages -- in this */
- /* case one page. By performing an integer divide, we obtain the */
- /* logical page number that this token's directory entry resides in. */
- /* */
- /* In order to access a directory entry when it is mapped in we use */
- /* this formula: */
- /* */
- /* directory_index = token % DIR_ENTRIES_PER_PAGE */
- /* */
- /* This number is used as an index into the page of the directory */
- /* array that's mapped in. This number is different than the token */
- /* which identifies the entry into the full directory array. */
- /**********************************************************************/
-
- typedef struct
- {
- unsigned int token;
- unsigned int size;
- unsigned int logical_page [MAX_ALLOCATABLE_PAGES];
- unsigned int offset;
-
- } DIRECTORY_NODE;
-
- /**********************************************************************/
- /* This structure is for holding the segment and page number of a */
- /* mappable memory region. This will be used in an array to hold the */
- /* entire list of mappable memory regions. */
- /**********************************************************************/
-
- typedef struct
- {
- unsigned int phys_page_segment;
- unsigned int phys_page_number;
-
- } MAPPABLE_REGIONS;
-
-
- /*$PAGE*/
- /*====================================================================*/
- /* MACROS */
- /*====================================================================*/
-
- /**********************************************************************/
- /* This macro returns the number of PAGE_SIZE pages needed for a */
- /* memory block of the given size. */
- /**********************************************************************/
- #define NUM_PAGES(size) ((unsigned int) (((unsigned long) size + PAGE_SIZE - 1) / PAGE_SIZE))
-
- /**********************************************************************/
- /* This macro returns the number of directory entries that fit within */
- /* the given amount of PAGES_SIZE pages. */
- /**********************************************************************/
- #define NUM_DIR_ENTRIES(num_pages) ((unsigned long) (PAGE_SIZE / sizeof (DIRECTORY_NODE)) * num_pages)
-
- /*$PAGE*/
- /*====================================================================*/
- /* GLOBAL VARIABLES */
- /*====================================================================*/
-
- /**********************************************************************/
- /* Actual number of PAGE_SIZE pages available in the page frame */
- /**********************************************************************/
-
- unsigned int num_pages_in_page_frame;
-
- /**********************************************************************/
- /* Store the page frame base address */
- /**********************************************************************/
-
- void far* page_frame_base_address;
-
- /**********************************************************************/
- /* Store the EMM handle that the app will use */
- /* Store the EMM handle that the memory manager will use */
- /**********************************************************************/
-
- unsigned int app_handle;
- unsigned int man_handle;
-
- /**********************************************************************/
- /* The first time that any of the external MEMLIB functions are */
- /* called the initializing routine must be called. This flag is set */
- /* to TRUE once the call is made. */
- /**********************************************************************/
-
- unsigned int exp_initialized = FALSE;
-
- /**********************************************************************/
- /* An array of pointers to each pysical page that the directory uses. */
- /* When we need to access two different entries on two separate pages */
- /* we can map both pages needed in. */
- /**********************************************************************/
-
- DIRECTORY_NODE far* directory[2];
-
- /**********************************************************************/
- /* Number of pages for the directory (dynamically changes) */
- /**********************************************************************/
-
- unsigned int dir_page_count;
-
- /**********************************************************************/
- /* Array tells which logical page is mapped at each physical page. */
- /* UNMAPPED ==> no page is mapped. Unmap 24 pages (A000 - EFFF). */
- /**********************************************************************/
-
- MAP_STRUCT pages_mapped[MAX_PAGE_FRAME_SIZE] =
- {
- UNMAPPED,0, UNMAPPED,1, UNMAPPED,2, UNMAPPED,3,
- UNMAPPED,4, UNMAPPED,5, UNMAPPED,6, UNMAPPED,7,
- UNMAPPED,8, UNMAPPED,9, UNMAPPED,10, UNMAPPED,11,
- UNMAPPED,12, UNMAPPED,13, UNMAPPED,14, UNMAPPED,15,
- UNMAPPED,16, UNMAPPED,17, UNMAPPED,18, UNMAPPED,19,
- UNMAPPED,20, UNMAPPED,21, UNMAPPED,22, UNMAPPED,23
- };
-
- /**********************************************************************/
- /* number_pages_mapped stores the number actually mapped. */
- /**********************************************************************/
-
- unsigned int number_pages_mapped = 0;
-
- /**********************************************************************/
- /* The total number of pages allocated to the application. */
- /**********************************************************************/
-
- unsigned int total_app_allocated_pages;
-
- /**********************************************************************/
- /* Used to get and restore partial page maps for push_context() and */
- /* pop_context(). */
- /**********************************************************************/
-
- PARTIAL_CONTEXT_LIST_STRUCT partial_page_map;
-
- /**********************************************************************/
- /* An array of pointers to saved contexts used by the push_context() */
- /* and pop_context() functions. */
- /**********************************************************************/
-
- CONTEXT_STRUCT* context_ptrs[MAX_CONTEXTS_AVAILABLE];
-
- /**********************************************************************/
- /* This variable keeps track of the top of the context_ptrs array. */
- /* This allows pop_context() to know whether there are any contexts */
- /* left to remove or for push_context() to know whether there is */
- /* enough room to store another context. */
- /**********************************************************************/
-
- unsigned int context_top;
-
- /**********************************************************************/
- /* Size of each context - set in init_exp_mem(). */
- /**********************************************************************/
-
- unsigned int context_size;
-
- /**********************************************************************/
- /* The index into the full directory array used as the starting */
- /* location when searching through the directory for a viable entry */
- /* to keep track of a new memory block. */
- /**********************************************************************/
-
- unsigned int dir_start;
-
- /**********************************************************************/
- /* The index into the full directory array used as the ending */
- /* location when searching through the directory for a viable entry */
- /* to keep track of a new memory block. */
- /**********************************************************************/
-
- unsigned int dir_end;
-
- /*$PAGE*/
- /*====================================================================*/
- /* CODE */
- /*====================================================================*/
-
- /**********************************************************************/
- /* Name: unsigned int prepare_dir_mapping (context_saved) */
- /* unsigned int *context_saved; */
- /* */
- /* Definition: */
- /* To save the context before mapping in the directory. This */
- /* function is called before a directory page will be mapped in. */
- /* It firsts checks to see if the expanded memory has been */
- /* initialized and then saves the current context. The status */
- /* will be returned to the caller for error checking. */
- /* 'context_saved' is set to TRUE if save_context() was */
- /* successful. */
- /* */
- /* The calling function can then call restore_memlib_context() */
- /* depending whether 'saved' is TRUE or not. This allows the */
- /* caller to preserve the error status from save_context(). */
- /* */
- /* Parameters: */
- /* output context_saved Whether the context was saved or not */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: init_exp_mem() */
- /* save_context() */
- /* */
- /* Called by: ememavl() */
- /* ememmax() */
- /* emsize() */
- /* efmalloc() */
- /* effree() */
- /* */
- /* Globals referenced/modified: exp_initialized */
- /* man_handle */
- /* */
- /**********************************************************************/
-
- unsigned int prepare_dir_mapping (context_saved)
- unsigned int *context_saved;
- {
- unsigned int status; /* The status of EMM and MEMLIB */
-
- *context_saved = FALSE;
- status = PASSED;
-
- /**********************************************/
- /* If expanded memory hasn't been initialized */
- /* then call init_exp_mem(). */
- /**********************************************/
-
- if (!exp_initialized)
- status = init_exp_mem();
-
- if (status == PASSED)
- {
- /*****************************/
- /* Save the current context. */
- /*****************************/
-
- status = save_context (man_handle);
- if (status == PASSED)
- {
- *context_saved = TRUE;
- }
- }
- return (status);
-
- } /** prepare_dir_mapping **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* Name: unsigned int map_dir_page (log_page, phys_page) */
- /* unsigned int log_page; */
- /* unsigned int phys_page; */
- /* */
- /* Definition: */
- /* Maps in the specified logical page for the directory into */
- /* the specified physical page. For use by MEMLIB only (uses */
- /* MEMLIB handle -- man_handle). */
- /* */
- /* Parameters: */
- /* input log_page The logical directory page to map in */
- /* input phys_page Which physical page to map log_page in */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: map_unmap_pages() */
- /* */
- /* Called by: ememavl() */
- /* ememmax() */
- /* emsize() */
- /* efmalloc() */
- /* effree() */
- /* seteptrs() */
- /* */
- /* Globals referenced/modified: exp_intialized */
- /* man_handle */
- /* */
- /**********************************************************************/
-
- unsigned int map_dir_page (log_page, phys_page)
- unsigned int log_page;
- unsigned int phys_page;
- {
- MAP_STRUCT directory_map[1]; /* Structure to use EMS map pages */
- unsigned int status; /* Status of EMM and MEMLIB */
-
- directory_map[0].log_page = log_page;
- directory_map[0].phys_page_or_seg = phys_page;
- status = map_unmap_pages (PHYS_PAGE_MODE, 1, directory_map, man_handle);
-
- return (status);
- } /** end map_dir_page **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int restore_memlib_context (status) */
- /* unsigned int status; */
- /* */
- /* Description: */
- /* Restores a context saved by prepare_dir_mapping() so that */
- /* memlib can access the directory. If the status passed in is */
- /* an error, then that is the status returned regardless if */
- /* restore_context() generates an error. If the status passed in */
- /* is PASSED, we return the status generated by restore_context().*/
- /* We do this so that in some recoverable errors we can */
- /* successfully restore the context and still return the correct */
- /* error code to the application. */
- /* */
- /* Parameters: */
- /* input status The status passed in */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: restore_context() */
- /* */
- /* Called by: ememavl() */
- /* ememmax() */
- /* emsize() */
- /* efmalloc() */
- /* effree() */
- /* */
- /* Globals referenced/modified: man_handle */
- /* */
- /**********************************************************************/
-
- unsigned int restore_memlib_context (status)
- unsigned int status;
- {
- unsigned int restore_status; /* Status returned from restore_context */
-
- restore_status = restore_context (man_handle);
- if (status == PASSED)
- return (restore_status);
- else
- return (status);
-
- } /** end restore_memlib_context **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int check_token (token) */
- /* unsigned int token; */
- /* */
- /* Description: */
- /* This function check's a token to see if it is valid. It */
- /* is valid if it is within the directory boundries. A token is */
- /* valid when it is set by efmalloc(). */
- /* */
- /* Parameters: */
- /* input token The token to be validated. */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: None */
- /* */
- /* Called by: effree() */
- /* emsize() */
- /* */
- /* Globals referenced/modified: dir_page_count */
- /* exp_initialized */
- /* */
- /**********************************************************************/
-
- unsigned int check_token (token)
- unsigned int token;
- {
- unsigned int status; /* The status of EMM and MEMLIB */
-
- /******************/
- /* Assume PASSED. */
- /******************/
-
- status = PASSED;
-
- /****************************************************************/
- /* If the manager is not initialized then the token is invalid. */
- /****************************************************************/
-
- if (!exp_initialized)
- status = INVALID_TOKEN;
-
- /***************************************************************/
- /* First make sure the token isn't greater than the number of */
- /* entries possible for the current number of directory pages. */
- /* Then check for a valid token. */
- /***************************************************************/
-
- if (status == PASSED)
- {
- if ((token > (unsigned int) (NUM_DIR_ENTRIES (dir_page_count) - 1)) ||
- (token == UNASSIGNED_TOKEN))
- status = INVALID_TOKEN;
- }
-
- return(status);
-
- } /** end check_token **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int init_exp_mem (void) */
- /* */
- /* Description: */
- /* This routine initializes the housekeeping variables needed */
- /* to keep track of expanded memory. It tests for the presence */
- /* of EMM 4.0 and initializes the directory. */
- /* */
- /* Parameters: None */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: alloc_pages() */
- /* EMM_installed() */
- /* get_page_frame_seg() */
- /* get_partial_context_size() */
- /* get_unalloc_page_count() */
- /* realloc_pages() */
- /* map_dir_page() */
- /* get_page_frame_count() */
- /* */
- /* Called by: prepare_dir_mapping() */
- /* push_context() */
- /* pop_context() */
- /* */
- /* Globals referenced/modified: directory */
- /* app_handle */
- /* context_size */
- /* dir_page_count */
- /* exp_intialized */
- /* man_handle */
- /* number_pages_mapped */
- /* page_frame_base_address */
- /* num_pages_in_page_frame */
- /* pages_mapped */
- /* context_top */
- /* total_app_allocated_pages */
- /* dir_start */
- /* dir_end */
- /* exp_initialized */
- /* partial_page_map */
- /* */
- /**********************************************************************/
-
- unsigned int init_exp_mem (void)
- {
-
- unsigned int status; /* The status of EMM and MEMLIB */
- unsigned int num_unalloc_pages; /* Number of unallocated pages */
- unsigned int page_frame_seg; /* Page frame segment */
- unsigned int i; /* Looping variable */
- unsigned int zero_pages; /* To call realloc for 0 pages */
-
- /********************************************************/
- /* Test for EMM presence and enough pages -- need at */
- /* least 1 for the directory and 1 for the application. */
- /********************************************************/
-
- status = EMM_installed();
- if (status == PASSED)
- {
- status = get_unalloc_page_count (&num_unalloc_pages);
- if (status == PASSED)
- if (num_unalloc_pages <= 1)
- status = NOT_ENOUGH_UNALLOCATED_PAGES;
- }
-
- if (status == PASSED)
- {
- /*****************************************/
- /* Allocate 0 pages for the application. */
- /* We need to first alloc 1 page to get */
- /* a handle then realloc to reduce the */
- /* number of pages used to 0. */
- /*****************************************/
-
- status = alloc_pages (1, &app_handle);
- if (status == PASSED)
- {
- zero_pages = 0;
- status = realloc_pages (&zero_pages, app_handle);
- if ((zero_pages != 0) ||
- (status == EMM_NOT_ENOUGH_PAGES))
- status = NOT_ENOUGH_UNALLOCATED_PAGES;
- }
-
- /*********************************************/
- /* Allocate 1 page for the manager (memlib). */
- /*********************************************/
-
- if (status == PASSED)
- status = alloc_pages (1, &man_handle);
-
- if (status == PASSED)
- {
- /****************************/
- /* Map this directory page. */
- /****************************/
-
- status = map_dir_page (0, FIRST_PHYS_PAGE);
- }
-
- if (status == PASSED)
- {
- /*********************************************************/
- /* Get the base address of the start of expanded memory. */
- /*********************************************************/
-
- status = get_page_frame_seg (&page_frame_seg);
- if (status == PASSED)
- {
- /***************************************************/
- /* Convert the page frame segment to a far pointer */
- /* and point directory[0] to it. */
- /***************************************************/
-
- page_frame_base_address = FP (page_frame_seg);
- directory[0] = (DIRECTORY_NODE far *) page_frame_base_address;
-
- /****************************************************/
- /* Point directory[1] to the address of the second */
- /* physical page in the page frame. */
- /****************************************************/
- FP_SEG(directory[1]) = page_frame_seg + OFFSET_SIZE;
- FP_OFF(directory[1]) = 0;
- }
- }
- }
-
- if (status == PASSED)
- {
- /************************************************/
- /* Set the variable that keeps track of the how */
- /* many pages the directory is using to 1. */
- /************************************************/
-
- dir_page_count = 1;
-
- /**************************************************************/
- /* Initialize all the directory entries so that the token */
- /* identifiers are set UNASSIGNED_TOKEN (entry is available) */
- /* and their size to 0. */
- /**************************************************************/
-
- for (i = 0; i < DIR_ENTRIES_PER_PAGE; i++)
- {
- directory[0][i].token = UNASSIGNED_TOKEN;
- directory[0][i].size = 0;
- }
-
- /********************************************************/
- /* Set the starting and ending entries in the directory */
- /* when doing free memory block searches. */
- /********************************************************/
-
- dir_start = 0;
- dir_end = 0;
-
- /****************************************************************/
- /* Set the total number of pages the application is using to 0. */
- /****************************************************************/
-
- total_app_allocated_pages = 0;
-
- /**********************************************/
- /* Get the number of pages in the page frame. */
- /**********************************************/
-
- status = get_page_frame_count (&num_pages_in_page_frame);
-
- if (status == PASSED)
- {
- /*************************************************/
- /* Set the partial page map for pushes and pops. */
- /*************************************************/
-
- partial_page_map.mappable_region_count = num_pages_in_page_frame;
- partial_page_map.mappable_region_seg[0] = FP_SEG (page_frame_base_address);
-
- /*************************************************************/
- /* Set the segment value for each 16K page in the page frame */
- /* that push_context() & pop_context() will be storing. */
- /*************************************************************/
-
- for (i = 1; i < num_pages_in_page_frame; i++)
- {
- partial_page_map.mappable_region_seg[i] =
- partial_page_map.mappable_region_seg[i - 1] + OFFSET_SIZE;
- }
-
- /***************************************************/
- /* Set the context push and pop stack to be empty. */
- /***************************************************/
-
- context_top = NO_CONTEXTS;
-
- /************************************************************/
- /* Get the number of bytes needed to save (push) a context. */
- /************************************************************/
-
- status = get_partial_context_size (num_pages_in_page_frame, &context_size);
- if (status == PASSED)
- {
- /********************/
- /* Unmap all pages. */
- /********************/
-
- for (i = 0; i < num_pages_in_page_frame; i++)
- {
- pages_mapped[i].log_page = UNMAPPED;
- }
- }
- number_pages_mapped = 0;
- }
- }
- /***************************************************************/
- /* If status is good then update the already-initialized flag. */
- /***************************************************************/
-
- if (status == PASSED)
- exp_initialized = TRUE;
-
- return (status);
-
- } /** end init_exp_mem **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int allocate_new_directory_page (void) */
- /* */
- /* Description: */
- /* This routine attempts to allocate a new page for the */
- /* directory. */
- /* */
- /* Parameters: None */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: map_dir_page() */
- /* realloc_pages() */
- /* */
- /* Called by: allocate_new_block() */
- /* check_best_fit() */
- /* */
- /* Globals referenced/modified: directory */
- /* dir_page_count */
- /* man_handle */
- /* */
- /**********************************************************************/
-
- unsigned int allocate_new_directory_page (void)
- {
- unsigned int status; /* The status of EMM and MEMLIB */
- unsigned int index; /* Index into a directory page */
- unsigned int new_num_dir_pages; /* New number of directory pages */
-
- /*****************************/
- /* Assume status will be ok. */
- /*****************************/
-
- status = PASSED;
-
- /******************************************/
- /* Set the new number of directory pages. */
- /******************************************/
-
- new_num_dir_pages = dir_page_count + 1;
-
- /***************************************************/
- /* Make sure we don't allocate beyond the maximum */
- /* number of directory entries allowable. */
- /***************************************************/
-
- if ((unsigned long) NUM_DIR_ENTRIES (new_num_dir_pages) > MAX_DIR_ENTRIES)
- status = TOO_MANY_DIRECTORY_ENTRIES;
-
- if (status == PASSED)
- {
- /************************************************/
- /* Attempt to add a new page for the directory. */
- /************************************************/
-
- status = realloc_pages (&new_num_dir_pages, man_handle);
-
- /******************************************/
- /* Make sure the number of pages returned */
- /* is equal to the number we wanted. */
- /******************************************/
-
- if ((status == EMM_NOT_ENOUGH_PAGES) ||
- (new_num_dir_pages != dir_page_count + 1))
- status = NOT_ENOUGH_UNALLOCATED_PAGES;
-
- if (status == PASSED)
- {
- /************************************************/
- /* Allocate succeeded, update the directory map */
- /************************************************/
-
- dir_page_count++;
-
- status = map_dir_page (dir_page_count - 1, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- /*****************************************/
- /* Initialize the new directory entries. */
- /*****************************************/
-
- for (index = 0; index < DIR_ENTRIES_PER_PAGE; index++)
- {
- directory[0][index].token = UNASSIGNED_TOKEN;
- directory[0][index].size = 0;
- }
- }
- }
- }
- return (status);
-
- } /** end allocate_new_directory_page **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int allocate_new_block (size, token) */
- /* unsigned int size; */
- /* unsigned int token; */
- /* */
- /* Description: */
- /* This routine attempts to allocate a block of size 'size', */
- /* in bytes, and set the fields in directory[token] appropriately.*/
- /* */
- /* Parameters: */
- /* input size the size, in bytes, to allocate */
- /* input token index into directory for this block */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: allocate_new_directory_page() */
- /* realloc_pages() */
- /* map_dir_page() */
- /* */
- /* Called by: efmalloc() */
- /* */
- /* Globals referenced/modified: directory */
- /* app_handle */
- /* dir_page_count */
- /* total_app_allocated_pages */
- /* dir_start */
- /* dir_end */
- /* */
- /**********************************************************************/
-
- unsigned int allocate_new_block (size, token)
- unsigned int size;
- unsigned int token;
- {
- unsigned int i; /* Looping variable */
- unsigned int page; /* Current directory page mapped in */
- unsigned int status; /* Status of EMM and MEMLIB */
- unsigned int num_pages_needed; /* Number of pages needed */
- unsigned int size_mod_page_size; /* Size in bytes MOD PAGE_SIZE */
- unsigned int new_total_pages; /* New number of pages for the */
- /* application's handle */
- unsigned int tokens_page; /* Token's dir entry's logical page */
- unsigned int tokens_index; /* Token's index into its page */
- unsigned int i_dir_entry; /* Translate i to an entry into the */
- /* full directory array */
- unsigned int dir_starts_page; /* Dir_start's dir entry's log page */
- unsigned int dir_starts_index; /* Dir_start's index into its page */
- unsigned int found_block; /* Whether a block was found or not */
- unsigned int remainders_logical_page; /* The remaining portion's first */
- /* logical page */
-
- status = PASSED;
-
- /****************************************************************/
- /* Check if we need to allocate another page for the directory. */
- /****************************************************************/
-
- if (dir_end >= (unsigned int) (NUM_DIR_ENTRIES (dir_page_count) - 2))
- status = allocate_new_directory_page();
-
- if (status == PASSED)
- {
- /********************************************/
- /* Allocate enough new pages for this block */
- /********************************************/
-
- num_pages_needed = NUM_PAGES (size);
- new_total_pages = total_app_allocated_pages + num_pages_needed;
-
- /*************************************************************/
- /* Assign the new number of pages to the application handle. */
- /*************************************************************/
-
- status = realloc_pages (&new_total_pages, app_handle);
-
- /******************************************/
- /* Make sure the number of pages returned */
- /* is equal to the number we wanted. */
- /******************************************/
-
- if ((new_total_pages != (total_app_allocated_pages + num_pages_needed))
- || (status == EMM_NOT_ENOUGH_PAGES))
- status = NOT_ENOUGH_UNALLOCATED_PAGES;
- }
-
- /****************************************************/
- /* If allocate succeeded, set the directory entries */
- /****************************************************/
-
- if (status == PASSED)
- {
- /*******************************************************/
- /* Convert 'token' to its respective directory entry's */
- /* logical page and its index into that page. */
- /*******************************************************/
-
- tokens_page = token / DIR_ENTRIES_PER_PAGE;
- tokens_index = token % DIR_ENTRIES_PER_PAGE;
-
- /**************************************/
- /* Map in the token's directory page. */
- /**************************************/
-
- status = map_dir_page (tokens_page, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- /**************************************/
- /* Set the entry in the directory for */
- /* the newly allocated block. */
- /**************************************/
-
- directory[0][tokens_index].token = token;
- directory[0][tokens_index].size = size;
- directory[0][tokens_index].offset = 0;
-
- /*********************************************/
- /* Set the logical pages for this block to */
- /* the logical pages that we just allocated. */
- /*********************************************/
-
- for (i = 0; i < num_pages_needed; i++)
- {
- directory[0][tokens_index].logical_page[i] =
- total_app_allocated_pages + i;
- }
-
- /**************************************************/
- /* If this block size is NOT a multiple of 16K, */
- /* find an unused directory entry and have it */
- /* point to the remaining part of the page. */
- /**************************************************/
-
- size_mod_page_size = size % PAGE_SIZE;
-
- if (size_mod_page_size != 0)
- {
- /********************************************************/
- /* We have a remainder on the last logical page for the */
- /* new block. Keep track of this page so that when we */
- /* set a free directory entry to point to the remainder */
- /* we already know what logical page it uses. */
- /********************************************************/
-
- remainders_logical_page =
- directory[0][tokens_index].logical_page[num_pages_needed - 1];
-
- dir_starts_page = dir_start / DIR_ENTRIES_PER_PAGE;
- dir_starts_index = dir_start % DIR_ENTRIES_PER_PAGE;
- found_block = FALSE;
-
- /****************************************/
- /* Go through the directory, page by */
- /* page, until we find an usable entry. */
- /****************************************/
-
- for (page = dir_starts_page; ((status == PASSED) &&
- (page < dir_page_count) &&
- (!found_block)); page++)
- {
- /***********************************/
- /* Map in the this directory page. */
- /***********************************/
-
- status = map_dir_page (page, FIRST_PHYS_PAGE);
-
- /*********************************************************/
- /* Go through each entry for the mapped in page until we */
- /* find a usable entry or until we run out of entries. */
- /*********************************************************/
-
- for (i = dir_starts_index; ((i < DIR_ENTRIES_PER_PAGE) &&
- (!found_block) &&
- (status == PASSED)); i++)
- {
- if ((directory[0][i].token == UNASSIGNED_TOKEN) &&
- (directory[0][i].size == 0))
- {
- /*******************************************/
- /* We found an unused directory entry, set */
- /* it to point to the leftover piece. */
- /*******************************************/
-
- directory[0][i].offset = size_mod_page_size;
- directory[0][i].size = PAGE_SIZE - size_mod_page_size;
- directory[0][i].logical_page[0] = remainders_logical_page;
-
- i_dir_entry = page * DIR_ENTRIES_PER_PAGE + i;
- if (i_dir_entry >= dir_end)
- dir_end = i_dir_entry + 1;
-
- found_block = TRUE;
- }
- } /** end for i **/
-
- dir_starts_index = 0;
-
- } /** end for page **/
-
- } /** end if page_mod_page_size **/
-
- /***********************************/
- /* Update the toal allocated pages */
- /***********************************/
-
- total_app_allocated_pages += num_pages_needed;
-
- } /** end if status PASSED **/
-
- } /** end if status PASSED **/
- return (status);
-
- } /** end allocate_new_block **/
-
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int split_block (best_index, size) */
- /* unsigned int best_index; */
- /* unsigned int size; */
- /* */
- /* Description: */
- /* This routine splits a block into allocated and unallocated */
- /* portions. The size is assigned to the allocated portion and */
- /* the left over portion is set up as a free block. */
- /* */
- /* Parms Passed: */
- /* input best_index The directory entry to be broken up. */
- /* It will be the entry that will point to */
- /* the allocated portion after it is broken */
- /* into its allocated/free portions. */
- /* size The size of the block to be allocated. */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: map_dir_page() */
- /* break_overlap() */
- /* */
- /* Called by: efmalloc() */
- /* */
- /* Globals referenced/modified: directory */
- /* dir_page_count */
- /* dir_end */
- /* dir_start */
- /* */
- /**********************************************************************/
-
- unsigned int split_block (best_index, size)
- unsigned int best_index;
- unsigned int size;
- {
- unsigned int num_pages_for_size; /* The num of logical pages for size */
- unsigned int size_mod_page_size; /* The size modulo the PAGE_SIZE */
- unsigned int dir_starts_page; /* Dir_start's dir entry's log page */
- unsigned int best_indexs_page; /* Best_index's dir entry's log page */
- unsigned int best_indexs_index; /* Best_index's index into its page */
- unsigned int best_index_offset; /* Best_index's logical page offset */
- unsigned int best_index_size; /* Best_index's memory block's size */
- unsigned int index; /* Current index into a logical page */
- unsigned int page; /* Current directory page mapped in */
- unsigned int remainder; /* The index into a dir page that */
- /* will point to the leftover portion */
- /* in a logical page after allocated */
- /* block is set */
- unsigned int remainders_entry; /* Remainder converted to a full */
- /* directory entry */
- unsigned int status; /* Status of EMM and MEMLIB */
- unsigned int j; /* Looping variable */
- unsigned int avail_entry_found; /* An available entry has been found */
- unsigned int start_page_for_remainder; /* The starting logical page */
- /* for the remainder */
-
- /*******************************/
- /* Initialize local variables. */
- /*******************************/
-
- avail_entry_found = FALSE;
- status = PASSED;
-
- /*************************************************/
- /* Convert dir_start to its respective directory */
- /* entry's logcal page. */
- /*************************************************/
-
- dir_starts_page = dir_start / DIR_ENTRIES_PER_PAGE;
-
- /**************************************************/
- /* Convert dir_start to its respective entry's */
- /* page index. We want to start the first */
- /* page's index at the current starting location. */
- /**************************************************/
-
- index = dir_start % DIR_ENTRIES_PER_PAGE;
-
- /****************************************************************/
- /* Check if we need to allocate another page for the directory. */
- /****************************************************************/
-
- if (dir_end >= (unsigned int) (NUM_DIR_ENTRIES (dir_page_count) - 2))
- status = allocate_new_directory_page();
-
- /****************************************************************/
- /* Go through all the directory pages starting with dir_start's */
- /* page until we find an usable entry. */
- /****************************************************************/
-
- for (page = dir_starts_page; ((page < dir_page_count) &&
- (!avail_entry_found) &&
- (status == PASSED)); page++)
- {
- /*******************************/
- /* Map in this directory page. */
- /*******************************/
-
- status = map_dir_page (page, FIRST_PHYS_PAGE);
- /************************************************************/
- /* Go through this page's indexes looking for the first */
- /* available directory entry to keep track of the remainder */
- /* portion. The first time we enter this loop we start */
- /* with the current starting location (dir_start converted */
- /* to a page's index) from above. All other index's after */
- /* the first page will start with 0. */
- /************************************************************/
-
- for (remainder = index; ((remainder < DIR_ENTRIES_PER_PAGE) &&
- (!avail_entry_found) &&
- (status == PASSED)); remainder++)
- {
- if ((directory[0][remainder].size == 0) &&
- (directory[0][remainder].token == UNASSIGNED_TOKEN))
- {
- /**********************************************/
- /* We've found an available directory entry */
- /* to keep track of the left-over portion. */
- /* Time to map in the block we want to split. */
- /**********************************************/
-
- avail_entry_found = TRUE;
-
- /*******************************************************/
- /* We're going to map in two different directory pages */
- /* so that we can reference best_index's and */
- /* remainder's directory entry at once. Since we are */
- /* using two different logical pages we need to use */
- /* directory[1] to access the second page's entries. */
- /*******************************************************/
-
- best_indexs_page = best_index / DIR_ENTRIES_PER_PAGE;
- best_indexs_index = best_index % DIR_ENTRIES_PER_PAGE;
-
- /************************************************/
- /* Map in the best_index's directory page in at */
- /* physical page one while keeping remainder's */
- /* directory page at physical page zero. */
- /************************************************/
-
- status = map_dir_page (best_indexs_page, SECOND_PHYS_PAGE);
- if (status == PASSED)
- {
- /*****************************/
- /* Set some local variables. */
- /*****************************/
-
- best_index_offset = directory[1][best_indexs_index].offset;
- best_index_size = directory[1][best_indexs_index].size;
- num_pages_for_size = NUM_PAGES (size);
-
- /*************************************************/
- /* Split this block into used and free portions. */
- /*************************************************/
-
- directory[0][remainder].size = best_index_size - size;
-
- /***********************************************************/
- /* Find the starting logical page for the remainder block. */
- /***********************************************************/
-
- if (((best_index_offset + size) % (PAGE_SIZE)) == 0)
- start_page_for_remainder = num_pages_for_size;
- else
- start_page_for_remainder = num_pages_for_size - 1;
-
- /********************************************************/
- /* Set the logical pages for the newly allocated block. */
- /********************************************************/
-
- for (j = start_page_for_remainder;
- (j < NUM_PAGES (best_index_size)); j++)
- {
- directory[0][remainder].
- logical_page[j - start_page_for_remainder] =
- directory[1][best_indexs_index].logical_page[j];
- }
-
- /*************************************************************/
- /* Set remainder's index to point to the new leftover piece. */
- /*************************************************************/
-
- directory[0][remainder].offset =
- (best_index_offset + size) % PAGE_SIZE;
-
- /*******************/
- /* Update dir_end. */
- /*******************/
-
- remainders_entry = remainder + page * DIR_ENTRIES_PER_PAGE;
- if (remainders_entry >= dir_end)
- dir_end = remainders_entry + 1;
-
- /********************************************************/
- /* If the leftover piece takes more logical pages than */
- /* it should (1 page / PAGE_SIZE) then we need to break */
- /* the remainder piece into two free blocks. */
- /********************************************************/
-
- size_mod_page_size = directory[0][remainder].size % PAGE_SIZE;
- if (size_mod_page_size >
- PAGE_SIZE - directory[0][remainder].offset)
- status = break_overlap (&remainders_entry);
-
- } /** if status PASSED **/
-
- } /** end if directory **/
-
- } /** end for remainder = dir_start **/
-
- index = 0;
-
- } /** end for page **/
-
- return (status);
-
- } /** end split_block() **/
-
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int find_new_dir_start (void) */
- /* */
- /* Description: */
- /* This function finds a new starting location in the */
- /* directory. This starting entry is used when looking for a */
- /* new block of memory. */
- /* */
- /* Note: We know the new starting location will always start */
- /* after the present one except when we free a block. In this */
- /* case, if the freed block's directory entry is before the */
- /* current starting entry, we set the starting location to that */
- /* of the newly freed block's directory entry. This is done in */
- /* effree(). */
- /* */
- /* Parameters: None */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: map_dir_page() */
- /* */
- /* Called by: check_best_fit() */
- /* */
- /* Globals referenced/modified: directory */
- /* directory_map */
- /* dir_page_count */
- /* dir_start */
- /* dir_end */
- /* */
- /**********************************************************************/
-
- unsigned int find_new_dir_start()
- {
- unsigned int i; /* Looping variable */
- unsigned int avail_entry_found; /* An available entry has been found */
- unsigned int dir_starts_page; /* Dir_start's dir entry's log page */
- unsigned int index; /* The current index into a page */
- unsigned int page; /* The current dir page mapped in */
- unsigned int status; /* Status of EMM and MEMLIB */
-
- /*******************************/
- /* Initialize local variables. */
- /*******************************/
-
- avail_entry_found = FALSE;
- status = PASSED;
-
- /***********************************************************/
- /* Convert dir_start + 1 to its respective directory page. */
- /***********************************************************/
-
- dir_starts_page = (dir_start + 1) / DIR_ENTRIES_PER_PAGE;
-
- /***************************************************************/
- /* Convert dir_start + 1 to its respective entry's page index. */
- /* We want to start the first page's index from one after the */
- /* current starting location. */
- /***************************************************************/
-
- index = (dir_start + 1) % DIR_ENTRIES_PER_PAGE;
-
- /****************************************************************/
- /* Go through all the directory pages starting with dir_start's */
- /* page until we find an usable entry. */
- /****************************************************************/
-
- for (page = dir_starts_page; ((page < dir_page_count) &&
- (!avail_entry_found) &&
- (status == PASSED)); page++)
- {
- /************************************************/
- /* Map in the directory page specified by page. */
- /************************************************/
-
- status = map_dir_page (page, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- /*****************************************************************/
- /* Go through this page's entries looking for to first available */
- /* entry. The first time we enter this loop we start with the */
- /* current starting location + 1 (converted to a page's index) */
- /* from above. All other index's after the first page will */
- /* start with 0. */
- /*****************************************************************/
-
- for (i = index; ((i < DIR_ENTRIES_PER_PAGE) &&
- (!avail_entry_found)); i++)
- {
- if (directory[0][i].token == UNASSIGNED_TOKEN)
- {
- /*****************************************/
- /* Translate the i index into an entry */
- /* into the full directory array for the */
- /* new starting location for dir_start. */
- /*****************************************/
-
- dir_start = i + page * DIR_ENTRIES_PER_PAGE;
-
- /***************************************/
- /* Make sure the new starting location */
- /* isn't greater than the end. If so, */
- /* than reset dir_end. */
- /***************************************/
-
- if (dir_start > dir_end)
- dir_end = dir_start + 1;
- avail_entry_found = TRUE;
- }
- } /** end for i **/
-
- } /** end if status PASSED **/
-
- index = 0;
-
- } /** end for page **/
-
- return (status);
-
- } /** end find_new_dir_start() **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int break_overlap (best_index) */
- /* unsigned int *best_index; */
- /* */
- /* Description: */
- /* This function breaks a free block into two parts at a page */
- /* boundry. This is done because check_best_fit() determined */
- /* that the requested block would overlap a page boundry */
- /* unnecessarily. For example, we don't want an 8K block using */
- /* two logical pages (part of it on one page and the rest on */
- /* another). Suppose we want to allocate a 9K block and */
- /* check_best_fit() determined that a 22K block (6K on one page, */
- /* 16K on the another) was the best fit. We want to start the 9K */
- /* block on a page boundry so that it will fit in one logical */
- /* page. This means that we eventually need to split the 22K */
- /* block into three pieces: */
- /* */
- /* 6K first free piece on the first logical page. */
- /* 9K allocated piece on the second logical page. */
- /* 7K free space on the second logical page. */
- /* */
- /* This routine will do the first split of 6K and 16K. The */
- /* function split_block(), called from efmalloc(), (which does */
- /* all the normal splitting) will split the 16K block into its 9K */
- /* allocated and 7K free pieces. */
- /* */
- /* Parameters: */
- /* output best_index The directory entry of the best fit loc */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: map_dir_page() */
- /* */
- /* Called by: efmalloc() */
- /* split_block() */
- /* */
- /* Globals referenced/modified: dir_page_count */
- /* directory */
- /* directory_map */
- /* dir_end */
- /* */
- /**********************************************************************/
-
- unsigned int break_overlap (best_index)
- unsigned int *best_index;
- {
- unsigned int i; /* Looping variable */
- unsigned int entry_found; /* Whether an entry was found */
- unsigned int free_space; /* The free space before a page */
- /* boundry in an overlaping block */
- unsigned int new_size; /* The free space starting on a page */
- /* boundry in an overlaping block */
- unsigned int status; /* Status of EMM and MEMLIB */
- unsigned int best_indexs_page; /* Best_index's dir entry's log page */
- unsigned int best_indexs_index; /* Best_index's index into its page */
- unsigned int page; /* Current directory page mapped in */
- unsigned int index; /* Index into a directory page */
- unsigned int j; /* Loop variable */
-
- status = PASSED;
-
- /****************************************************************/
- /* Check if we need to allocate another page for the directory. */
- /****************************************************************/
-
- if (dir_end >= (unsigned int) (NUM_DIR_ENTRIES (dir_page_count) - 2))
- status = allocate_new_directory_page();
-
- /******************************************************************/
- /* Convert best_index to its respective directory page and index. */
- /******************************************************************/
-
- best_indexs_page = *best_index / DIR_ENTRIES_PER_PAGE;
- best_indexs_index = *best_index % DIR_ENTRIES_PER_PAGE;
-
- /*******************************************/
- /* Map in the best_index's directory page. */
- /*******************************************/
-
- status = map_dir_page (best_indexs_page, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- /***************************************/
- /* Set sizes for breaking the overlap. */
- /***************************************/
-
- free_space = PAGE_SIZE - directory[0][best_indexs_index].offset;
- new_size = directory[0][best_indexs_index].size - free_space;
-
- /**********************************/
- /* Initialize variables for loop. */
- /**********************************/
-
- entry_found = FALSE;
- index = best_indexs_index;
-
- /****************************************************/
- /* Go through all the directory pages starting with */
- /* best_index's page until we find an usable entry. */
- /****************************************************/
-
- for (page = best_indexs_page; ((page < dir_page_count) &&
- (!entry_found) &&
- (status == PASSED)); page++)
- {
- /************************************************/
- /* Map in the directory page specified by page. */
- /************************************************/
-
- status = map_dir_page (page, SECOND_PHYS_PAGE);
- if (status == PASSED)
- {
- /********************************************************/
- /* Go through this page's entries looking for the first */
- /* available entry. The first time we enter this loop */
- /* we start with best_index's entry (converted to a */
- /* page's index from above). All other index's after */
- /* the first page will start with 0. */
- /********************************************************/
-
- for (i = index; ((i < DIR_ENTRIES_PER_PAGE) &&
- (!entry_found) &&
- (status == PASSED)); i++)
- {
- if ((directory[1][i].token == UNASSIGNED_TOKEN) &&
- (directory[1][i].size == 0))
- {
- /********************************************/
- /* We found a usable entry. Convert i to */
- /* a full directory entry for best_index. */
- /* Best_index will now point to this */
- /* directory entry though best_indexs_index */
- /* and best_indexs_page will still refer to */
- /* the original best_index. Set this */
- /* directory entry to point to the */
- /* allocated block. */
- /********************************************/
-
- *best_index = i + (page * DIR_ENTRIES_PER_PAGE);
- directory[1][i].token = *best_index;
- directory[1][i].size = new_size;
- directory[1][i].offset = 0;
-
- /*************************************/
- /* Set logical pages for this block. */
- /*************************************/
-
- for (j = 0; j < NUM_PAGES (new_size); j++)
- {
- directory[1][i].logical_page[j] =
- directory[0][best_indexs_index].logical_page[j + 1];
- }
-
- /***********************************/
- /* Update size for original block. */
- /***********************************/
-
- directory[0][best_indexs_index].size = free_space;
-
- /*****************************/
- /* Update dir_end if needed. */
- /*****************************/
-
- if (*best_index >= dir_end)
- dir_end = *best_index + 1;
-
- entry_found = TRUE;
-
- } /** end if directory[1][i] **/
-
- } /** end for i **/
-
- index = 0;
-
- } /** end if status PASSED **/
-
- } /** end for page **/
-
- } /** end if status PASSED **/
-
- return (status);
-
- } /** done break_overlap() **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int check_best_fit (size, best_index, */
- /* min_difference) */
- /* unsigned int size; */
- /* unsigned int *best_index; */
- /* long *min_difference; */
- /* */
- /* Description: */
- /* This function finds the best fit for a block of memory */
- /* asked for in efmalloc(). */
- /* */
- /* Parameters: */
- /* input size The desired size of the block of */
- /* memory. */
- /* output best_index The directory entry of the best fit */
- /* output min_difference The remainder from best_fit() */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: allocate_new_directory_page() */
- /* map_dir_page() */
- /* break_overlap() */
- /* find_new_dir_start() */
- /* */
- /* Called by: efmalloc() */
- /* */
- /* Globals referenced/modified: dir_page_count */
- /* directory */
- /* directory_map */
- /* dir_start */
- /* dir_end */
- /* */
- /**********************************************************************/
-
- unsigned int check_best_fit (size, best_index, min_difference)
- unsigned int size;
- unsigned int *best_index;
- long *min_difference;
- {
- unsigned int index; /* Index into a directory page */
- unsigned int status; /* Status of EMM and MEMLIB */
- unsigned int page; /* Directory page to map in */
- unsigned int size_mod_page_size; /* Size of block MOD PAGE_SIZE */
- unsigned int free_space; /* The free space before a page */
- /* boundry in a free block */
- unsigned int dir_starts_page; /* Dir_start's dir entry's log page */
- long this_ones_min_diff; /* Current block's min difference */
- unsigned int this_ones_offset; /* Current block's offset into a */
- /* logical page */
- long new_size; /* Free space after page boundry */
- unsigned int found_exact_fit; /* Whether we found an exact fit */
- unsigned int overlap; /* Whether we have an overlapping */
- /* block */
- long overlap_min_difference; /* Minimum difference for the */
- /* overlapping block */
-
- /************************************************/
- /* Initialize variables for best fit algorithm. */
- /************************************************/
-
- index = dir_start % DIR_ENTRIES_PER_PAGE;
- *best_index = UNASSIGNED_TOKEN;
- found_exact_fit = FALSE;
- overlap = FALSE;
- *min_difference = LARGEST_ALLOCATABLE_BLOCK;
- status = PASSED;
- overlap_min_difference = LARGEST_ALLOCATABLE_BLOCK;
- size_mod_page_size = size % PAGE_SIZE;
-
- if (size_mod_page_size == 0)
- size_mod_page_size = PAGE_SIZE;
-
- /**************************************************/
- /* Make sure a new directory page is allocated */
- /* before it is needed. This done so the a block */
- /* that has free mem will not be lost to the */
- /* the purple zone before a new directory page */
- /* is allocated in allocate_new_block(). */
- /* Allocate_new_directory_page() is called when */
- /* the current directory entries is two from */
- /* being filled up. */
- /**************************************************/
-
- if (dir_end >= (unsigned int) (NUM_DIR_ENTRIES (dir_page_count) - 2))
- status = allocate_new_directory_page();
-
- if (status == PASSED)
- {
- dir_starts_page = dir_start / DIR_ENTRIES_PER_PAGE;
-
- /*****************************************/
- /* Go through all of the directory pages */
- /* until we find an exact fit. */
- /*****************************************/
-
- for (page = dir_starts_page; ((page < dir_page_count) &&
- (!found_exact_fit) &&
- (status == PASSED)); page++)
- {
- /**********************************/
- /* Map in the this directory page */
- /**********************************/
-
- status = map_dir_page (page, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- /*********************************************************/
- /* Go through the current page looking for the best fit. */
- /*********************************************************/
-
- while ((index < DIR_ENTRIES_PER_PAGE) &&
- ((index + page * DIR_ENTRIES_PER_PAGE) <= dir_end) &&
- (!found_exact_fit))
- {
- /*****************************************/
- /* If this block of memory is available. */
- /*****************************************/
-
- if (directory[0][index].token == UNASSIGNED_TOKEN)
- {
- /************************************************/
- /* If size is 0 then this block is unallocated. */
- /************************************************/
-
- if (directory[0][index].size == 0)
- {
- /*********************************************/
- /* If best_index = UNASSIGNED_TOKEN we */
- /* haven't found any previous blocks to use. */
- /*********************************************/
-
- if (*best_index == UNASSIGNED_TOKEN)
- *best_index = index + (page * DIR_ENTRIES_PER_PAGE);
- }
- else
- {
- /************************************************/
- /* This is a previously freed block and we need */
- /* to check how close of a fit it is. */
- /************************************************/
-
- this_ones_min_diff = (long) directory[0][index].size - size;
- if ((this_ones_min_diff >= 0) &&
- (this_ones_min_diff < *min_difference))
- {
- /**************************************/
- /* If exact fit then take this block. */
- /**************************************/
-
- if (this_ones_min_diff == 0)
- {
- found_exact_fit = TRUE;
- *best_index = index + (page * DIR_ENTRIES_PER_PAGE);
- *min_difference = 0;
- overlap = FALSE;
- }
- else
- {
- /***********************************************/
- /* Make sure that putting the newly allocated */
- /* block at the beginning of the free block */
- /* won't cause the new block to overlap more */
- /* logical pages than it needs. */
- /* */
- /* If the remainder of the requested block */
- /* size MOD PAGE_SIZE will fit in the first */
- /* logical page of the freed block, then the */
- /* requested block will fit correctly. */
- /***********************************************/
-
- /*******************************************/
- /* Where this free block starts within its */
- /* first logical page. */
- /*******************************************/
-
- this_ones_offset = directory[0][index].offset;
-
- /********************************************/
- /* The room left on the first logical page. */
- /********************************************/
-
- free_space = PAGE_SIZE - this_ones_offset;
-
- if (free_space >= size_mod_page_size)
- {
- /******************************************/
- /* The block will fit just fine. We will */
- /* have the block itself and a remainder. */
- /******************************************/
-
- *best_index = index + (page * DIR_ENTRIES_PER_PAGE);
- *min_difference = this_ones_min_diff;
- overlap = FALSE;
- }
- else
- {
- /********************************************/
- /* The new block will fit but we have to */
- /* start it on this free block's first page */
- /* boundry. We will need to keep track of */
- /* the space before the page boundry, the */
- /* new block, and any remainder from the */
- /* new block. We will have an overlap to */
- /* break. */
- /********************************************/
-
- new_size = (long) directory[0][index].size - free_space;
- if (new_size >= size)
- {
- overlap = TRUE;
- this_ones_min_diff = new_size - size;
- if (this_ones_min_diff < overlap_min_difference)
- {
- overlap_min_difference = new_size - size;
- *best_index = index + (page * DIR_ENTRIES_PER_PAGE);
- }
- }
- } /** end else **/
-
- } /** end else **/
-
- } /** end if temp_difference ... **/
-
- } /** end else **/
-
- } /** end if directory **/
-
- index++;
-
- } /** end while **/
-
- } /** end if passed **/
- index = 0;
-
- } /** end if page **/
-
- /**********************************************/
- /* If we have an overlap we need to break it. */
- /**********************************************/
-
- if ((overlap) &&
- (status == PASSED))
- {
- *min_difference = overlap_min_difference;
- status = break_overlap (best_index);
- }
-
- /****************************************************/
- /* Update our starting entry if the current one == */
- /* to best_index and we don't have an overlap. */
- /****************************************************/
-
- if ((dir_start == *best_index) &&
- (!overlap) &&
- (status == PASSED))
- status = find_new_dir_start();
-
- /**************************************/
- /* Update our ending entry if needed. */
- /**************************************/
-
- if ((*best_index >= dir_end) &&
- (status == PASSED))
- dir_end = *best_index + 1;
-
- } /** end if passed **/
-
- return (status);
-
- } /* end check_best_fit() */
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int check_if_all_blocks_free (all_blocks_free) */
- /* unsigned int *all_blocks_free; */
- /* */
- /* Description: */
- /* If the block being freed by effree() is the last one to be */
- /* freed then we need to deallocate all the pages allocated to */
- /* this application. This tells us that the program using MEMLIB */
- /* may be terminating and we want to be sure that all pages for */
- /* this application have been deallocated. This function will */
- /* see if there are any blocks left in the directory that are */
- /* allocated and if not, will deallocate all pages that this */
- /* application owns. */
- /* */
- /* Parameters: */
- /* output free_status TRUE - all blocks are free */
- /* FALSE - there are some blocks used */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: map_dir_page() */
- /* */
- /* Called by: effree() */
- /* */
- /* Globals referenced/modified: dir_page_count */
- /* directory */
- /* directory_map */
- /* */
- /**********************************************************************/
-
- unsigned int check_if_all_blocks_free (all_blocks_free)
- unsigned int *all_blocks_free;
- {
- unsigned int status; /* Status of EMM and MEMLIB */
- unsigned int page; /* Current directory page mapped in */
- unsigned int index; /* Current index into a logical page */
-
- /******************************/
- /* Assume all blocks are free */
- /* and status OK. */
- /******************************/
-
- *all_blocks_free = TRUE;
- status = PASSED;
-
- /**************************************************************/
- /* Loop through the directory, checking for non-freed blocks. */
- /**************************************************************/
-
- for (page = 0; ((page < dir_page_count) &&
- (*all_blocks_free) &&
- (status == PASSED)); page++)
- {
- /*******************************/
- /* Map in this directory page. */
- /*******************************/
-
- status = map_dir_page (page, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- /************************************/
- /* Check all index's for this page. */
- /************************************/
-
- for (index = 0; ((index < DIR_ENTRIES_PER_PAGE) &&
- (*all_blocks_free)); index++)
- {
- if (directory[0][index].token != UNASSIGNED_TOKEN)
- {
- /**********************************************/
- /* If we find a block that's being used, set */
- /* all_block_free to FALSE and stop checking. */
- /**********************************************/
-
- *all_blocks_free = FALSE;
- }
- } /** end for index **/
-
- } /** end if status PASSED **/
-
- } /** end for page **/
-
- return (status);
-
- } /** end if_all_blocks_free **/
-
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int coalesce_block (block1, block2, coalasce) */
- /* unsigned int block1; */
- /* unsigned int block2; */
- /* unsigned int *coalesce; */
- /* */
- /* Description: */
- /* This coalesces one block of free expanded memory (block1) */
- /* to another (block2). */
- /* */
- /* Parameters: */
- /* input block1 The identifier for the first block. */
- /* block2 The identifier for the second block. */
- /* output coalesce Whether we really coalesced or not. */
- /* */
- /* Results returned: */
- /* PASSED Coalescing successful or not needed */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: map_dir_page() */
- /* get_context() */
- /* set_context() */
- /* */
- /* Called by: search_before() */
- /* search_after() */
- /* */
- /* Globals referenced/modified: directory */
- /* directory_map */
- /* */
- /**********************************************************************/
-
- unsigned int coalesce_block (block1, block2, coalesce)
- unsigned int block1;
- unsigned int block2;
- unsigned int *coalesce;
- {
- unsigned int j; /* Looping variable */
- unsigned int block1s_page; /* Block1's directory entry's log page */
- unsigned int block1s_index; /* Block1's index into its logical page */
- unsigned int block2s_page; /* Block2's directory entry's log page */
- unsigned int block2s_index; /* Block2's index into its logical page */
- unsigned int end_of_block2; /* End of block2 (size+offset) */
- unsigned int start_page; /* Starting logical page for coalescing */
- unsigned int status; /* Status of EMM and MEMLIB */
- CONTEXT_STRUCT context; /* For storing the current context */
-
- /******************************************************************/
- /* We need to continue where we left off from when we return */
- /* to search_before() or search_after(), so we need to save */
- /* the pages they had mapped in before they called this function. */
- /******************************************************************/
-
- status = get_context (&context);
- if (status == PASSED)
- {
- /**************************************************************/
- /* Convert block1 to its respective directory page and index. */
- /**************************************************************/
-
- block1s_page = block1 / DIR_ENTRIES_PER_PAGE;
- block1s_index = block1 % DIR_ENTRIES_PER_PAGE;
-
- /***********************************/
- /* Map in block1's directory page. */
- /***********************************/
-
- status = map_dir_page (block1s_page, FIRST_PHYS_PAGE);
- }
-
- if (status == PASSED)
- {
- /*********************************************************/
- /* Convert block1 to its respective directory page and */
- /* index. We're going to map this page into the second */
- /* physical page. In order to access this pages entries */
- /* we need to offset its indexes by DIR_ENTRIES_PER_PAGE */
- /* from the beginning of the first physical page. */
- /*********************************************************/
-
- block2s_page = block2 / DIR_ENTRIES_PER_PAGE;
- block2s_index = block2 % DIR_ENTRIES_PER_PAGE;
-
- /*****************************************************/
- /* Map in block2's directory page using the */
- /* directory_map's second array element to map this */
- /* page in at physical page one while keeping */
- /* block1's directory page at physical page zero. */
- /*****************************************************/
-
- status = map_dir_page (block2s_page, SECOND_PHYS_PAGE);
-
- /****************************/
- /* Coalesce the two blocks. */
- /****************************/
-
- if (status == PASSED)
- {
- /****************************************/
- /* Assume we will coalesce these blocks */
- /****************************************/
-
- *coalesce = TRUE;
-
- /*********************************************/
- /* Set the starting logical page for block2. */
- /*********************************************/
-
- end_of_block2 = (directory[1][block2s_index].offset +
- directory[1][block2s_index].size) % PAGE_SIZE;
-
- if (end_of_block2 == 0)
- start_page = NUM_PAGES (directory[1][block2s_index].size);
- else
- start_page = NUM_PAGES (directory[1][block2s_index].size) - 1;
-
- /********************************************************/
- /* If combining the blocks would cause too many logical */
- /* pages to be used, DON'T coalesce them. */
- /********************************************************/
-
- if ((start_page + NUM_PAGES (directory[0][block1s_index].size))
- >= MAX_ALLOCATABLE_PAGES)
- *coalesce = FALSE;
-
- if (*coalesce)
- {
-
- /*****************************************************/
- /* Combine the logical pages for block1 into block2. */
- /*****************************************************/
-
- for (j = 0; j < NUM_PAGES (directory[0][block1s_index].size); j++)
- {
- directory[1][block2s_index].logical_page[start_page + j] =
- directory[0][block1s_index].logical_page[j];
- }
-
- /******************************************/
- /* Set block2's size to the combined size */
- /* and zero out block 1. */
- /******************************************/
-
- directory[1][block2s_index].size += directory[0][block1s_index].size;
- directory[0][block1s_index].size = 0;
-
- }
- }
- }
-
- /************************************/
- /* Restore the pages that were here */
- /* before this function was called. */
- /************************************/
-
- if (status == PASSED)
- status = set_context (&context);
-
- return (status);
-
- } /** end coalesce_block() **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int search_after (token, final_entry, */
- /* usable_entry) */
- /* unsigned int token; */
- /* unsigned int *final_entry; */
- /* unsigned int *usable_entry; */
- /* */
- /* Description: */
- /* This function searches for a free block of memory after the */
- /* block of memory we just freed. This is done in order to */
- /* coalesce the two blocks. */
- /* */
- /* Parameters: */
- /* input token The token of the block of memory */
- /* that's been freed */
- /* output final_entry The directory entry of the final */
- /* coalesced block or unassigned if no */
- /* blocks were found. */
- /* usable_entry The directory entry of a usable block */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: coalesce_block() */
- /* map_dir_page() */
- /* */
- /* Called by: effree() */
- /* */
- /* Globals referenced/modified: directory */
- /* directory_map */
- /* dir_page_count */
- /* */
- /**********************************************************************/
-
- unsigned int search_after (token, final_entry, usable_entry)
- unsigned int token;
- unsigned int *final_entry;
- unsigned int *usable_entry;
- {
- unsigned int index; /* Index into a directory page */
- unsigned int indexs_entry; /* Index translated to a full dir entry*/
- unsigned int coalesce; /* Whether we should coalesce or not */
- unsigned int tokens_last_page; /* Last logical page for token's block */
- unsigned int end_of_tokens_block;/* The end of token's block */
- unsigned int page; /* Directory pages to loop through */
- unsigned int tokens_page; /* Token's directory entry's log page */
- unsigned int tokens_index; /* Token's index into its logical page */
- unsigned int status; /* Status of EMM and MEMLIB */
-
- /****************************************************************/
- /* Convert the token passed in to its respective directory page */
- /* and index. We're going to map this page into the second */
- /* physical page. In order to access this pages entries we */
- /* need to use second_dir_page. */
- /****************************************************************/
-
- tokens_page = token / DIR_ENTRIES_PER_PAGE;
- tokens_index = token % DIR_ENTRIES_PER_PAGE;
-
- /*********************************************************/
- /* Map in the token's directory page using the */
- /* directory_map's second array element to map this page */
- /* in at physical page one while keeping the block to be */
- /* coalesced's directory page at physical page zero. */
- /*********************************************************/
-
- status = map_dir_page (tokens_page, SECOND_PHYS_PAGE);
- if (status == PASSED)
- {
- /**********************************/
- /* Find the end of token's block. */
- /**********************************/
-
- end_of_tokens_block = (directory[1][tokens_index].size +
- directory[1][tokens_index].offset) % PAGE_SIZE;
-
- /**************************/
- /* Set variables for loop */
- /**************************/
-
- *final_entry = UNASSIGNED_TOKEN;
- tokens_last_page = NUM_PAGES (directory[1][tokens_index].size) - 1;
- coalesce = FALSE;
-
- /******************************************************/
- /* Search for a free block of memory after this block */
- /* to coalesce into one free block. */
- /******************************************************/
-
- for (page = 0; ((page < dir_page_count) &&
- (status == PASSED) &&
- (!coalesce)); page++)
- {
- /*******************************/
- /* Map in this directory page. */
- /*******************************/
-
- status = map_dir_page (page, FIRST_PHYS_PAGE);
- /*********************************************/
- /* Go through all the indexes for this page. */
- /*********************************************/
-
- for (index = 0; ((index < DIR_ENTRIES_PER_PAGE) &&
- (status == PASSED) &&
- (!coalesce)); index++)
- {
- /********************************************/
- /* Convert index to a full directory entry. */
- /********************************************/
-
- indexs_entry = index + page * DIR_ENTRIES_PER_PAGE;
-
- /*********************************************************/
- /* For index's block test: */
- /* Is it free? */
- /* Is it > 0? */
- /* Is it different than the block we called effree with? */
- /* Would its size make a coalesced block > 64K? */
- /*********************************************************/
-
- if ((directory[0][index].token == UNASSIGNED_TOKEN) &&
- (directory[0][index].size > 0) &&
- (indexs_entry != token) &&
- ((unsigned long) directory[0][index].size +
- directory[1][tokens_index].size < K64K))
- {
- /****************************************************/
- /* If the end of token's block equals the beginning */
- /* of index's block then index's block could lie */
- /* AFTER our block. */
- /****************************************************/
-
- if (end_of_tokens_block == directory[0][index].offset)
- {
- /******************************************************/
- /* Test the logical pages for these two blocks to */
- /* see if we want to coalesce them. We will coalesce */
- /* if either of the following is true: */
- /* */
- /* 1. If the token's block ends on an exact page */
- /* boundry (end_of_tokens_block == 0) then we do */
- /* NOT want the last logical page of token's block */
- /* to match the first logical page of index's */
- /* block. */
- /* */
- /* 2. If token's block ends in the middle of a */
- /* logical page (end_of_tokens_block != 0) the we */
- /* DO want token's block's last logical page to */
- /* match index's block's first logical page. */
- /******************************************************/
-
- if (end_of_tokens_block == 0)
- {
- if (directory[1][tokens_index].logical_page[tokens_last_page]
- != directory[0][index].logical_page[0])
- {
- coalesce = TRUE;
- }
- }
- else
- {
- if (directory[1][tokens_index].logical_page[tokens_last_page]
- == directory[0][index].logical_page[0])
- {
- coalesce = TRUE;
- }
- }
- if (coalesce)
- {
- /************************************/
- /* We've got a winner! Coalesce the */
- /* i'th block into our block. */
- /************************************/
-
- status = coalesce_block (indexs_entry, token, &coalesce);
-
- if ((status == PASSED) && coalesce)
- {
- *final_entry = token;
- *usable_entry = indexs_entry;
- }
-
- } /** end if coalesce **/
-
- } /** end if end_of_tokens_block **/
-
- } /** end if directory **/
-
- } /** end for index **/
-
- } /** end for page **/
-
- } /** end if PASSED **/
-
- return (status);
-
- } /** end search_after() **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int search_before (token, final_entry, */
- /* usable_entry) */
- /* unsigned int token; */
- /* unsigned int *final_entry; */
- /* unsigned int *usable_entry; */
- /* */
- /* Description: */
- /* This function searches for a free block of memory before */
- /* the block of memory we just freed. This is done in order to */
- /* coalesce the two blocks. */
- /* */
- /* Parameters: */
- /* input token The token of the block of memory */
- /* that's been freed */
- /* output final_entry The directory entry of the final */
- /* coalesced block or unassigned if no */
- /* blocks were found. */
- /* temp_entry The directory entry of a usable block */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calls: coalesce_block() */
- /* map_dir_page() */
- /* */
- /* Called by: effree() */
- /* */
- /* Globals referenced/modified: directory */
- /* directory_map */
- /* dir_page_count */
- /* */
- /**********************************************************************/
-
- unsigned int search_before (token, final_entry, usable_entry)
- unsigned int token;
- unsigned int *final_entry;
- unsigned int *usable_entry;
- {
- unsigned int index; /* Index into a directory page */
- unsigned int indexs_entry; /* Index translated to a full dir entry */
- unsigned int indexs_last_page; /* Last logical page for index's block */
- unsigned int coalesce; /* Whether we should coalesce or not */
- unsigned int end_of_indexs_block;/* The end of token's block */
- unsigned int page; /* Directory pages to loop through */
- unsigned int tokens_page; /* Token's directory entry's log page */
- unsigned int tokens_index; /* Token's index into its logical page */
- unsigned int status; /* Status of EMM and MEMLIB */
-
- /****************************************************************/
- /* Convert the token passed in to its respective directory page */
- /* and index. We're going to map this page into the second */
- /* physical page. In order to access this page's entries we */
- /* need to use directory[1]. */
- /****************************************************************/
-
- tokens_page = token / DIR_ENTRIES_PER_PAGE;
- tokens_index = token % DIR_ENTRIES_PER_PAGE;
-
- /*********************************************************/
- /* Map in the token's directory page using the */
- /* directory_map's second array element to map this page */
- /* in at physical page one while keeping the block to be */
- /* coalesced's directory page at physical page zero. */
- /*********************************************************/
-
- status = map_dir_page (tokens_page, SECOND_PHYS_PAGE);
- if (status == PASSED)
- {
- /***************************/
- /* Set variables for loop. */
- /***************************/
-
- coalesce = FALSE;
-
- /*************************************************/
- /* Search for a free block of memory before this */
- /* block to coalesce into one free block. */
- /*************************************************/
-
- for (page = 0; ((page < dir_page_count) &&
- (status == PASSED) &&
- (!coalesce)); page++)
- {
- /*******************************/
- /* Map in this directory page. */
- /*******************************/
-
- status = map_dir_page (page, FIRST_PHYS_PAGE);
-
- /*********************************************/
- /* Go through all the indexes for this page. */
- /*********************************************/
-
- for (index = 0; ((index < DIR_ENTRIES_PER_PAGE) &&
- (status == PASSED) &&
- (!coalesce)); index++)
- {
- /********************************************/
- /* Convert index to a full directory entry. */
- /********************************************/
-
- indexs_entry = index + page * DIR_ENTRIES_PER_PAGE;
-
- /*********************************************************/
- /* For index's block test: */
- /* Is it free? */
- /* Is it > 0? */
- /* Is it different than the block we called effree with? */
- /* Would its size make a coalesced block > 64K? */
- /*********************************************************/
-
- if ((directory[0][index].token == UNASSIGNED_TOKEN) &&
- (directory[0][index].size > 0) &&
- (indexs_entry != token) &&
- ((unsigned long) directory[0][index].size +
- directory[1][tokens_index].size < K64K))
- {
- end_of_indexs_block = (directory[0][index].offset +
- directory[0][index].size) % PAGE_SIZE;
-
- indexs_last_page = NUM_PAGES (directory[0][index].size) - 1;
-
-
- /*********************************************/
- /* If the beginning of token's block exactly */
- /* matches the end of index's block then */
- /* index's block could lie BEFORE our block. */
- /*********************************************/
-
- if (directory[1][tokens_index].offset == end_of_indexs_block)
- {
- /******************************************************/
- /* Test the logical pages for these two blocks to */
- /* see if we want to coalesce them. We will coalesce */
- /* if either of the following is true: */
- /* */
- /* 1. If the token's block ends on an exact page */
- /* boundry (end_of_indexs_block == 0) then we do */
- /* NOT want the first logical page of token's */
- /* block to match the last logical page of index's */
- /* block. */
- /* */
- /* 2. If token's block ends in the middle of a */
- /* logical page (end_of_indexs_block != 0) the we */
- /* DO want token's block's first logical page to */
- /* match index's block's last logical page. */
- /******************************************************/
-
- if (end_of_indexs_block == 0)
- {
- if (directory[0][index].logical_page[indexs_last_page] !=
- directory[1][tokens_index].logical_page[0])
- {
- coalesce = TRUE;
- }
- }
- else
- {
- if (directory[0][index].logical_page[indexs_last_page] ==
- directory[1][tokens_index].logical_page[0])
- {
- coalesce = TRUE;
- }
- }
- if (coalesce)
- {
- /************************************/
- /* We've got a winner! Coalesce the */
- /* i'th block into our block. */
- /************************************/
-
- status = coalesce_block (token, indexs_entry, &coalesce);
-
- if ((status == PASSED) &&
- coalesce)
- {
- *final_entry = indexs_entry;
- *usable_entry = token;
- }
-
- } /** end if coalesce **/
-
- } /** end if directory **/
-
- } /** end if directory **/
-
- } /** end for index = 0 **/
-
- } /** end for page **/
-
- } /** end if PASSED **/
-
- return (status);
- } /** end search_before() **/
-
-
-
-
-