home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************/
- /* */
- /* Module: MEMLIB.C */
- /* */
- /* This module contains the C MEMORY MANAGER - a group of C */
- /* callable routines that manage expanded memory. These */
- /* routines alleviate many of the housekeeping chores necessary */
- /* when dealing with expanded memory and make allocating and */
- /* freeing expanded memory look as much like allocating and */
- /* freeing conventional memory as possible. */
- /* */
- /* The routines called by an application are: */
- /* */
- /* ememavl Approximate amount of free expanded memory */
- /* ememmax Size of the largest contiguous free block */
- /* emsize Size of a specified block */
- /* efmalloc Allocate a block of memory */
- /* effree Free a previously allocated block */
- /* seteptrs Access n different blocks */
- /* set1eptr Access 1 block */
- /* set2eptrs Access 2 blocks */
- /* set3eptrs Access 3 blocks */
- /* push_context Push the current mapping context */
- /* pop_context Pop a mapping context */
- /* effreeall Frees ALL blocks */
- /* */
- /**********************************************************************/
-
- #include "memintrl.c"
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int ememavl (*size) */
- /* unsigned long *size; */
- /* */
- /* Description: */
- /* Computes the size of expanded memory available in bytes but */
- /* due to memory fragmentation, the largest useable block may be */
- /* smaller than the amount returned by this function. See */
- /* ememmax. */
- /* */
- /* Parameters: */
- /* output size The size computed. */
- /* */
- /* Results returned: */
- /* PASSED The size is valid */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* unsigned long size; */
- /* unsigned int status; */
- /* ... */
- /* status = ememavl (&size); */
- /* if (status == PASSED) */
- /* printf("Expanded memory available = %lu \n", size); */
- /* else */
- /* { error condition } */
- /* */
- /* Calls: prepare_dir_mapping() */
- /* get_unalloc_page_count() */
- /* restore_memlib_context() */
- /* map_dir_page() */
- /* */
- /* Called by: Application */
- /* */
- /* Globals referenced/modified: directory */
- /* dir_page_count */
- /* */
- /**********************************************************************/
-
- unsigned int ememavl (size)
- unsigned long *size;
- {
- unsigned int status; /* The status of EMM and MEMLIB */
- unsigned int num_unalloc_pages; /* Number of unallocated pages */
- unsigned int index; /* Index into a directory page */
- unsigned int dir_page; /* The directory page to map in */
- unsigned int context_saved; /* Whether the contexted was saved */
-
- *size = 0;
-
- /**********************************************/
- /* Call prepare_dir_mapping() to save context */
- /* before mapping in the directory. */
- /**********************************************/
-
- status = prepare_dir_mapping (&context_saved);
-
- if (status == PASSED)
- {
- /********************************************************/
- /* Add up the number of 16K pages that are unallocated. */
- /********************************************************/
-
- status = get_unalloc_page_count (&num_unalloc_pages);
- if (status == PASSED)
- {
- *size += PAGE_SIZE * (long) num_unalloc_pages;
- }
-
- /***************************************************/
- /* Go through entire directory one page at a time. */
- /***************************************************/
-
- for (dir_page = 0; ((status == PASSED) &&
- (dir_page < dir_page_count)); dir_page++)
- {
- /***********************************/
- /* Map in the this directory page. */
- /***********************************/
-
- status = map_dir_page (dir_page, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- /******************************************/
- /* Add up all freed blocks for this page. */
- /******************************************/
-
- for (index = 0; (index < DIR_ENTRIES_PER_PAGE); index++)
- {
- if (directory[0][index].token == UNASSIGNED_TOKEN)
- *size += directory[0][index].size;
- }
- }
- }
- }
- /**************************************************************/
- /* Unmap the directory - remap the pages that were in before. */
- /**************************************************************/
-
- if (context_saved)
- status = restore_memlib_context (status);
-
- /*************************************/
- /* If some error return a size of 0. */
- /*************************************/
-
- if (status != PASSED)
- *size = 0;
-
- return (status);
-
- } /** end of ememavl **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int ememmax (*size) */
- /* unsigned int *size; */
- /* */
- /* Description: */
- /* Computes the size of the largest block of expanded memory */
- /* that MEMLIB can allocate. */
- /* */
- /* Parameters: */
- /* output size The size of the largest allocatable block. */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* unsigned int size; */
- /* unsigned int status; */
- /* ... */
- /* status = ememmax (&size); */
- /* if (status == PASSED) */
- /* printf("Largest block available = %u \n", size); */
- /* else */
- /* { error condition } */
- /* */
- /* Calls: prepare_dir_mapping() */
- /* map_dir_page() */
- /* get_unalloc_page_count() */
- /* restore_memlib_context() */
- /* */
- /* Called by: Application */
- /* */
- /* Globals referenced/modified: directory */
- /* dir_page_count */
- /* */
- /**********************************************************************/
-
- unsigned int ememmax (size)
- unsigned int *size;
- {
- unsigned int status; /* The status of EMM and MEMLIB */
- unsigned int num_pages; /* Number of unallocated pages */
- unsigned int page; /* Directory page to map in */
- unsigned int index; /* Index into a directory page */
- unsigned int saved; /* whether the context was saved */
-
- /**********************************************/
- /* Call prepare_dir_mapping() to save context */
- /* before mapping in the directory */
- /**********************************************/
-
- status = prepare_dir_mapping (&saved);
-
- if (status == PASSED)
- {
- /***************************************************************/
- /* If more than 64K worth of unallocated pages, set max to */
- /* the largest allocateable block (64K-1). Otherwise, test */
- /* the number of unallocated pages * 16K against *size. */
- /***************************************************************/
-
- status = get_unalloc_page_count (&num_pages);
- if (status == PASSED)
- {
- if (num_pages >= MAX_ALLOCATABLE_PAGES)
- *size = LARGEST_ALLOCATABLE_BLOCK;
- else
- *size = PAGE_SIZE * num_pages;
- }
- }
-
- /**************************************/
- /* Go through all the directory pages */
- /**************************************/
-
- for (page = 0; ((status == PASSED) &&
- (page < dir_page_count)); page++)
- {
- /***********************************/
- /* Map in the this directory page. */
- /***********************************/
-
- status = map_dir_page (page, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- /********************************/
- /* Find the maximum free block. */
- /********************************/
-
- for (index = 0; index < DIR_ENTRIES_PER_PAGE; index++)
- {
- if ((directory[0][index].token == UNASSIGNED_TOKEN) &&
- (directory[0][index].size > *size))
- *size = directory[0][index].size;
- }
- }
- }
-
- /**************************************************************/
- /* Unmap the directory - remap the pages that were in before. */
- /**************************************************************/
-
- if (saved)
- status = restore_memlib_context (status);
-
- /*************************************/
- /* If some error return a size of 0. */
- /*************************************/
-
- if (status != PASSED)
- *size = 0;
-
- return (status);
-
- } /** end of ememmax **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int emsize (token, *size) */
- /* unsigned int token; */
- /* unsigned int *size; */
- /* */
- /* Description: */
- /* Returns the size, in bytes, of the allocated block of */
- /* memory identified by 'token.' (A token returned from */
- /* efmalloc). */
- /* */
- /* Parameters: */
- /* input token identifies the block desired */
- /* output size the size, in bytes, of the block */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* unsigned int status; */
- /* unsigned int token; */
- /* unsigned int size; */
- /* */
- /* status = efmalloc (200, &token); */
- /* ... */
- /* status = emsize (token, &size); */
- /* if (status == PASSED) */
- /* printf ("Size of block = %u bytes\n", size); */
- /* */
- /* Calls: prepare_dir_mapping() */
- /* map_dir_page() */
- /* check_token() */
- /* restore_memlib_context() */
- /* */
- /* Called by: Application */
- /* */
- /* Globals referenced/modified: directory */
- /* */
- /**********************************************************************/
-
- unsigned int emsize (token, size)
- unsigned int token;
- unsigned int *size;
- {
- unsigned int status; /* The status of EMM and MEMLIB */
- unsigned int page; /* Directory page to map in */
- unsigned int index; /* The index into a directory page */
- unsigned int context_saved; /* Whether the context was saved */
-
- /**********************************************/
- /* Call prepare_dir_mapping() to save context */
- /* before mapping in the directory */
- /**********************************************/
-
- status = prepare_dir_mapping (&context_saved);
-
- /***************************/
- /* Check for a valid token */
- /***************************/
-
- if (status == PASSED)
- status = check_token (token);
-
- if (status == PASSED)
- {
- /*****************************************************/
- /* Set 'page' to the directory page this token is in */
- /*****************************************************/
-
- page = token / DIR_ENTRIES_PER_PAGE;
-
- /**********************************************/
- /* Convert the token into an index that falls */
- /* within the size of a directory page */
- /**********************************************/
-
- index = token % DIR_ENTRIES_PER_PAGE;
-
- /******************************/
- /* Map in this directory page */
- /******************************/
-
- status = map_dir_page (page, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- /*****************************/
- /* Check size for this index */
- /*****************************/
-
- if (directory[0][index].token == token)
- {
- *size = directory[0][index].size;
- status = PASSED;
- }
- else
- {
- *size = 0;
- status = INVALID_TOKEN;
- }
- }
- }
-
- /*************************************************************/
- /* Unmap the directory - remap the pages that were in before */
- /*************************************************************/
-
- if (context_saved)
- status = restore_memlib_context (status);
-
- /************************************/
- /* If some error return a size of 0 */
- /************************************/
-
- if (status != PASSED)
- *size = 0;
-
- return (status);
-
- } /** end of emsize **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int efmalloc (size, token); */
- /* unsigned int size; */
- /* unsigned int *token; */
- /* */
- /* Description: */
- /* This function is analagous to fmalloc except it allocates a */
- /* block of memory from the expanded memory pool. */
- /* */
- /* Parameters: */
- /* input size The desired size, in bytes, of the block of */
- /* memory. */
- /* output token A tag needed for subsequent calls to the C */
- /* Memory Manager to unquiely identify the */
- /* block of memory allocated. */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* unsigned int token; */
- /* unsigned int size; */
- /* unsigned int status */
- /* ... */
- /* size = 100; */
- /* status = efmalloc (size, &token); */
- /* if (status == PASSED) */
- /* { continue normal code - we have allocated space to } */
- /* { store 100 byte values } */
- /* else */
- /* { error condition } */
- /* */
- /* Calls: allocate_new_block() */
- /* check_best_fit() */
- /* prepare_dir_mapping() */
- /* restore_memlib_context() */
- /* split_block() */
- /* map_dir_page() */
- /* */
- /* Called by: Application */
- /* */
- /* Globals reference/modified: directory */
- /* directory_map */
- /* */
- /**********************************************************************/
-
- unsigned int efmalloc (size, token)
- unsigned int size;
- unsigned int *token;
-
- {
- unsigned int found_block; /* memory block found */
- 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 best_index; /* Index of the current best fit */
- unsigned int context_saved; /* whether the context was saved */
- long min_difference; /* Minimum difference - best size */
-
- /**********************************************/
- /* Attempting to allocate 0 bytes is an error */
- /**********************************************/
-
- if (size > 0)
- status = PASSED;
- else
- status = REQUEST_FOR_ZERO_LENGTH_BLOCK;
-
- /**********************************************/
- /* Call prepare_dir_mapping() to save context */
- /* before mapping in the directory */
- /**********************************************/
-
- if (status == PASSED)
- status = prepare_dir_mapping (&context_saved);
-
- if (status == PASSED)
- {
- /*************************************/
- /* check to see if there exists a */
- /* "best size" fit in memory blocks. */
- /*************************************/
-
- status = check_best_fit (size, &best_index, &min_difference);
-
- /********************************************/
- /* If best_index is not an UNASSIGNED_TOKEN */
- /* then we found a block. */
- /********************************************/
-
- if ((status == PASSED) &&
- (best_index != UNASSIGNED_TOKEN))
- {
- found_block = TRUE;
-
- /****************************************************/
- /* We're going to use a free block to put our block */
- /* into. First we need to map in the free block's */
- /* (best_index) directory entry's logical 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 best_index's directory page. */
- /***************************************/
-
- status = map_dir_page (best_indexs_page, FIRST_PHYS_PAGE);
-
-
- /********************************************************/
- /* If the size of the best fit that we found was 0 then */
- /* what we found was an unallocated block. Allocate a */
- /* a new block. */
- /********************************************************/
-
- if (directory[0][best_indexs_index].size == 0)
- status = allocate_new_block (size, best_index);
- else
- {
- /******************************************************/
- /* When using a previously allocated block we need to */
- /* check the size and if any space is left over we */
- /* should make a new available block. */
- /******************************************************/
-
- if ((status == PASSED) &&
- (min_difference != 0))
- {
- status = split_block (best_index, size);
- }
-
- } /** end else **/
-
- } /** end if best_index ... **/
-
- } /** end if passed from prepare_dir_mapping() **/
-
- /********************************************************/
- /* We found a block - set the token value and directory */
- /* entries. (The directory pointer (offset) is set */
- /* either in allocate_new_block or was already valid.) */
- /********************************************************/
- if (status == PASSED)
- {
- if (found_block)
- {
- status = map_dir_page (best_indexs_page, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- *token = best_index;
- directory[0][best_indexs_index].token = best_index;
- directory[0][best_indexs_index].size = size;
- }
- }
- else
- {
- *token = UNASSIGNED_TOKEN;
- if (!found_block)
- status = TOO_MANY_DIRECTORY_ENTRIES;
- }
- }
-
- /*************************************************************/
- /* Unmap the directory - remap the pages that were in before */
- /*************************************************************/
-
- if (context_saved)
- status = restore_memlib_context (status);
-
- return (status);
-
- } /** end efmalloc **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int effree (token) */
- /* unsigned int token; */
- /* */
- /* Description: */
- /* This function frees a block of memory from expanded memory */
- /* that was allocated by efmalloc(). */
- /* */
- /* Parameters: */
- /* input token The token returned by efmalloc when this */
- /* block was allocated. */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* unsigned int token; */
- /* unsigned int status; */
- /* ... */
- /* status = efmalloc (100, &token); */
- /* ... */
- /* status = efree(token); */
- /* if (status == PASSED) */
- /* { continue normal code } */
- /* else */
- /* { error condition } */
- /* */
- /* Calls: check_if_all_blocks_free() */
- /* check_token() */
- /* prepare_dir_mapping() */
- /* restore_memlib_context() */
- /* search_after() */
- /* search_before() */
- /* map_dir_page() */
- /* effreeall() */
- /* */
- /* Called by: Application */
- /* */
- /* Globals referenced/modified: directory */
- /* dir_start */
- /* */
- /**********************************************************************/
-
- unsigned int effree (token)
- unsigned int token;
- {
- unsigned int status; /* Status of EMM and MEMLIB */
- unsigned int all_blocks_free; /* Whether all blocks are free or not */
- unsigned int j; /* Looping variable */
- unsigned int usable_entry; /* A usuable directory entry */
- unsigned int size_mod_page_size; /* Size of a block MOD PAGE_SIZE */
- unsigned int tokens_index; /* Token's index into its log page */
- unsigned int tokens_page; /* Token's dir entry's logical page */
- unsigned int usable_entrys_index;/* Usable_entry's index into its page */
- unsigned int usable_entrys_page; /* Usable_entry's dir entry's log page*/
- unsigned int final_entrys_index; /* Final_entry's index into its page */
- unsigned int final_entrys_page; /* Final_entry's dir entry's log page */
- unsigned int final_entry; /* Directory entry of the final */
- /* coalesced block */
- unsigned int context_saved; /* Whether the context was saved */
-
- /******************************/
- /* Initialize some variables. */
- /******************************/
-
- all_blocks_free = FALSE;
- context_saved = FALSE;
-
- /******************************/
- /* Check for an invalid token */
- /******************************/
-
- status = check_token (token);
-
- /**********************************************/
- /* Call prepare_dir_mapping() to save context */
- /* before mapping in the directory */
- /**********************************************/
- if (status == PASSED)
- status = prepare_dir_mapping (&context_saved);
-
- if (status == PASSED)
- {
- /************************************************/
- /* Convert token to its index and logical page. */
- /************************************************/
-
- tokens_index = token % DIR_ENTRIES_PER_PAGE;
- tokens_page = token / DIR_ENTRIES_PER_PAGE;
-
- /*******************************/
- /* Map in this directory page. */
- /*******************************/
-
- status = map_dir_page (tokens_page, FIRST_PHYS_PAGE);
- }
-
- if (status == PASSED)
- {
- /*************************************************/
- /* If token does not identify an allocated block */
- /* or if its size is zero return an error code. */
- /*************************************************/
-
- if ((directory[0][tokens_index].token != token) ||
- (directory[0][tokens_index].size == 0))
- status = INVALID_TOKEN;
-
- if (status == PASSED)
- {
- /*******************************************************/
- /* Set token to UNASSIGNED_TOKEN showing freed status. */
- /*******************************************************/
-
- directory[0][tokens_index].token = UNASSIGNED_TOKEN;
-
- /****************************************************/
- /* If this token is less than the current starting */
- /* location then set the new starting location used */
- /* when searching for free directory entries. */
- /****************************************************/
-
- if (token < dir_start)
- dir_start = token;
-
- /**********************************/
- /* Check if all pages are free. */
- /* If not, try to coalesce blocks */
- /**********************************/
-
- status = check_if_all_blocks_free (&all_blocks_free);
- }
- if ((status == PASSED) &&
- (all_blocks_free))
- {
- /*****************************************/
- /* We need to restore the context before */
- /* the pages and handles. */
- /*****************************************/
-
- if (context_saved)
- status = restore_memlib_context (status);
-
- if (status == PASSED)
- {
- context_saved = FALSE;
- status = effreeall();
- }
- }
- else if ((status == PASSED) &&
- (!all_blocks_free))
- {
- /*****************************************************/
- /* Search for a free block of memory after this free */
- /* block to coalesce into one free block. This */
- /* makes sure that if there are a number of little */
- /* blocks that could actually be put together into */
- /* one large block that we do so. */
- /*****************************************************/
-
- status = search_after (token, &final_entry, &usable_entry);
-
- /*******************************************************/
- /* Search for a free block of memory before this block */
- /* to coalesce into one free block. */
- /*******************************************************/
-
- if (status == PASSED)
- status = search_before (token, &final_entry, &usable_entry);
-
- /**************************************************/
- /* Test to see if we coalesced any blocks. If so */
- /* we need to check that the coalesced block does */
- /* not overlap too many logical pages. */
- /**************************************************/
-
- if ((status == PASSED) &&
- (final_entry != UNASSIGNED_TOKEN))
- {
- /*****************************************/
- /* Convert final_entry to its respective */
- /* directory page and index. */
- /*****************************************/
-
- final_entrys_page = final_entry / DIR_ENTRIES_PER_PAGE;
- final_entrys_index = final_entry % DIR_ENTRIES_PER_PAGE;
-
- /****************************************/
- /* Map in final_entry's directory page. */
- /****************************************/
-
- status = map_dir_page (final_entrys_page, FIRST_PHYS_PAGE);
- if (status == PASSED)
- {
- /*******************************************************/
- /* We can't have a block taking up more logical pages */
- /* than it needs. We always guarantee that a block of */
- /* memory take the least amount of logical pages as */
- /* possible. If it overlaps too many blocks we need */
- /* to break it up. Check the block final_index for */
- /* too much overlap. */
- /*******************************************************/
-
- size_mod_page_size =
- directory[0][final_entrys_index].size % PAGE_SIZE;
- if (size_mod_page_size == 0)
- size_mod_page_size = PAGE_SIZE;
-
- if ((PAGE_SIZE - directory[0][final_entrys_index].offset) <
- size_mod_page_size)
-
- {
- /*********************************************************/
- /* Convert usable_block to its respective directory page */
- /* and index. We're going to map this page into the */
- /* second physical page. */
- /*********************************************************/
-
- usable_entrys_page = usable_entry / DIR_ENTRIES_PER_PAGE;
- usable_entrys_index = usable_entry % DIR_ENTRIES_PER_PAGE;
-
- /****************************************************/
- /* Map in usable_block's directory page using the */
- /* directory_map's second array element to map this */
- /* page in at physical page one while keeping the */
- /* block that was coalesced's directory page at */
- /* physical page zero. */
- /***************************************************/
-
- status = map_dir_page (usable_entrys_page, SECOND_PHYS_PAGE);
-
- /*************************************************/
- /* This block overlaps too many logical pages. */
- /* We need to break it into two pieces at a */
- /* a logical page boundry. Use the usable_block */
- /* set when coalescing. */
- /*************************************************/
-
- if (status == PASSED)
- {
- /*************************************************/
- /* Set the second block's (usable_entry) size to */
- /* the size of the first piece after the first */
- /* page boundry of the whole block. */
- /*************************************************/
-
- directory[1][usable_entrys_index].size =
- directory[0][final_entrys_index].size -
- PAGE_SIZE + directory[0][final_entrys_index].offset;
-
- /**************************************/
- /* Set the offset of the second block */
- /* to start at the page boundry. */
- /**************************************/
-
- directory[1][usable_entrys_index].offset = 0;
-
- /***********************************************/
- /* Set the logical pages for the second block. */
- /***********************************************/
-
- for (j = 0; j < NUM_PAGES (directory[1][usable_entrys_index].size); j++)
- {
- directory[1][usable_entrys_index].logical_page[j] =
- directory[0][final_entrys_index].logical_page[j + 1];
- }
-
- /***********************************************/
- /* Set the first block size to the amount of */
- /* memory before the logical page boundry (the */
- /* space before the second block). */
- /***********************************************/
-
- directory[0][final_entrys_index].size -=
- directory[1][usable_entrys_index].size;
- }
-
- } /** end if PAGE_SIZE ... **/
-
- } /** status passed **/
-
- } /** end if final_index ... **/
-
- } /** end if check_of_all_blocks_free **/
-
- } /** end if status passed **/
-
- /*************************************************************/
- /* Unmap the directory - remap the pages that were in before */
- /*************************************************************/
-
- if ((!all_blocks_free) &&
- (context_saved))
- status = restore_memlib_context (status);
-
- return (status);
-
- } /** end effree **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int seteptrs (num_blocks, token, pointer) */
- /* unsigned int num_blocks; */
- /* unsigned int token[]; */
- /* void far* pointer[]; */
- /* */
- /* Description: */
- /* Attempts to map all the pages required by the block(s) of */
- /* memory identified by token[]. Returns pointers to each block */
- /* that has been mapped in. If the requested block(s) could not */
- /* mapped in then we return an error. */
- /* */
- /* Parameters: */
- /* input num_blocks Number of blocks to get access */
- /* to. */
- /* input token[num_blocks] An array of tokens that identify */
- /* the blocks to be mapped in. (The */
- /* tokens returned by efmalloc when */
- /* the block(s) were allocated.) */
- /* output pointer[num_blocks] An array of far pointers returned*/
- /* to the application. Pointer[i] */
- /* will point to the block of */
- /* memory identified by token[i]. */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* void far* pointers[2]; */
- /* unsigned int tokens[2]; */
- /* unsigned int status; */
- /* ... */
- /* status = efmalloc (200, &token[0]); */
- /* if (status != PASSED) */
- /* { error condition } */
- /* else */
- /* { continue normal code } */
- /* ... */
- /* status = efmalloc (600, &token[1]); */
- /* if (status != PASSED) */
- /* { error condition } */
- /* else */
- /* { continue normal code } */
- /* ... */
- /* status = seteptrs (2, tokens, pointers) */
- /* if (status == PASSED) */
- /* { blocks mapped in - use pointers to reference them } */
- /* else */
- /* { error - a token was bad or not all blocks could fit } */
- /* */
- /* Calls: map_dir_page() */
- /* map_unmap_pages() */
- /* */
- /* Called by: Application */
- /* set1eptr() */
- /* set2eptrs() */
- /* set3eptrs() */
- /* */
- /* Globals referenced/modified: directory */
- /* app_handle */
- /* directory_map */
- /* num_pages_in_page_frame */
- /* number_pages_mapped */
- /* page_frame_base_address */
- /* pages_mapped */
- /* */
- /**********************************************************************/
-
- unsigned int seteptrs (num_blocks, token, pointer)
- unsigned int num_blocks;
- unsigned int token[];
- void far* pointer[];
- {
- unsigned int status; /* Status of EMM & MEMLIB */
- unsigned int i; /* looping variable */
- unsigned int j; /* looping variable */
- unsigned int start_phys_page; /* Starting physical page in page frame */
- unsigned int log_page_match; /* Match was found? TRUE/FALSE */
- unsigned int log_page; /* temporarily store log page we're on */
- unsigned int current_dir_page; /* The current directory page mapped in */
- unsigned int tokens_page; /* Token's dir entry's logical page */
- unsigned int tokens_index; /* Token's index into its logical page */
- unsigned int num_pages_for_token;/* Number of logical pages for token's */
- /* block */
- void far* tokens_ptr; /* pointer to token's block */
-
- /*******************************/
- /* Initialize local variables. */
- /*******************************/
-
- status = PASSED;
- current_dir_page = UNMAPPED;
-
- /***************************************/
- /* Make sure all the tokens are valid. */
- /***************************************/
-
- for (i = 0; ((status == PASSED) &&
- (i < num_blocks)); i++)
- {
- status = check_token (token[i]);
- }
-
- if (status == PASSED)
- {
- /*******************************************************/
- /* Set each page in the page frame to UNMAPPED status. */
- /*******************************************************/
-
- for (i = 0; i < num_pages_in_page_frame; i++)
- pages_mapped[i].log_page = UNMAPPED;
-
- number_pages_mapped = 0;
-
- /***********************************************/
- /* For each block requested, try to map it in. */
- /***********************************************/
-
- for (i = 0; ((status == PASSED) &&
- (i < num_blocks)); i++)
- {
- tokens_page = token[i] / DIR_ENTRIES_PER_PAGE;
- tokens_index = token[i] % DIR_ENTRIES_PER_PAGE;
-
- if (tokens_page != current_dir_page)
- {
- current_dir_page = tokens_page;
- status = map_dir_page (current_dir_page, FIRST_PHYS_PAGE);
- }
-
- if ((status == PASSED) &&
- (token[i] != directory[0][tokens_index].token))
- status = INVALID_TOKEN;
-
- if (status == PASSED)
- {
- /*********************************/
- /* Initialize variable for loop. */
- /*********************************/
-
- start_phys_page = 0;
- log_page_match = FALSE;
- num_pages_for_token = NUM_PAGES (directory[0][tokens_index].size);
-
- /***********************************************************/
- /* While there's potentially room to map the logical pages */
- /* need for the i'th block and it isn't already mapped in. */
- /***********************************************************/
-
- while (((start_phys_page + num_pages_for_token)
- <= num_pages_in_page_frame)
- && (!log_page_match))
- {
- /*****************************************/
- /* Assume the logical pages need for the */
- /* i'th block are already mapped in. */
- /*****************************************/
-
- log_page_match = TRUE;
-
- /**************************************************/
- /* Test each of the logical pages in the i'th */
- /* block against the logical pages already mapped */
- /* in the page frame starting at start_phys_page. */
- /**************************************************/
-
- for (j = 0; (j < num_pages_for_token); j++)
- {
- log_page = directory[0][tokens_index].logical_page[j];
-
- /**********************************************/
- /* We won't have a match if the logical page */
- /* we're looking for is not already mapped in */
- /* and if the page is unmapped. */
- /**********************************************/
-
- if ((log_page != pages_mapped[start_phys_page + j].log_page) &&
- (pages_mapped[start_phys_page + j].log_page != UNMAPPED))
- log_page_match = FALSE;
- }
- /*************************************************/
- /* If the i'th block isn't mapped in (starting */
- /* at start_phys_page) increment start_phys_page */
- /* and try again. */
- /*************************************************/
-
- if (!log_page_match)
- start_phys_page++;
-
- } /** end while **/
-
- /**************************************************/
- /* If a match was found set pages_mapped array to */
- /* include the logical pages for this block. If */
- /* no match was found we can't map this block */
- /**************************************************/
-
- if (log_page_match)
- {
- for (j = 0; (j < num_pages_for_token); j++)
- {
- pages_mapped[start_phys_page + j].log_page =
- directory[0][tokens_index].logical_page[j];
-
- /*************************************************/
- /* Update pointer[i] to point to the i'th block. */
- /* The offset of the pointer we return is equal */
- /* to the offset of this block within the first */
- /* logical page for this block. These pointers */
- /* are only good modulus 16K since, for example, */
- /* we could have allocated a block when it was */
- /* mapped in at phys page 0 and now want to map */
- /* it in at phys page 3 or some such. */
- /*************************************************/
-
- FP_OFF (tokens_ptr) = directory[0][tokens_index].offset;
- FP_SEG (tokens_ptr) = FP_SEG(page_frame_base_address) +
- start_phys_page * OFFSET_SIZE;
- pointer[i] = tokens_ptr;
- }
- }
- else
- status = CANNOT_MAP_ALL_BLOCKS;
-
- } /** if status PASSED **/
-
- } /** end for i **/
-
- } /** end if status PASSED **/
-
- /*************************************************************/
- /* Unmap the directory - remap the pages that were in before */
- /*************************************************************/
-
- if (status == PASSED)
- {
- /*************************************/
- /* Count the number of pages to map. */
- /*************************************/
-
- number_pages_mapped = 0;
- for (i = 0; i < num_pages_in_page_frame; i++)
- {
- if (pages_mapped[i].log_page != UNMAPPED)
- number_pages_mapped++;
- }
- /************************************/
- /* Map in all the blocks requested. */
- /************************************/
-
- status = map_unmap_pages (PHYS_PAGE_MODE, number_pages_mapped,
- pages_mapped, app_handle);
- }
- return(status);
-
- } /** end seteptrs **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int set1eptr (token, pointer) */
- /* unsigned int token; */
- /* void far* *pointer; */
- /* */
- /* Description: */
- /* Convenience routine that calls seteptrs to just get access */
- /* to one block. */
- /* */
- /* Parms Passed: */
- /* input token A token that identifies the block to be */
- /* mapped in. (The token returned by efmalloc */
- /* when the block was allocated.) */
- /* output pointer A far pointer returned to the application. */
- /* It will point to the block of memory */
- /* identified by token. */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* void far* pointer; */
- /* unsigned int token; */
- /* unsigned int status; */
- /* ... */
- /* status = efmalloc (500, &token); */
- /* if (status != PASSED) */
- /* { error condition } */
- /* else */
- /* { continue normal code } */
- /* ... */
- /* status = set1eptr(token, &pointer) */
- /* if (status == PASSED) */
- /* { block mapped in - use pointer to reference it } */
- /* else */
- /* { error - the token was invalid } */
- /* */
- /* Calls: seteptrs() */
- /* */
- /* Called by: Application */
- /* */
- /* Globals referenced/modified: None */
- /* */
- /**********************************************************************/
-
- unsigned int set1eptr (token, pointer)
- unsigned int token;
- void far* *pointer;
- {
- unsigned int tokens[1]; /* Set one array entry to pass to */
- /* seteptrs() */
- void far* pointers[1]; /* Set one array entry to be passed */
- /* back from seteptrs() */
- unsigned int status; /* Status of EMM and MEMLIB */
-
- tokens[0] = token;
-
- /**************************************************/
- /* Call seteptrs() to map in the block identified */
- /* by token and return it pointer. */
- /**************************************************/
-
- status = seteptrs (1, tokens, pointers);
-
- if (status == PASSED)
- *pointer = pointers[0];
-
- return (status);
-
- } /** end set1eptr **/
-
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int set2eptrs (token1, token2, pointer1, */
- /* pointer2) */
- /* unsigned int token1; */
- /* unsigned int token2; */
- /* void far* *pointer1; */
- /* void far* *pointer2; */
- /* */
- /* Description: */
- /* Convenience routine that calls seteptrs to get access to */
- /* two different blocks of memory at one time. */
- /* */
- /* Parameters: */
- /* input token1 A token that identifies the first block to */
- /* be mapped in. (The token returned by */
- /* efmalloc when the block was allocated.) */
- /* input token2 A token that identifies the second block */
- /* to be mapped in. (The token returned by */
- /* efmalloc when the block was allocated.) */
- /* output pointer1 A far pointer returned to the application. */
- /* It will point to the block of memory */
- /* identified by token1. */
- /* output pointer2 A far pointer returned to the application. */
- /* It will point to the block of memory */
- /* identified by token2. */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* void far* ptr1; */
- /* void far* ptr2; */
- /* unsigned int token1; */
- /* unsigned int token2; */
- /* unsigned int status; */
- /* ... */
- /* status = efmalloc (500, &token1); */
- /* if (status != PASSED) */
- /* { error condition } */
- /* else */
- /* { continue normal code } */
- /* ... */
- /* status = efmalloc (900, &token2); */
- /* if (status != PASSED) */
- /* { error condition } */
- /* else */
- /* { continue normal code } */
- /* ... */
- /* status = set2eptrs (token1, token2, &ptr1, &ptr2); */
- /* if (status == PASSED) */
- /* { blocks mapped in - use pointers to reference them } */
- /* else */
- /* { error - a token was invalid or blocks couldn't fit } */
- /* */
- /* Calls: seteptrs() */
- /* */
- /* Called by: Application */
- /* */
- /* Globals referenced/modified: None */
- /* */
- /**********************************************************************/
-
- unsigned int set2eptrs (token1, token2, pointer1, pointer2)
- unsigned int token1;
- unsigned int token2;
- void far* *pointer1;
- void far* *pointer2;
- {
- unsigned int tokens[2]; /* Set two array entries to pass to */
- /* seteptrs() */
- void far* pointers[2]; /* Set two array entries to be passed */
- /* back from seteptrs() */
- unsigned int status; /* Status of EMM and MEMLIB */
-
- tokens[0] = token1;
- tokens[1] = token2;
-
- /***************************************************/
- /* Call seteptrs() to map in the blocks identified */
- /* by token1 and token2 and return their pointers. */
- /***************************************************/
-
- status = seteptrs (2, tokens, pointers);
-
- if (status == PASSED)
- {
- *pointer1 = pointers[0];
- *pointer2 = pointers[1];
- }
-
- return (status);
-
- } /** end set2eptrs **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int set3eptrs (token1, token2, token3, */
- /* pointer1, pointer2, pointer3) */
- /* unsigned int token1; */
- /* unsigned int token2; */
- /* unsigned int token3; */
- /* void far* *pointer1; */
- /* void far* *pointer2; */
- /* void far* *pointer3; */
- /* */
- /* Description: */
- /* Convenience routine that calls seteptrs to get access to */
- /* three different blocks of memory at one time. */
- /* */
- /* Parameters: */
- /* input token1 A token that identifies the first block to */
- /* be mapped in. (The token returned by */
- /* efmalloc when the block was allocated.) */
- /* input token2 A token that identifies the second block */
- /* to be mapped in. (The token returned by */
- /* efmalloc when the block was allocated.) */
- /* input token3 A token that identifies the third block to */
- /* be mapped in. (The token returned by */
- /* efmalloc when the block was allocated.) */
- /* output pointer1 A far pointer returned to the application. */
- /* It will point to the block of memory */
- /* identified by token1. */
- /* output pointer2 A far pointer returned to the application. */
- /* It will point to the block of memory */
- /* identified by token2. */
- /* output pointer3 A far pointer returned to the application. */
- /* It will point to the block of memory */
- /* identified by token3. */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* void far* ptr1; */
- /* void far* ptr2; */
- /* void far* ptr3; */
- /* unsigned int tok1; */
- /* unsigned int tok2; */
- /* unsigned int tok3; */
- /* unsigned int status; */
- /* ... */
- /* status = efmalloc (500, &tok1); */
- /* if (status != PASSED) */
- /* { error condition } */
- /* else */
- /* { continue normal code } */
- /* ... */
- /* status = efmalloc (900, &tok2); */
- /* if (status != PASSED) */
- /* { error condition } */
- /* else */
- /* { continue normal code } */
- /* ... */
- /* status = efmalloc (300, &tok3); */
- /* if (status != PASSED) */
- /* { error condition } */
- /* else */
- /* { continue normal code } */
- /* ... */
- /* status = set3eptrs (tok1, tok2, tok3, &ptr1, &ptr2, &ptr3); */
- /* if (status == PASSED) */
- /* { blocks mapped in - use pointers to reference them } */
- /* else */
- /* { error - a token was invalid or blocks couldn't fit } */
- /* */
- /* Calls: seteptrs() */
- /* */
- /* Called by: Application */
- /* */
- /* Globals referenced/modified: None */
- /* */
- /**********************************************************************/
-
- unsigned int set3eptrs (token1, token2, token3, pointer1, pointer2,
- pointer3)
- unsigned int token1;
- unsigned int token2;
- unsigned int token3;
- void far* *pointer1;
- void far* *pointer2;
- void far* *pointer3;
- {
- unsigned int tokens[3]; /* Set three array entries to pass */
- /* seteptrs() */
- void far* pointers[3]; /* Set three array entries to be */
- /* passed back from seteptrs() */
- unsigned int status; /* Status of EMM and MEMLIB */
-
- tokens[0] = token1;
- tokens[1] = token2;
- tokens[2] = token3;
-
- /*********************************************************/
- /* Call seteptrs() to map in the blocks identified by */
- /* token1, token2, and token3 and return their pointers. */
- /*********************************************************/
-
- status = seteptrs (3, tokens, pointers);
-
- if (status == PASSED)
- {
- *pointer1 = pointers[0];
- *pointer2 = pointers[1];
- *pointer3 = pointers[2];
- }
- return (status);
-
- } /** end set3eptrs **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int push_context (void) */
- /* */
- /* Description: */
- /* Pushes the current mapping context onto an internal stack. */
- /* The routine pop_context() can be used to restore the context */
- /* saved by this routine. Note that for each push we do we must */
- /* do a pop. */
- /* */
- /* Parameters: None */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* unsigned int status; */
- /* ... */
- /* status = push_context(); */
- /* if (status == PASSED) */
- /* { continue normal code } */
- /* else */
- /* { error condition } */
- /* */
- /* Calls: get_partial_context() */
- /* init_exp_mem() */
- /* */
- /* Called by: Application */
- /* */
- /* Globals referenced/modified: context_ptrs */
- /* context_size */
- /* exp_initialized */
- /* partial_page_map */
- /* context_top */
- /* */
- /**********************************************************************/
-
- unsigned int push_context (void)
- {
- unsigned int status; /* The status of EMM and MELIB */
-
- /**************************/
- /* Assume this will pass. */
- /**************************/
-
- status = PASSED;
-
- /*************************************************************/
- /* Initialize expanded memory if we haven't already done so. */
- /*************************************************************/
-
- if (!exp_initialized)
- status = init_exp_mem();
-
- if (status == PASSED)
- {
- /**************************************/
- /* Increment our variable for keeping */
- /* track of top of our context stack. */
- /**************************************/
-
- context_top++;
-
- /***********************************************************/
- /* We have an array of pointers that keep track of the */
- /* saved context. Make sure we stay with our array limit. */
- /***********************************************************/
-
- if (context_top < MAX_CONTEXTS_AVAILABLE)
- {
- /***************************************************************/
- /* Allocate space in conventional memory to save this context. */
- /* Then call get_partial_page_map to do the actual save. */
- /***************************************************************/
-
- context_ptrs[context_top] = (CONTEXT_STRUCT *) malloc (context_size);
-
- /*************************************************/
- /* Make sure we have enough conventional memory. */
- /*************************************************/
-
- if (context_ptrs[context_top] == NULL)
- status = MALLOC_FAILURE;
- else
- status = get_partial_context (&partial_page_map,
- context_ptrs[context_top]);
- }
- else
- status = MAX_PUSH_CONTEXTS_EXCEEDED;
-
- /*************************************************/
- /* If status failed, reset top of context stack. */
- /*************************************************/
-
- if (status != PASSED)
- context_top--;
- }
-
- return (status);
-
- } /** end push_context **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int pop_context (void) */
- /* */
- /* Description: */
- /* Pops the last context saved by a call to push_context(). */
- /* Note that for each push we do we must do a pop. */
- /* */
- /* Parameters: None */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* ... */
- /* unsigned int status; */
- /* ... */
- /* status = pop_context(); */
- /* if (status == PASSED) */
- /* { continue normal code } */
- /* else */
- /* { error condition } */
- /* */
- /* Calls: set_partial_context() */
- /* init_exp_mem() */
- /* */
- /* Called by: Application */
- /* */
- /* Globals referenced/modified: context_ptrs */
- /* exp_initialized */
- /* context_top */
- /* */
- /**********************************************************************/
-
- unsigned int pop_context (void)
- {
- unsigned int status; /* The status of EMM and MEMLIB) */
-
- /**************************/
- /* Assume this will pass. */
- /**************************/
-
- status = PASSED;
-
- /*************************************************************/
- /* Initialize expanded memory if we haven't already done so. */
- /*************************************************************/
-
- if (!exp_initialized)
- status = init_exp_mem();
-
- if (status == PASSED)
- {
- /********************************************/
- /* Make sure there is a context to restore. */
- /********************************************/
-
- if (context_top != NO_CONTEXTS)
- {
- /*********************************************************/
- /* Save the context using set_partial_context(), storing */
- /* the information an our stack (context_ptrs array). */
- /*********************************************************/
-
- status = set_partial_context (context_ptrs[context_top]);
- if (status == PASSED)
-
- /**************************************************************/
- /* Free the conventional memory we used to save this context. */
- /**************************************************************/
-
- free (context_ptrs[context_top]);
- }
- else
- status = NO_CONTEXT_AVAILABLE_TO_POP;
-
- /**********************************************/
- /* If status passed, decrement stack pointer. */
- /**********************************************/
-
- if (status == PASSED)
- if (context_top > 0)
- context_top--;
- else
- context_top = NO_CONTEXTS;
- }
-
- return (status);
-
- } /** end pop_context **/
-
- /*$PAGE*/
- /**********************************************************************/
- /* */
- /* Name: unsigned int effreeall (void) */
- /* */
- /* Description: */
- /* Frees all handles, pages and blocks. Prepare for program */
- /* termination. */
- /* */
- /* Parameters: None */
- /* */
- /* Results returned: */
- /* PASSED Operation successful */
- /* error Non-zero value, see "ERRORS.H" or EMS table A-2 */
- /* */
- /* Calling sequence: */
- /* #include "memlib.h" */
- /* #include "errors.h" */
- /* */
- /* unsigned int status; */
- /* ... */
- /* status = effree(); */
- /* if (status == PASSED) */
- /* { continue normal code } */
- /* else */
- /* { error condition } */
- /* */
- /* Calls: dealloc_pages() */
- /* map_umap_page() */
- /* */
- /* Called by: Application */
- /* effree() */
- /* */
- /* Globals referenced/modified: app_handle */
- /* exp_initialized */
- /* man_handle */
- /* num_pages_in_page_frame */
- /* context_ptrs */
- /* context_top */
- /* */
- /**********************************************************************/
-
- unsigned int effreeall (void)
- {
- unsigned int status; /* The status of EMM and MEMLIB */
- unsigned int j; /* Looping variable */
-
- status = PASSED;
-
- /*****************************************************************/
- /* If MEMLIB has not been initialized no need to free anything. */
- /*****************************************************************/
-
- if (exp_initialized)
- {
-
- /**************************************/
- /* Unmap all pages in the page frame. */
- /**************************************/
-
- for (j = 0; (status == PASSED) &&
- (j < num_pages_in_page_frame); j++)
- {
- status = map_unmap_page(j, UNMAPPED, man_handle);
- }
-
- if (status == PASSED)
- {
- /***********************************************/
- /* Deallocate the pages and handle for MEMLIB. */
- /***********************************************/
-
- status = dealloc_pages (man_handle);
- }
- if (status == PASSED)
- {
- /********************************************************/
- /* Deallocate the pages and handle for the application. */
- /********************************************************/
-
- status = dealloc_pages (app_handle);
-
- /***********************************/
- /* Reset exp_initialized to FALSE. */
- /***********************************/
-
- if (status == PASSED)
- {
- exp_initialized = FALSE;
-
- /***********************************************/
- /* Free up all space taken by pushed contexts. */
- /***********************************************/
-
- if (context_top != NO_CONTEXTS)
- {
- for (j = 0; j < context_top; j++)
- {
- if (context_ptrs[j] != NULL)
- free (context_ptrs[j]);
- }
- }
- }
- }
- }
- return(status);
-
- } /** end effreeall **/
-
-
-