Example #1
0
T_doubleLinkList DoubleLinkListCreate(T_void)
{
    T_doubleLinkListStruct *p_head ;

    DebugRoutine("DoubleLinkListCreate") ;

#ifdef COMPILE_OPTION_DOUBLE_LINK_OUTPUT
printf("!A 1 list_%s\n", DebugGetCallerName()) ;
#endif
    p_head = ICreateNode() ;
    DebugCheck(p_head != NULL) ;

    if (p_head)  {
        p_head->p_next = p_head ;        /* Next is self. */
        p_head->p_previous = p_head ;    /* Previous is self. */
        p_head->p_head = p_head ;        /* Self points to self. */
        p_head->countOrData.count = 0 ;  /* No elements. */
    }

#ifndef NDEBUG
    if (G_doOutput==FALSE)  {
        G_doOutput = TRUE ;
        atexit(IDumpMaxCount) ;
    }
#endif

    DebugEnd() ;

    return (T_doubleLinkList) p_head ;
}
Example #2
0
/**
 *  DoubleLinkListDestroy goes through a list of double link list nodes
 *  and detaches the data with them and then deletes all the nodes.
 *
 *  NOTE:
 *  The calling routine must realize that this routine does not
 *  deallocate memory attached to a node, it is assumed that the calling
 *  routine will do this.
 *
 *  @param linkList -- Handle to link list to destroy
 *
 *<!-----------------------------------------------------------------------*/
T_void DoubleLinkListDestroy(T_doubleLinkList linkList)
{
    T_doubleLinkListStruct *p_head ;

    DebugRoutine("DoubleLinkListDestroy") ;
    DebugCheck(linkList != DOUBLE_LINK_LIST_BAD) ;

#ifdef COMPILE_OPTION_DOUBLE_LINK_OUTPUT
printf("!F 1 list_%s\n", DebugGetCallerName()) ;
#endif
    /* Get a quick pointer. */
    p_head = (T_doubleLinkListStruct *)linkList ;
    DebugCheck(p_head->tag == DOUBLE_LINK_LIST_TAG) ;

    /* Remove all items in the list.  Hopefully */
    /* all attached data is not allocated memory or is being */
    /* managed by someone else. */
    while (p_head->p_next != p_head)
        DoubleLinkListRemoveElement((T_doubleLinkListElement)p_head->p_next) ;

    /* Destroy this element now. */
    IDestroyNode(p_head) ;

    DebugEnd() ;
}
Example #3
0
/**
 *  DoubleLinkListAddElementBeforeElement adds a new element before
 *  another element in a link list.
 *
 *  @param element -- handle of element to go before
 *  @param p_data -- Pointer to element data
 *
 *<!-----------------------------------------------------------------------*/
T_doubleLinkListElement DoubleLinkListAddElementBeforeElement(
                            T_doubleLinkListElement element,
                            T_void *p_data)
{
    T_doubleLinkListStruct *p_before ;
    T_doubleLinkListStruct *p_head ;
    T_doubleLinkListStruct *p_element ;

    DebugRoutine("DoubleLinkListAddElementBeforeElement") ;
    DebugCheck(element != DOUBLE_LINK_LIST_ELEMENT_BAD) ;

    /* Get a quick pointer. */
    p_before = (T_doubleLinkListStruct *)element;
    DebugCheck(p_before->tag == DOUBLE_LINK_LIST_TAG) ;
    p_head = p_before->p_head ;
    DebugCheck(p_head != NULL) ;
    DebugCheck(p_head->tag == DOUBLE_LINK_LIST_TAG) ;
    DebugCheck(p_head->p_head == p_head) ;

    if ((p_head) && (p_before))  {
        /* Create a new element. */
#ifdef COMPILE_OPTION_DOUBLE_LINK_OUTPUT
printf("!A 1 node_%s\n", DebugGetCallerName()) ;
#endif
        p_element = ICreateNode() ;
        DebugCheck(p_element != NULL) ;

        if (p_element)  {
            /* Attach the data to the element. */
            p_element->countOrData.p_data = p_data ;
            p_element->p_previous = p_before->p_previous ;
            p_element->p_next = p_before ;
            p_element->p_head = p_head ;
            p_before->p_previous->p_next = p_element ;
            p_before->p_previous = p_element ;
            p_head->countOrData.count++ ;
        }
    }

    DebugEnd() ;

    return ((T_doubleLinkListElement)p_element) ;
}
Example #4
0
File: FILE.C Project: LesInk/Test
T_void *FileLoad(T_byte8 *p_filename, T_word32 *p_size)
{
    T_byte8 *p_data ;
    T_file file ;

    DebugRoutine("FileLoad") ;
    DebugCheck(p_filename != NULL) ;
    DebugCheck(p_size != NULL) ;

    /* See how big the file is so we know how much memory to allocate. */
    *p_size = FileGetSize(p_filename) ;
#ifdef COMPILE_OPTION_FILE_OUTPUT
printf("!A 1 file_%s\n", p_filename) ;
printf("!A 1 file_r_%s\n", DebugGetCallerName()) ;
#endif
    if (*p_size)  {
        /* Allocate the memory for the file. */
        p_data = MemAlloc(*p_size) ;

        DebugCheck(p_data != NULL) ;

        /* Make sure we got the memory. */
        if (p_data != NULL)  {
            /* If memory was allocated, read in the file into this memory. */
            file = FileOpen(p_filename, FILE_MODE_READ) ;
            FileRead(file, p_data, *p_size) ;
            FileClose(file) ;
        } else {
            /* If memory was not allocated, return with a zero length. */
            *p_size = 0 ;
        }
    } else {
        *p_size = 0 ;
        p_data = NULL ;
    }

    DebugEnd() ;

    /* Return the pointer to the data. */
    return p_data ;
}
Example #5
0
/**
 *  DoubleLinkListRemoveElement removes  an element from a link list.
 *  This routine also returns the data that was attached to this element.
 *
 *  @param element --  removes the element from the list.
 *
 *  @return Previously attached node data
 *
 *<!-----------------------------------------------------------------------*/
T_void *DoubleLinkListRemoveElement(T_doubleLinkListElement element)
{
    T_doubleLinkListStruct *p_node ;
    T_void *p_data = NULL ;

    DebugRoutine("DoubleLinkListRemoveElement") ;
    DebugCheck(element != DOUBLE_LINK_LIST_ELEMENT_BAD) ;

    /* Get a quick pointer. */
    p_node = (T_doubleLinkListStruct *)element;
    DebugCheck(p_node->tag == DOUBLE_LINK_LIST_TAG) ;

    /* Make sure we are not trying to delete the head. */
    DebugCheck(p_node->p_head != p_node) ;

    if (p_node)  {
        /* Detach the node from the list. */
        p_node->p_next->p_previous = p_node->p_previous ;
        p_node->p_previous->p_next = p_node->p_next ;

        /* Get the attached data. */
        p_data = p_node->countOrData.p_data ;

        /* Decrement the count of items on this list. */
        p_node->p_head->countOrData.count-- ;

        /* Release the node from memory. */
#ifdef COMPILE_OPTION_DOUBLE_LINK_OUTPUT
printf("!F 1 node_%s\n", DebugGetCallerName()) ;
#endif
        IDestroyNode(p_node) ;
    }

    DebugEnd() ;

    return p_data ;
}
Example #6
0
/**
 *  DoubleLinkListFreeAndDestroy goes through a linked list and does a
 *  MemFree on each of the data elements and then calls Destroy on the
 *  whole list.
 *
 *  @param linkList -- Handle to link list to destroy
 *
 *<!-----------------------------------------------------------------------*/
T_void DoubleLinkListFreeAndDestroy(T_doubleLinkList *linkList)
{
    T_doubleLinkListStruct *p_head ;
    T_doubleLinkListStruct *p_at ;
    T_doubleLinkListStruct *p_next ;

    DebugRoutine("DoubleLinkListFreeAndDestroy") ;
    DebugCheck(linkList != DOUBLE_LINK_LIST_BAD) ;

#ifdef COMPILE_OPTION_DOUBLE_LINK_OUTPUT
printf("!F 1 list_%s\n", DebugGetCallerName()) ;
#endif
    /* Get a quick pointer. */
    p_head = (T_doubleLinkListStruct *)(*linkList) ;
    DebugCheck(p_head->tag == DOUBLE_LINK_LIST_TAG) ;

    /* Remove all items in the list.  Hopefully */
    /* all attached data is not allocated memory or is being */
    /* managed by someone else. */
    if (p_head)  {
        p_at = p_head->p_next ;
        while ((p_at != p_head) && (p_at != DOUBLE_LINK_LIST_ELEMENT_BAD))  {
            p_next = p_at->p_next ;
            if (p_at->countOrData.p_data != NULL)  {
                MemFree(p_at->countOrData.p_data) ;
                p_at->countOrData.p_data = NULL ;
            }
            p_at = p_next ;
        }
    }

    DoubleLinkListDestroy(*linkList) ;
    linkList = DOUBLE_LINK_LIST_BAD ;

    DebugEnd() ;
}
/**
 *  FindFreeSpace is the routine called by MemAlloc when it just tried
 *  to allocate new memory and could not.  This routine is called to free
 *  up space use by discarded memory.  If there is memory freed up, this
 *  routine returns with a TRUE, otherwise FALSE.  It does this by looking
 *  at the discard list and freeing up the oldest block.  It will only
 *  discard one block and then return with a TRUE status.
 *  Also, before the block is freed, it's callback routine is called
 *  to note the block's disappearance.
 *
 *  NOTE: 
 *  A future version might want to free up a certain amount of space
 *  instead of being called several times.  However, when you are running
 *  out of memory, this method is probably just as good.
 *
 *  @return TRUE = memory was freed
 *      FALSE = no more memory can be freed.
 *
 *<!-----------------------------------------------------------------------*/
static E_Boolean IMemFindFreeSpace(T_void)
{
    E_Boolean answer = FALSE ;
    T_memBlockHeader *p_header ;
    T_word16 pos ;

    DebugRoutine("IMemFindFreeSpace") ;

//printf("Finding free space!\n") ;
//fprintf(stderr, "Finding free space!") ;
MemCheck(2925) ;
//MemDumpDiscarded() ;
//_heapmin() ;

/*
printf("List:\n") ;
p_header = P_startOfDiscardList ;
while (p_header)  {
    printf("  %p\n", ((T_byte8 *)p_header)+sizeof(T_memBlockHeader)) ;
    p_header = p_header->p_nextBlock ;
}
printf("End of list\n\n") ;
*/
    /* Do we have any blocks on the discard list? */
    if (P_startOfDiscardList != NULL)  {
        /* Yes, call it's callback routine -- it is about to be */
        /* freed from memory.  Make sure to pass a pointer to the */
        /* true data part (past header) of the memory block. */
        p_header = P_startOfDiscardList ;

        /* Make sure you are freeing a discarded block. */
        DebugCheck(strcmp(p_header->blockTag, "DaG") == 0) ;

//printf("Discard %p\n", (((T_byte8 *)p_header)+sizeof(T_memBlockHeader))) ;
        p_header->p_callback(((T_byte8 *)p_header)+sizeof(T_memBlockHeader)) ;

        /* Make sure you are freeing a discarded block. */
        DebugCheck(strcmp(p_header->blockTag, "DaG") == 0) ;

        /* Now that the block's owner has been notified, we */
        /* can continue. */

        /* We first need to note the previous block that the next block */
        /* is disappearing. */
#if 0
        if (p_header->p_nextBlock != NULL)  {
            p_header->p_nextBlock->p_prevBlock = NULL ;

            /* If there is a previous block, make it the new end. */
            P_startOfDiscardList = p_header->p_nextBlock ;
        } else {
            /* If there is no previous block, the list is now empty. */
            P_endOfDiscardList =
                P_startOfDiscardList = NULL ;
        }
#endif
        P_startOfDiscardList = p_header->p_nextBlock ;
        if (P_startOfDiscardList == NULL)
            P_endOfDiscardList = NULL ;
        else
            p_header->p_nextBlock->p_prevBlock = NULL ;

        /* Note that the total is now less. */
        G_sizeAllocated -= sizeof(T_memBlockHeader) + p_header->size ;
#ifdef COMPILE_OPTION_OUTPUT_ALLOCATION
printf("!F %d %s\n", p_header->size, DebugGetCallerFile()) ;
printf("!F %d %s:%s\n", p_header->size, DebugGetCallerFile(), DebugGetCallerName()) ;
#endif

#ifndef NDEBUG
        /* Make sure we didn't roll under. */
        DebugCheck(G_sizeAllocated < 0xF0000000) ;
#endif

#ifdef _MEM_CHECK_FULL_
        /* Find the block on the list (if it is there). */
        pos = IFindPointer(p_header) ;

        if (pos == 0xFFFF)  {
            printf("bad attempt to free memory at %p\n", p_header+1) ;
            DebugCheck(FALSE) ;
        }
        /* Remove the block from the alloc list and put on the free list. */
        G_blockList[pos] = ((T_memBlockHeader *)((T_word32)G_firstFree)) ;

        G_firstFree = pos ;
#endif
#ifndef NDEBUG
        /* Mark the block as fully freed. */
        strcpy(p_header->blockTag, "!!!") ;

        /* Fill the block with junk. */
        memset(((T_byte8 *)p_header)+sizeof(T_memBlockHeader), 0xCE, p_header->size) ;
#endif
#ifndef NDEBUG
    memset(p_header, 0xCD, sizeof(T_memBlockHeader) + p_header->size) ;
#endif
        /* Ok, now we can actually free the block. */
        free(p_header) ;

        /* Note that memory *was* freed. */
        answer = TRUE ;
    }

    DebugCheck(answer < BOOLEAN_UNKNOWN) ;
    DebugEnd() ;
    return answer ;
}
/**
 *  MemFree frees a block of memory that was previously allocated.
 *  It also checks the integrity of the pointer given to it.  If the
 *  pointer is NULL, it crashes.  If the pointer does not point to a
 *  block that was allocated, it crashes.
 *
 *  NOTE: 
 *  None that I can think of (except this will definitely slow down
 *  the system a little).
 *
 *  @param p_data -- Pointer to block to free
 *      Normally we can assume p_data points to data and is not NULL.
 *
 *<!-----------------------------------------------------------------------*/
T_void MemFree(T_void *p_data)
{
    T_byte8 *p_bytes ;
    T_memBlockHeader *p_header ;
    T_word16 pos ;

    DebugRoutine("MemFree") ;
    DebugCheck(p_data != NULL) ;

    /* Back up from the pointer we are given and try to find the
       header tag. */
    p_bytes = p_data ;
    p_bytes -= sizeof(T_memBlockHeader) ;

    p_header = (T_memBlockHeader *)p_bytes ;
//printf("Freeing %p, ID: %d, for %s\n", p_data, p_header->blockId, DebugGetCallerName()) ;

//printf("free ID: %ld, @ %p, %s\n", p_header->blockId, p_data, DebugGetCallerName()) ;
//fflush(stdout) ;
#ifdef _MEM_CHECK_FULL_
    MemCheck(10210) ;
    /* Find the block on the list (if it is there). */
    pos = IFindPointer(p_header) ;

    if (pos == 0xFFFF)  {
        printf("bad attempt to free memory at %p\n", p_data) ;
        DebugCheck(FALSE) ;
    }
    /* Remove the block from the alloc list and put on the free list. */
    G_blockList[pos] = ((T_memBlockHeader *)((T_word32)G_firstFree)) ;

    G_firstFree = pos ;
#endif

//printf("MemFree: %s (%p)\n", ((T_memBlockHeader *)p_bytes)->blockTag, p_data) ;
    /* Make sure we are freeing one of our blocks. */
    DebugCheck(strcmp (((T_memBlockHeader *)p_bytes)->blockTag, "DaG") != 0) ;
    DebugCheck(strcmp (((T_memBlockHeader *)p_bytes)->blockTag, "TaG") == 0) ;

    /* Check if the tag is there, or bomb. */
    DebugCheck(strcmp(((T_memBlockHeader *)p_bytes)->blockTag, "TaG") == 0) ;
    strcpy(((T_memBlockHeader *)p_bytes)->blockTag, "!!!");

//#ifndef NDEBUG
    /* Note that the total is now less. */
    G_sizeAllocated -= sizeof(T_memBlockHeader) + p_header->size ;
#ifdef COMPILE_OPTION_OUTPUT_ALLOCATION
printf("!F %d %s (@0x%08X)\n", p_header->size, DebugGetCallerFile(), p_bytes) ;
printf("!F %d %s:%s\n", p_header->size, DebugGetCallerFile(), DebugGetCallerName()) ;
#endif

#ifndef NDEBUG
    /* Make sure we didn't roll under. */
    DebugCheck(G_sizeAllocated < 0xF0000000) ;
#endif
#ifndef NDEBUG
    memset(p_bytes, 0xCD, sizeof(T_memBlockHeader) + p_header->size) ;
#endif
    /* OK, free up the valid block. */
    free(p_bytes) ;
//puts("OK") ;
//printf("FREE: %d   \r", FreeMemory()) ;
//fflush(stdout) ;

    /* Cound how many are freed. */
    G_deallocCount++ ;

    DebugEnd() ;
}
/**
 *  Currently, this routine is provided more for debugging than an
 *  actual utility.  However, this should be the one routine that everyone
 *  calls to allocate memory (no matter what system).
 *  Since we use this for debugging, we will assign a number to each
 *  piece of memory that is allocated and will attach a "tag" at the
 *  beginning to make the system have a way to check if we are later
 *  freeing a block, or just random memory.
 *  Space is also provided to allow the block to be declared as discard-
 *  able.  A discardable block needs to be able to be placed on a double
 *  link list and have a call back function (for when the block is actually
 *  discarded).  See MemMarkDiscardable for more details.
 *
 *  NOTE: 
 *  I'm sure what the size limitations for this will be, so we had
 *  best stick to 64K or smaller allocations.  Note that this routine is
 *  also made for blocks of typically larger than 256 bytes.  If you got
 *  alot of small parts, you might want to try doing it a different way.
 *
 *  @param size -- Amount of memory to allocate
 *
 *  @return Pointer or NULL to memory block.
 *
 *<!-----------------------------------------------------------------------*/
T_void *MemAlloc(T_word32 size)
{
    T_byte8 *p_memory ;
    T_memBlockHeader *p_header ;
    E_Boolean memFound ;
    T_word16 next ;
    const char *p_name ;
    long line ;

    DebugRoutine("MemAlloc") ;

DebugGetCaller(&p_name, &line) ;
//printf("|%s,%ld\.0\n", p_name, size) ;
#ifdef COMPILE_OPTION_OUTPUT_ALLOCATION
//printf("!A %d %s\n", size, DebugGetCallerFile()) ;
printf("!A %d %s:%s ", size, DebugGetCallerFile(), DebugGetCallerName()) ;
#endif
    /* Allocate memory and room for our tag. */
    do {
//DebugCheck(_heapchk() == _HEAPOK) ;
        p_memory = malloc(sizeof(T_memBlockHeader)+size) ;
//DebugCheck(_heapchk() == _HEAPOK) ;

        /* If the memory was not allocated, check to see if */
        /* Memory can be allocated. */
        if (p_memory == NULL)  {
            /* Check if there are blocks that we can discard. */
            if (IMemFindFreeSpace()==TRUE)  {
                /* If there is, note that we have not found memory */
                /* so the loop continues trying to allocate. */
                memFound = FALSE ;
            } else {
                /* If there is not, say we found memory to break */
                /* out of the loop (when we actually did not). */
                memFound = TRUE ;
            }
        } else {
            memFound = TRUE ;
        }
    } while (memFound == FALSE) ;

    /* Check to see if we actually got the memory. */
    if (p_memory != NULL)  {
        /* Initialize the header for this block. */
        p_header = (T_memBlockHeader *)p_memory ;

#ifdef _MEM_RECORD_ROUTINES_
       DebugGetCaller(&p_header->routine, &p_header->line) ;
#endif
#ifdef _MEM_CHECK_FULL_
       /* Place the block on the allocated block list. */
       if (G_firstFree == 0xFFFF)  {
           /* Use a fresh block. */
           DebugCheck(G_numBlocks < MAX_BLOCK_LIST) ;
           G_blockList[G_numBlocks++] = p_header ;
       } else {
           /* Take one off the free list. */
           next = (T_word32)G_blockList[G_firstFree] ;
           G_blockList[G_firstFree] = p_header ;
           G_firstFree = next ;
       }
#endif
        p_header->size = size ;
        /* Make sure the block has been tagged. */
        strcpy((char *)p_header->blockTag, "TaG") ;

        /* Make sure that the block has an id (for debugging). */
        p_header->blockId = G_allocCount++ ;

        /* Clear out the previous and next pointers. */
        p_header->p_nextBlock = p_header->p_prevBlock = NULL ;

        /* Make sure the callback routine points to no where. */
        p_header->p_callback = NULL ;

/* Get who called this routine. */
//DebugGetCaller(&p_header->routine, &p_header->line) ;

        /* Move pointer up past header. That way we can return a pointer
           to where the information really is. */
        p_memory += sizeof(T_memBlockHeader) ;
//DebugCheck(_heapchk() == _HEAPOK) ;
    }
//printf("ALLC: %d   \r", FreeMemory()) ;
//fflush(stdout) ;
//printf("alloc %d, ID: %d, @ %p, %s\n", size, p_header->blockId, p_memory, DebugGetCallerName()) ;
//fflush(stdout) ;

//DebugCheck(p_memory != NULL) ;

//#ifndef NDEBUG
    /* Add to the total amount of memory allocated this size. */
    G_sizeAllocated += sizeof(T_memBlockHeader)+size ;

    /* Is this the biggest it has ever been? */
    if (G_sizeAllocated > G_maxSizeAllocated)
        /* Yes, it is bigger.  Store this new maximum. */
        G_maxSizeAllocated = G_sizeAllocated ;
//#endif

    DebugEnd() ;

#ifndef REAL_MODE
    if (p_memory==NULL)
    {
        /* fail hard! out of memory ! */
        GrGraphicsOff();
        printf ("Out of memory error, exiting\n");
        MemDumpDiscarded() ;
        exit(-1);
    }
#endif
#ifdef COMPILE_OPTION_OUTPUT_ALLOCATION
printf("(@0x%08X)\n", p_memory) ;
#endif
    return p_memory ;
}