head 4.4; access ; symbols ; locks oasisa:4.4; strict; comment @ * @; 4.4 date 2001.06.19.12.14.36; author oasisa; state Exp; branches ; next ; desc @New Repository; 6/19/2001 (klh) @ 4.4 log @New Repository; 6/19/2001 (klh) @ text @/****************************************************************************/ /* Copyright 1990-1994 MBARI */ /****************************************************************************/ /* Summary : C malloc utility */ /* Filename : malloc.c */ /* Author : Andrew Pearce */ /* Project : OASIS Microcontroller */ /* $Revision: 1.1 $ */ /* Created : 11/21/90, Andrew Pearce */ /* */ /* MBARI provides this documentation and code "as is", with no warranty, */ /* express or implied, of its quality or consistency. It is provided without*/ /* support and without obligation on the part of the Monterey Bay Aquarium */ /* Research Institute to assist in its use, correction, modification, or */ /* enhancement. This information should not be published or distributed to */ /* third parties without specific written permission from MBARI. */ /* */ /****************************************************************************/ /* Modification History: */ /* 12dec94, rah, modified for OASIS */ /* $Log: malloc.c,v $ * Revision 1.1 2001/06/19 11:44:10 11:44:10 oasisa (Oasis users) * Initial revision * * Revision 4.3 99/06/16 10:21:40 10:21:40 bobh (Bob Herlien) * Mar/May '99 Deployments of M3/M2 * * Revision 4.1 98/05/12 09:35:16 09:35:16 bobh (Bob Herlien) * June '98 turnaround for EqPac * * Revision 3.0 95/02/21 18:42:54 18:42:54 hebo (Bob Herlien) * February '95 Deployment * */ /****************************************************************************/ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* OASIS controller definitions */ #include /* String library functions */ #include /* OASIS Multitasking definitions */ typedef struct malloc_hdr /************************************/ { /* Header for malloc'd memory */ struct malloc_hdr *next_hdr_ptr; /* Link to next header */ Nat16 size; /* Segment Size - LSB is allocated bit*/ } MallocHdr; /************************************/ #define MIN_SEG_SIZE 16 /* Minimum fragment size */ #define set_alloc_bit(x) (x->size |= 0x01) #define clear_alloc_bit(x) (x->size &= ~0x01) #define test_alloc_bit(x) (x->size & 0x01) #define set_size_free(x, s) x->size = (s & ~0x01) #define set_size_alloc(x, s) x->size = (s | 0x01) #define get_size(x) (x->size & ~0x01) #define MH_NULL ((MallocHdr *)0) /********************************/ /* External Data */ /********************************/ Extern const Nat16 free_mem; /* Start of free memory */ Extern const Nat16 mem_size; /* Free memory size */ /********************************/ /* Global Data */ /********************************/ Global Nat16 tmpRamStart; Global Nat16 tmpRamLen; /********************************/ /* Module Local Data */ /********************************/ MLocal MallocHdr *tmpMallocHead; /* Head of tmp memory pool */ MLocal MallocHdr *permMallocHead; /* Head of perm memory pool */ /****************************************************************************/ /* Function : checkLink */ /* Purpose : Internal routine which checks integrty of malloc pool */ /* Inputs : memory pool header */ /* Outputs : Returns TRUE if link is OK, else FALSE */ /****************************************************************************/ MLocal MBool checkLink( MallocHdr *mhp ) { if ( (mhp->next_hdr_ptr == MH_NULL) || (mhp->next_hdr_ptr == (MallocHdr *) ((char *)mhp + sizeof(MallocHdr) + get_size(mhp))) ) return(TRUE); return(FALSE); } /* checkLink() */ /****************************************************************************/ /* Function : initMallocPool */ /* Purpose : Initialize memory pool */ /* Inputs : None */ /* Outputs : None */ /****************************************************************************/ Void initMallocPool( MallocHdr **hdrpp, char *start, Nat16 size ) { Reg MallocHdr *mhp; *hdrpp = mhp = (MallocHdr *)start; /* Set start of allocatable memory*/ set_size_free(mhp, size - sizeof(MallocHdr)); mhp->next_hdr_ptr = MH_NULL; /* Set tail link to NULL */ } /* initMallocPool() */ /****************************************************************************/ /* Function : mallocInit */ /* Purpose : Warm Boot initialize routine for malloc library */ /* Inputs : None */ /* Outputs : None */ /****************************************************************************/ Void mallocInit( Void ) { tmpRamStart = (free_mem + (sizeof(Nat32) - 1)) & ~(sizeof(Nat32) - 1); tmpRamLen = mem_size & ~(sizeof(Nat32) - 1); initMallocPool( &tmpMallocHead, (char *)tmpRamStart, tmpRamLen ); } /* mallocInit() */ /****************************************************************************/ /* Function : mallocColdInit */ /* Purpose : Cold Boot initialize routine for malloc library */ /* Inputs : None */ /* Outputs : None */ /****************************************************************************/ Void mallocColdInit( Void ) { initMallocPool( &permMallocHead, (char *)PERM_RAM, PERM_RAM_SIZE ); mallocInit(); } /* mallocColdInit() */ /****************************************************************************/ /* Function : mallocFromPool */ /* Purpose : Allocates memory from the specified memory pool */ /* Inputs : size of memory area and memory pool header */ /* Outputs : Returns pointer to memory or NULL if not enough memory */ /****************************************************************************/ MLocal char * mallocFromPool( Nat16 sz, MallocHdr *malloc_header ) { Reg MallocHdr *mh, *next_mh; Reg Nat16 size; size = (sz + (sizeof(Nat32) - 1)) & ~(sizeof(Nat32) - 1); /* Align on longword boundaries */ for ( mh = malloc_header; mh != MH_NULL; mh = mh->next_hdr_ptr ) { if ( !checkLink(mh) ) /* If memory segment bad, return NULL*/ return( NULL ); if ( test_alloc_bit(mh) ) /* If this segment allocated, do next*/ continue; /* Segment is free */ while ( (mh->next_hdr_ptr != MH_NULL) && (test_alloc_bit(mh->next_hdr_ptr) == 0) ) { /* If the next segment is free then */ /* coalesce the two segments */ next_mh = mh->next_hdr_ptr; set_size_free(mh, mh->size+sizeof(MallocHdr)+get_size(next_mh)); mh->next_hdr_ptr = next_mh->next_hdr_ptr; } if ( get_size(mh) >= size ) /* Is this segment big enough? */ { /* If yes, is it big enough to split?*/ if ( get_size(mh) >= (size + sizeof(MallocHdr) + MIN_SEG_SIZE)) { /* Calculate address of new header */ next_mh = (MallocHdr *) ((char *)(mh) + sizeof(MallocHdr) + size); /* Fill in size, set unallocated */ set_size_free(next_mh, get_size(mh)-size-sizeof(MallocHdr)); /* Insert this node into the list */ next_mh->next_hdr_ptr = mh->next_hdr_ptr; mh->next_hdr_ptr = next_mh; set_size_alloc(mh, size); /* Set the size of segment */ } set_alloc_bit(mh); /* Set segment as allocated */ return( (char *)mh + sizeof(MallocHdr) ); /* Return malloc'd segment */ } /* if */ } /* for */ return( NULL ); /* We're out of memory - return NULL*/ } /* mallocFromPool() */ /****************************************************************************/ /* Function : tmpMalloc */ /* Purpose : Allocate memory from temporary RAM pool */ /* Inputs : size of desired memory area in bytes */ /* Outputs : Returns pointer to memory or NULL if not enough memory */ /* Note : This function may NOT be called from interrupt context */ /****************************************************************************/ char * tmpMalloc( Nat16 size ) { return( mallocFromPool(size, tmpMallocHead) ); } /* tmpMalloc() */ /****************************************************************************/ /* Function : tmpFree */ /* Purpose : Release memory previously allocated with tmpMalloc */ /* Inputs : pointer to memory from prior malloc */ /* Outputs : None */ /* Note : This function may be called from interrupt context */ /****************************************************************************/ Void tmpFree( char *ptr ) { MallocHdr *mhp; mhp = (MallocHdr *)(ptr - sizeof(MallocHdr)); clear_alloc_bit(mhp); } /* tmpFree() */ /****************************************************************************/ /* Function : permMalloc */ /* Purpose : Allocate memory from permanent RAM pool */ /* Inputs : size of desired memory area in bytes */ /* Outputs : Returns pointer to memory or NULL if not enough memory */ /* Note : This function may NOT be called from interrupt context */ /****************************************************************************/ char * permMalloc( Nat16 size ) { return( mallocFromPool(size, permMallocHead) ); } /* permMalloc() */ /****************************************************************************/ /* Function : permFree */ /* Purpose : Release memory previously allocated with permMalloc */ /* Inputs : pointer to memory from prior malloc */ /* Outputs : None */ /* Note : This function may be called from interrupt context */ /****************************************************************************/ Void permFree( char *ptr ) { MallocHdr *mhp; mhp = (MallocHdr *)(ptr - sizeof(MallocHdr)); clear_alloc_bit(mhp); } /* permFree() */ @