/* Common routines for Sim. */ #include "sim.h" #ifdef CHECK_MEM_LEAK unsigned long old_mem_state = 0; #endif #if 0 /* pointer to the list of locked blocks registered for CleanAll() */ static HANDLE *LockedBlocks = NULL; static unsigned short LockedBlocksNum = 0; #endif /* pointer to the list of created blocks registered for CleanAll() */ static void **CreatedBlocks = NULL; static unsigned short CreatedBlocksNum = 0; /* Free the temporary blocks of memory, and unlock the locked blocks. This function is registered with atexit(). */ static void CleanAll (void) { unsigned short i; void *list_ptr; for (i = CreatedBlocksNum, list_ptr = CreatedBlocks; i; i--) { if (*(void **)list_ptr) free (*(void **)list_ptr); ((void **)list_ptr)++; } if (CreatedBlocks) free (CreatedBlocks); #if 0 for (i = LockedBlocksNum, list_ptr = LockedBlocks; i; i--) { if (*(HANDLE*)list_ptr) HeapUnlock (*(HANDLE*)list_ptr); ((HANDLE*)list_ptr)++; } if (LockedBlocks) free (LockedBlocks); #endif #ifdef CHECK_MEM_LEAK { unsigned long new_mem_state = HeapAvail(); if (new_mem_state < old_mem_state) { char str_buf[sizeof ("Warning, memory leak: 999999 bytes.")]; sprintf (str_buf, "Warning, memory leak: %lu bytes.", old_mem_state - new_mem_state); /* If there was an other message in the status bar, let time to read it. */ ngetchx(); xST_helpMsg (str_buf); } } #endif /* CHECK_MEM_LEAK */ } /* Prepare the CleanAll() mechanism. Must be called before any use of xmalloc(), xHLock(), ... */ void CleanAllInit (void) { #if 0 LockedBlocks = NULL; #endif CreatedBlocks = NULL; #if 0 LockedBlocksNum = 0; #endif CreatedBlocksNum = 0; atexit ((atexit_t)CleanAll); #ifdef CHECK_MEM_LEAK /* Must be *after* atexit() which allocates memory. */ old_mem_state = HeapAvail(); #endif } /* Allocate and register a block to be freed by CleanAll(). */ void *xmalloc (unsigned long size) { void *new_block; /* Make space for a new pointer in the list. */ if (!CreatedBlocks) { /* The list does not exist. */ CreatedBlocks = malloc (sizeof (void*)); if (!CreatedBlocks) fatal (NO_MEM_STR); /* NOTREACHED */ } else { new_block = realloc (CreatedBlocks, (CreatedBlocksNum + 1) * sizeof (void*)); if (!new_block) fatal (NO_MEM_STR); /* NOTREACHED */ CreatedBlocks = new_block; } /* Create the block. */ new_block = malloc (size); if (!new_block) { /* There is not enough memory. Remove the space we made for the new pointer. */ if (!CreatedBlocksNum) { /* The list is empty. */ free (CreatedBlocks); CreatedBlocks = NULL; } else { /* Reallocate the block with the original size. */ new_block = realloc (CreatedBlocks, (CreatedBlocksNum) * sizeof (void*)); if (new_block) /* If it has been reallocated. */ CreatedBlocks = new_block; } fatal (NO_MEM_STR); /* NOTREACHED */ } CreatedBlocksNum++; /* one more block in the list */ CreatedBlocks[CreatedBlocksNum - 1] = new_block; return new_block; } /* Reallocate and register a block to be freed by CleanAll(). */ void *xrealloc (void *ptr, unsigned long size) { void **list_ptr; void *newptr; if (!ptr) return xmalloc (size); newptr = realloc (ptr, size); if (!newptr) fatal (NO_MEM_STR); /* Search the pointer in the list. */ for (list_ptr = CreatedBlocks; *list_ptr != ptr;) list_ptr++; *list_ptr = newptr; return newptr; } #if 0 /* Free and remove from the list CREATEDBLOCKS the block pointed to by PTR. */ void xfree (void *ptr) { void **list_ptr; /* Search the pointer in the list. */ list_ptr = CreatedBlocks; while (*list_ptr != ptr) list_ptr++; /* Remove it from the list. */ *list_ptr = NULL; free (ptr); } #endif #if 0 /* Lock and register a block to be unlocked by CleanAll(). */ void *xHLock (HANDLE handle) { void *new_block; /* Make space for a new pointer in the list. */ if (!LockedBlocks) { /* The list does not exist. */ LockedBlocks = malloc (sizeof (HANDLE)); if (!LockedBlocks) fatal (NO_MEM_STR); /* NOTREACHED */ } else { new_block = realloc (LockedBlocks, (LockedBlocksNum + 1) * sizeof (HANDLE)); if (!new_block) fatal (NO_MEM_STR); /* NOTREACHED */ LockedBlocks = new_block; } /* Lock the block. */ new_block = HLock (handle); if (!new_block) { /* There is not enough memory. Remove the space we made for the new handle. */ if (!LockedBlocksNum) { /* The list is empty. */ free (LockedBlocks); LockedBlocks = NULL; } else { /* Reallocate the block with the original size. */ new_block = realloc (LockedBlocks, (LockedBlocksNum) * sizeof (HANDLE)); if (new_block) /* If it has been reallocated. */ LockedBlocks = new_block; } fatal (NO_MEM_STR); /* NOTREACHED */ } LockedBlocksNum++; /* one more handle in the list */ LockedBlocks[LockedBlocksNum - 1] = handle; return new_block; } #endif #if 0 /* Unlock and remove from LOCKEDBLOCKS list the block referenced by HANDLE. */ HANDLE xHeapUnlock (HANDLE handle) { HANDLE *list_ptr; /* Search the handle in the list. */ list_ptr = LockedBlocks; while (*list_ptr != handle) list_ptr++; /* Remove it from the list. */ *list_ptr = H_NULL; /* Unlock it . */ return (HeapUnlock (handle)); } #endif