FreeCalypso > hg > fc-tourmaline
view src/nucleus/erc.c @ 49:4e178a0e90f6
LICENSE added
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 18 Oct 2020 03:39:10 +0000 |
parents | 4e78acac3d88 |
children |
line wrap: on
line source
/*************************************************************************/ /* */ /* Copyright Mentor Graphics Corporation 2002 */ /* All Rights Reserved. */ /* */ /* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS */ /* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS */ /* SUBJECT TO LICENSE TERMS. */ /* */ /*************************************************************************/ /*************************************************************************/ /* */ /* FILE NAME VERSION */ /* */ /* erc.c Nucleus PLUS 1.14 */ /* */ /* COMPONENT */ /* */ /* ER - Error Management */ /* */ /* DESCRIPTION */ /* */ /* This file contains the core routines for the Error management */ /* component. */ /* */ /* DATA STRUCTURES */ /* */ /* None */ /* */ /* FUNCTIONS */ /* */ /* ERC_System_Error System error function */ /* ERC_Assert System assertion routine */ /* */ /* DEPENDENCIES */ /* */ /* tc_defs.h Thread control definitions */ /* er_extr.h Error handling functions */ /* */ /* HISTORY */ /* */ /* DATE REMARKS */ /* */ /* 03-01-1993 Created initial version 1.0 */ /* 04-19-1993 Verified version 1.0 */ /* 03-01-1994 Modified copyright notice, */ /* resulting in version 1.1 */ /* */ /* 03-18-1994 Verified version 1.1 */ /* 04-17-1996 updated to version 1.2 */ /* 03-24-1998 Released version 1.3. */ /* 11-24-1998 Added ERC_Assert routine. */ /* 03-26-1999 Released 1.11m (new release */ /* numbering scheme) */ /* 04-07-1999 Release 1.11mA */ /* 04-17-2002 Released version 1.13m */ /* 11-07-2002 Released version 1.14 */ /*************************************************************************/ #define NU_SOURCE_FILE #ifdef NU_ERROR_STRING #include <stdio.h> /* Standard I/O functions */ #endif #include "tc_defs.h" /* Thread control constants */ #include "er_extr.h" /* Error handling functions */ #ifdef NU_DEBUG_MEMORY #include "er_defs.h" /* Error management structures */ #include "dm_extr.h" /* Memory management */ #include "ncl\inc\string.h" /* memcmp & memcpy functions */ #include "ncl\inc\nu_ncl.h" /* memcmp & memcpy functions */ extern NU_MEMORY_POOL NU_DEBUG_POOL; extern const UINT8 ERD_MemoryAllocationHead[]; extern const UINT8 ERD_MemoryAllocationFoot[]; extern ER_DEBUG_ALLOCATION *ERD_RecentAllocation; extern UINT32 ERD_AllocationCount; extern UINT32 ERD_AllocationSequenceCounter; extern UINT32 ERD_TotalMemoryAllocated; extern UINT32 ERD_TotalMemoryAllocations; extern UINT32 ERD_MaxTotalMemoryAllocated; extern UINT32 ERD_MaxTotalMemoryAllocations; #endif /* NU_DEBUG_MEMORY */ /* Define external inner-component global data references. */ extern INT ERD_Error_Code; #ifdef NU_ERROR_STRING extern CHAR ERD_Error_String[]; #endif #ifdef NU_DEBUG extern UNSIGNED ERD_Assert_Count; #endif /* Define direct access to a thread component variable. */ extern VOID *TCD_Current_Thread; /*************************************************************************/ /* */ /* FUNCTION */ /* */ /* ERC_System_Error */ /* */ /* DESCRIPTION */ /* */ /* This function processes system errors detected by various */ /* system components. Typically an error of this type is */ /* considered fatal. */ /* */ /* CALLED BY */ /* */ /* Various Components */ /* */ /* CALLS */ /* */ /* None */ /* */ /* INPUTS */ /* */ /* error_code Code of detected system error*/ /* */ /* OUTPUTS */ /* */ /* None */ /* */ /* HISTORY */ /* */ /* DATE REMARKS */ /* */ /* 03-01-1993 Created initial version 1.0 */ /* 04-19-1993 Verified version 1.0 */ /* */ /*************************************************************************/ VOID ERC_System_Error(INT error_code) { #ifdef NU_ERROR_STRING INT i; CHAR *pointer; CHAR name[NU_MAX_NAME+1]; #endif NU_SUPERV_USER_VARIABLES /* Switch to supervisor mode */ NU_SUPERVISOR_MODE(); /* First place the error code into the global variable. */ ERD_Error_Code = error_code; #ifdef NU_ERROR_STRING /* Build string that corresponds to the error. */ switch(error_code) { case NU_ERROR_CREATING_TIMER_HISR: /* Build string that indicates an error occurred creating the timer HISR. */ sprintf(ERD_Error_String,"%s\n", "Error Creating Timer HISR"); break; case NU_ERROR_CREATING_TIMER_TASK: /* Build string that indicates an error occurred creating the timer Task. */ sprintf(ERD_Error_String,"%s\n", "Error Creating Timer Task"); break; case NU_STACK_OVERFLOW: /* Build string that indicates a stack overflow occurred. */ name[NU_MAX_NAME] = (CHAR) 0; pointer = (((TC_TCB *) TCD_Current_Thread) -> tc_name); for (i = 0; i < NU_MAX_NAME; i++) name[i] = *pointer++; sprintf(ERD_Error_String,"%s %s\n", "Stack Overflow in task/HISR: ", name); break; case NU_UNHANDLED_INTERRUPT: /* Build string that indicates an error occurred because of an unhandled interrupt. */ sprintf(ERD_Error_String,"%s\n", "Unhandled interrupt error"); break; } #endif /* This function cannot return, since the error is fatal. */ while(1) { } /* No need to return to user mode because of the infinite loop. */ /* Returning to user mode will cause warnings with some compilers. */ } #ifdef NU_DEBUG_MEMORY /*************************************************************************/ /* */ /* FUNCTION */ /* */ /* ERC_Memory_To_Debug */ /* */ /* DESCRIPTION */ /* */ /* This function returns a pointer to the ER_DEBUG_ALLOCATION that */ /* contains the memory allocation specified by the caller (target). */ /* */ /* CALLED BY */ /* */ /* ERC_Deallocate_Memory */ /* */ /* CALLS */ /* */ /* memcmp (CLIB_memcmp) */ /* ERC_System_Error */ /* */ /* INPUTS */ /* */ /* target memory allocation to find */ /* */ /* OUTPUTS */ /* */ /* ER_DEBUG_ALLOCATION ER_DEBUG_ALLOCATION that contains*/ /* target. */ /* */ /* HISTORY */ /* */ /* DATE REMARKS */ /* */ /*************************************************************************/ static ER_DEBUG_ALLOCATION *ERC_Memory_To_Debug(VOID *target) { INT dataOffset; ER_DEBUG_ALLOCATION *walk; ER_DEBUG_ALLOCATION *to_find; dataOffset = (INT)(((ER_DEBUG_ALLOCATION *)0)->data); to_find = (ER_DEBUG_ALLOCATION *)(((UNSIGNED_CHAR *)target) - dataOffset); /* Invalid pointer, report no match found */ if((target == NULL) && (to_find == NULL)) return(NULL); for (walk = ERD_RecentAllocation; ((walk != to_find) && (walk != NULL)); walk = walk->prev); /* if no match was found */ if (walk != NULL) { /* Has the "HEAD" or "FOOT" been disturbed by a rouge pointer? */ if (memcmp((void *)ERD_MemoryAllocationHead,(void *)walk->head,4) != 0) ERC_System_Error(NU_MEMORY_CORRUPT); if (memcmp((void *)ERD_MemoryAllocationFoot,(void *)&(walk->data[walk->size]),4) != 0) ERC_System_Error(NU_MEMORY_CORRUPT); } return(walk); } /*************************************************************************/ /* */ /* FUNCTION */ /* */ /* ERC_Remove_Debug_Allocation */ /* */ /* DESCRIPTION */ /* */ /* This function removes an ER_DEBUG_ALLOCATION from the linked list*/ /* */ /* CALLED BY */ /* */ /* ERC_Deallocate_Memory */ /* */ /* CALLS */ /* */ /* none */ /* */ /* INPUTS */ /* */ /* target ER_DEBUG_ALLOCATION to remove */ /* */ /* OUTPUTS */ /* */ /* STATUS status of the operation */ /* */ /* HISTORY */ /* */ /* DATE REMARKS */ /* */ /*************************************************************************/ static STATUS ERC_Remove_Debug_Allocation(ER_DEBUG_ALLOCATION *target) { ER_DEBUG_ALLOCATION *walk; if (target == NULL) return(NU_INVALID_POINTER); /* If the list is empty nothing can be removed! */ if (ERD_RecentAllocation == NULL) return(NU_EMPTY_DEBUG_ALLOCATION_LIST); /* If there is only one item on the list. */ if (ERD_RecentAllocation->prev == NULL) { /* If the only item on the list is the one to be removed...*/ if (ERD_RecentAllocation == target) { ERD_RecentAllocation = NULL; return(NU_SUCCESS); } else return(NU_INVALID_DEBUG_ALLOCATION); } if (ERD_RecentAllocation == target) { ERD_RecentAllocation->prev = target->prev; return(NU_SUCCESS); } /* Walk the entire list until walk->prev is the target. */ walk = ERD_RecentAllocation; while (NU_TRUE) { if (walk->prev == target) break; if (walk->prev == NULL) break; walk = walk->prev; } /* target is last item on the list */ if (walk->prev == target) { walk->prev = target->prev; return(NU_SUCCESS); } return(NU_INVALID_DEBUG_ALLOCATION); } /*************************************************************************/ /* */ /* FUNCTION */ /* */ /* ERC_Append_Debug_Allocation */ /* */ /* DESCRIPTION */ /* */ /* This function appends an ER_DEBUG_ALLOCATION to the linked list. */ /* */ /* CALLED BY */ /* */ /* ERC_Allocate_Memory */ /* */ /* CALLS */ /* */ /* none */ /* */ /* INPUTS */ /* */ /* new_guy ER_DEBUG_ALLOCATION to append */ /* */ /* OUTPUTS */ /* */ /* STATUS status of the operation */ /* */ /* HISTORY */ /* */ /* DATE REMARKS */ /* */ /*************************************************************************/ static STATUS ERC_Append_Debug_Allocation(ER_DEBUG_ALLOCATION *new_guy) { /* Either this is the first ER_DEBUG_ALLOCATION ever to be appended or this is the first on a list that shrank to 0 element. */ if (ERD_AllocationCount == 0) { ERD_RecentAllocation = new_guy; ERD_RecentAllocation->prev = NULL; } else { new_guy->prev = ERD_RecentAllocation; ERD_RecentAllocation = new_guy; } return(NU_SUCCESS); } /*************************************************************************/ /* */ /* FUNCTION */ /* */ /* ERC_Allocate_Memory */ /* */ /* DESCRIPTION */ /* */ /* This function tracks additional information regarding the memory */ /* allocation */ /* */ /* CALLED BY */ /* */ /* Application */ /* */ /* CALLS */ /* */ /* ERC_Append_Debug_Allocation */ /* DMCE_Allocate_Memory */ /* memcpy */ /* */ /* INPUTS */ /* */ /* pool_ptr Memory pool pointer */ /* return_pointer Pointer to the destination */ /* memory pointer */ /* size Number of bytes requested */ /* suspend Suspension option if full */ /* */ /* OUTPUTS */ /* */ /* NU_SUCCESS If service is successful */ /* NU_NO_MEMORY Memory not available */ /* NU_TIMEOUT If timeout on service */ /* NU_POOL_DELETED If memory pool deleted */ /* during suspension */ /* */ /* HISTORY */ /* */ /* DATE REMARKS */ /* */ /*************************************************************************/ STATUS ERC_Allocate_Memory(NU_MEMORY_POOL *pool_ptr, VOID **ptr, UNSIGNED size, UNSIGNED suspend, unsigned long line, const char* file) { ER_DEBUG_ALLOCATION **debug_ptr; STATUS status = NU_SUCCESS; /* If the allocation is not from the pool specified in the NU_DEBUG_POOL macro then allocate memory normally (no meta-data) */ if(&NU_DEBUG_POOL != pool_ptr) return(DMCE_Allocate_Memory(pool_ptr, ptr, size, suspend)); /* This call allocates memory for a structure that will contain the users data and the meta-data used to find memory problems */ status = DMCE_Allocate_Memory(pool_ptr, ptr, (sizeof(ER_DEBUG_ALLOCATION) + size + 4), suspend); if (status != NU_SUCCESS) return status; /* From here out, debug_ptr is used because it is typed. In the end ptr will be set to point to debug_ptr->data, where the user will put the data. */ debug_ptr = (ER_DEBUG_ALLOCATION **)ptr; /* Record file and line where the application made the allocation */ (*debug_ptr)->line = line; (*debug_ptr)->file = file; /* Set "HEAD" and "FOOT" boundary markers */ memcpy((*debug_ptr)->head,ERD_MemoryAllocationHead,4); memcpy(&((*debug_ptr)->data[size]),ERD_MemoryAllocationFoot,4); /* Record the size */ (*debug_ptr)->size = size; /* This links debug_ptr to a linked list that holds all the ER_DEBUG_ALLOCATION structures. */ ERC_Append_Debug_Allocation((*debug_ptr)); (*debug_ptr)->AllocSequenceCounter = ERD_AllocationSequenceCounter++; ERD_TotalMemoryAllocated += size; ERD_TotalMemoryAllocations++; ERD_AllocationCount++; if (ERD_MaxTotalMemoryAllocated < ERD_TotalMemoryAllocated) ERD_MaxTotalMemoryAllocated = ERD_TotalMemoryAllocated; if (ERD_MaxTotalMemoryAllocations < ERD_TotalMemoryAllocations) ERD_MaxTotalMemoryAllocations = ERD_TotalMemoryAllocations; /* Return pointer to the data field of debug allocation by reference */ (*ptr) = (*debug_ptr)->data; return(status); } /*************************************************************************/ /* */ /* FUNCTION */ /* */ /* ERC_Deallocate_Memory */ /* */ /* DESCRIPTION */ /* */ /* This function tracks additional information regarding the memory */ /* deallocation. */ /* */ /* CALLED BY */ /* */ /* Application */ /* */ /* CALLS */ /* */ /* ERC_Memory_To_Debug */ /* ERC_Remove_Debug_Allocation */ /* DMCE_Deallocate_Memory */ /* */ /* INPUTS */ /* */ /* ptr Pointer to dynamic memory */ /* */ /* OUTPUTS */ /* */ /* NU_SUCCESS */ /* NU_INVALID_POINTER Returned when ptr is null or */ /* when there is no */ /* corresponding */ /* ER_DEBUG_ALLOCATION */ /* */ /* HISTORY */ /* */ /* DATE REMARKS */ /* */ /*************************************************************************/ STATUS ERC_Deallocate_Memory(VOID *ptr) { ER_DEBUG_ALLOCATION *target; STATUS status; if (ptr == NULL) return(NU_INVALID_POINTER); /* Find the NU_DEBUG_ALLOCATION ptr refers to. After this call, (&(target->data) == ptr) or (target == NULL). */ target = ERC_Memory_To_Debug(ptr); /* Remove target from the linked list of ER_DEBUG_ALLOCATIONs */ status = ERC_Remove_Debug_Allocation(target); if ((status != 0) || (target == NULL)) return(NU_INVALID_POINTER); /* Maintain status variables */ ERD_TotalMemoryAllocated -= target->size; ERD_TotalMemoryAllocations--; ERD_AllocationCount--; return(DMCE_Deallocate_Memory(target)); } #endif /* NU_DEBUG_MEMORY */ /************************************************************************** This routine should appear last in this file and must *NOT* use the NU_ASSERT macro. **************************************************************************/ #ifdef NU_ASSERT /* Don't use NU_ASSERT past this point */ #undef NU_ASSERT #define NU_ASSERT(ignore) ((void) 0) #endif #ifdef NU_ASSERT2 #undef NU_ASSERT2 #define NU_ASSERT2(ignore) ((void) 0) #endif /*************************************************************************/ /* */ /* FUNCTION */ /* */ /* ERC_Assert */ /* */ /* DESCRIPTION */ /* */ /* This public routine is called when an assertion made by the */ /* NU_ASSERT (or NU_ASSERT2) macro fails. By default, this routine */ /* simply counts the number of failed assertions. A breakpoint can */ /* be set in the routine to observe failed assertions, or the */ /* routine can be customized to perform some action, such as */ /* printing the failed assertion as a message, etc. */ /* */ /* CALLED BY */ /* */ /* NU_ASSERT macro */ /* NU_ASSERT2 macro */ /* */ /* CALLS */ /* */ /* None */ /* */ /* INPUTS */ /* */ /* test Pointer to string of failed assertion test */ /* name File name of file containing failed assertion */ /* line Location of failed assertion in above file */ /* */ /* OUTPUTS */ /* */ /* None */ /* */ /* HISTORY */ /* */ /* NAME DATE REMARKS */ /* */ /* Todd C. Larsen 09-01-1998 Created initial revision */ /* */ /*************************************************************************/ #ifdef NU_DEBUG void ERC_Assert(CHAR *test, CHAR *name, UNSIGNED line) { NU_SUPERV_USER_VARIABLES #ifdef NU_ENABLE_HISTORY /* Make an entry that corresponds to this function in the system history log. */ HIC_Make_History_Entry(NU_ASSERT_ID, (UNSIGNED) test, (UNSIGNED) name, line); #endif /* Switch to supervisor mode */ NU_SUPERVISOR_MODE(); /* Set breakpoint here to catch failed assertions. */ ERD_Assert_Count += 1; /* Return to user mode */ NU_USER_MODE(); } #endif /* NU_DEBUG */