home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
dbmalloc-1.14-src.tgz
/
tar.out
/
contrib
/
dbmalloc
/
realloc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
11KB
|
491 lines
/*
* (c) Copyright 1990, 1991, 1992 Conor P. Cahill (cpcahil@virtech.vti.com)
*
* This software may be distributed freely as long as the following conditions
* are met:
* * the distribution, or any derivative thereof, may not be
* included as part of a commercial product
* * full source code is provided including this copyright
* * there is no charge for the software itself (there may be
* a minimal charge for the copying or distribution effort)
* * this copyright notice is not modified or removed from any
* source file
*/
#ifndef lint
static
char rcs_hdr[] = "$Id: realloc.c,v 1.26 1992/09/03 22:24:33 cpcahil Exp $";
#endif
#include <stdio.h>
#include "mallocin.h"
DATATYPE *
realloc(cptr,size)
DATATYPE * cptr;
SIZETYPE size;
{
return( debug_realloc(NULL,-1,cptr,size) );
}
DATATYPE *
debug_realloc(file,line,cptr,size)
CONST char * file;
int line;
DATATYPE * cptr;
SIZETYPE size;
{
static IDTYPE call_counter;
/*
* increment the call counter
*/
call_counter++;
return( DBFrealloc("realloc",M_T_REALLOC,call_counter,
file,line,cptr,size) );
}
/*
* Function: DBFrealloc()
*
* Purpose: to re-allocate a data area.
*
* Arguments: cptr - pointer to area to reallocate
* size - size to change area to
*
* Returns: pointer to new area (may be same area)
*
* Narrative: verify pointer is within malloc region
* obtain mlist pointer from cptr
* verify magic number is correct
* verify inuse flag is set
* verify connection to adjoining segments is correct
* save requested size
* round-up size to appropriate boundry
* IF size is bigger than what is in this segment
* try to join next segment to this segment
* IF size is less than what is is this segment
* determine leftover amount of space
* ELSE
* allocate new segment of size bites
* IF allocation failed
* return NULL
* copy previous data to new segment
* free previous segment
* return new pointer
* split of extra space in this segment (if any)
* clear bytes beyound what they had before
* return pointer to data
*/
DATATYPE *
DBFrealloc(func,type,call_counter,file,line,cptr,size)
CONST char * func;
int type;
IDTYPE call_counter;
CONST char * file;
int line;
DATATYPE * cptr;
SIZETYPE size;
{
SIZETYPE i;
char * new_cptr;
int marked;
SIZETYPE need;
struct mlist * optr;
struct mlist * ptr;
SIZETYPE r_size;
SIZETYPE start;
MALLOC_INIT();
/*
* IF malloc chain checking is on, go do it.
*/
if( malloc_opts & MOPT_CKCHAIN )
{
VOIDCAST DBFmalloc_chain_check(func,file,line,1);
}
/*
* if the user wants to be warned about zero length mallocs, do so
*/
if( ((malloc_opts & MOPT_ZERO) != 0) && (size == 0) )
{
malloc_errno = M_CODE_ZERO_ALLOC;
malloc_warning(func,file,line,(struct mlist *)NULL);
}
/*
* if this is an ansi-c compiler and we want to use the realloc(0)
* paradigm, or if this is a call from xtrealloc, then if the
* pointer is a null, act as if this is a call to malloc.
*/
#if defined(ANSI_NULLS) || (__STDC__ && ! defined(NO_ANSI_NULLS))
if( cptr == NULL )
#else
if( (cptr == NULL) && (type == M_T_XTREALLOC) )
#endif
{
/*
* allocate the new chunk
*/
new_cptr = DBFmalloc(func,type,call_counter,file,line,size);
return(new_cptr);
}
/*
* verify that cptr is within the malloc region...
*/
if( (cptr < malloc_data_start)
|| (cptr > malloc_data_end)
|| ((((long)cptr) & malloc_round) != 0 ) )
{
malloc_errno = M_CODE_BAD_PTR;
malloc_warning(func,file,line,(struct mlist *)NULL);
return (NULL);
}
/*
* convert pointer to mlist struct pointer. To do this we must
* move the pointer backwards the correct number of bytes...
*/
ptr = (struct mlist *) (((char *)cptr) - M_SIZE);
if( (ptr->flag&M_MAGIC_BITS) != M_MAGIC )
{
malloc_errno = M_CODE_BAD_MAGIC;
malloc_warning(func,file,line,(struct mlist *)NULL);
return(NULL);
}
if( ! (ptr->flag & M_INUSE) )
{
malloc_errno = M_CODE_NOT_INUSE ;
malloc_warning(func,file,line,ptr);
return(NULL);
}
if( (ptr->prev && (ptr->prev->next != ptr) ) ||
(ptr->next && (ptr->next->prev != ptr) ) ||
((ptr->next == NULL) && (ptr->prev == NULL)) )
{
malloc_errno = M_CODE_BAD_CONNECT;
malloc_warning(func,file,line,ptr);
return(NULL);
}
/*
* save the marked status
*/
marked = ptr->flag & M_MARKED;
/*
* save the requested size;
*/
r_size = size;
/*
* make sure we have the full boundary that is needed
*/
size += malloc_boundsize;
M_ROUNDUP(size);
if( (size > ptr->s.size) && ((malloc_opts & MOPT_REUSE) != 0) )
{
malloc_join(ptr,ptr->next,INUSEOK,DOFILL);
}
/*
* if we still don't have enough room, and we are at the end of the
* malloc chain and we are up against the current sbrk, we can just
* sbrk more room for our data area.
*/
if( (size > ptr->s.size)
&& (ptr == malloc_end)
&& ((ptr->data+ptr->s.size) == sbrk(0) ) )
{
need = size - ptr->s.size;
/*
* if the need is less than the minimum block size,
* get the minimum block size
*/
if( need < M_BLOCKSIZE )
{
need = M_BLOCKSIZE;
}
/*
* else if the need is not an even multiple of the block size,
* round it up to an even multiple
*/
else if( need & (M_BLOCKSIZE-1) )
{
need &= ~(M_BLOCKSIZE-1);
need += M_BLOCKSIZE;
}
/*
* get the space from the os
*/
cptr = sbrk(need);
/*
* if we failed to get the space, tell the user about it
*/
if( cptr == (char *) -1 )
{
malloc_errno = M_CODE_NOMORE_MEM;
malloc_fatal(func,file,line, (struct mlist *)NULL);
return(NULL);
}
/*
* adjust our segment size (extra space will be split off later
*/
start = ptr->s.size;
ptr->s.size += need;
/*
* we have to act like this was a join of a new segment so
* we need to call the fill routine to get it to fill the
* new data area.
*/
FILLDATA(ptr,FILL_JOIN,start,(struct mlist *)NULL);
/*
* mark our end point
*/
malloc_data_end = sbrk((int)0);
}
/*
* if the size is still too small and the previous segment is free
* and it would be big enough it if was joined to the current segment
*/
if( ((malloc_opts & MOPT_CKCHAIN) != 0)
&& (size > ptr->s.size)
&& ((ptr->prev->flag & M_INUSE) == 0)
&& (size < (ptr->s.size + ptr->prev->s.size + M_SIZE) ) )
{
/*
* save the old pointer
*/
optr = ptr;
/*
* move out pointer to the proper area.
*/
ptr = ptr->prev;
/*
* force this pointer to be inuse
*/
ptr->flag |= M_INUSE;
ptr->r_size = ptr->next->r_size;
/*
* join the two segments
*/
malloc_join(ptr, ptr->next, ANY_INUSEOK, DONTFILL);
/*
* remove ptr from the free list
*/
malloc_freeseg(M_FREE_REMOVE,ptr);
/*
* copy data from the current space to the new space. Note
* that the data areas for this copy will likely overlap.
*/
DataMC(ptr->data,optr->data,ptr->r_size);
/*
* note that we don't fill in the areas here. It will be
* filled later
*/
}
if( size > ptr->s.size )
{
/*
* else we can't combine it, so lets allocate a new chunk,
* copy the data and free the old chunk...
*/
new_cptr = DBFmalloc(func,type,call_counter,file,line,size);
if( new_cptr == (char *) 0)
{
return(new_cptr);
}
if( r_size < ptr->r_size )
{
i = r_size;
}
else
{
i = ptr->r_size;
}
in_malloc_code++;
VOIDCAST memcpy(new_cptr,ptr->data,i);
in_malloc_code--;
/*
* if the old segment was marked, unmark it and mark the new
* segment.
*/
if( marked )
{
ptr->flag &= ~M_MARKED;
malloc_mark(new_cptr);
}
/*
* free the old segment since it is no longer needed.
*/
DBFfree("realloc:free",F_T_REALLOC,call_counter,file,line,cptr);
return(new_cptr);
} /* if( size... */
/*
* save amount of real data in new segment (this will be used in the
* memset later) and then save requested size of this segment.
*/
if( ptr->r_size < r_size )
{
i = ptr->r_size;
}
else
{
i = r_size;
}
ptr->r_size = r_size;
/*
* split off extra free space at end of this segment, if possible...
*/
malloc_split(ptr);
/*
* save the id info.
*/
ptr->file = file;
ptr->line = line;
ptr->id = call_counter;
ptr->hist_id = malloc_hist_id++;
ptr->stack = StackCurrent();
ptr->freestack = NULL;
SETTYPE(ptr,type);
/*
* fill data and/or boundary areas
*/
FILLDATA(ptr,FILL_REALLOC,i, (struct mlist *) NULL);
return(ptr->data);
} /* DBFrealloc(... */
/*
* $Log: realloc.c,v $
* Revision 1.26 1992/09/03 22:24:33 cpcahil
* final changes for PL14
*
* Revision 1.25 1992/08/22 16:27:13 cpcahil
* final changes for pl14
*
* Revision 1.24 1992/07/03 00:03:25 cpcahil
* more fixes for pl13, several suggestons from Rich Salz.
*
* Revision 1.23 1992/05/14 23:02:27 cpcahil
* added support for ANSI NULL behavior even with non-ansi compilers (if
* chosen at compile time).
*
* Revision 1.22 1992/05/08 02:30:35 cpcahil
* minor cleanups from minix/atari port
*
* Revision 1.21 1992/05/06 05:37:44 cpcahil
* added overriding of fill characters and boundary size
*
* Revision 1.20 1992/05/06 04:53:29 cpcahil
* performance enhancments
*
* Revision 1.19 1992/04/22 18:17:32 cpcahil
* added support for Xt Alloc functions, linted code
*
* Revision 1.18 1992/04/13 03:06:33 cpcahil
* Added Stack support, marking of non-leaks, auto-config, auto-testing
*
* Revision 1.17 1992/03/01 12:42:38 cpcahil
* added support for managing freed areas and fixed doublword bndr problems
*
* Revision 1.16 1992/01/30 12:23:06 cpcahil
* renamed mallocint.h -> mallocin.h
*
* Revision 1.15 1992/01/10 17:28:03 cpcahil
* Added support for overriding void datatype
*
* Revision 1.14 1991/12/06 08:54:19 cpcahil
* cleanup of __STDC__ usage and addition of CHANGES file
*
* Revision 1.13 91/12/04 09:23:44 cpcahil
* several performance enhancements including addition of free list
*
* Revision 1.12 91/12/02 19:10:14 cpcahil
* changes for patch release 5
*
* Revision 1.11 91/11/25 14:42:05 cpcahil
* Final changes in preparation for patch 4 release
*
* Revision 1.10 91/11/24 00:49:32 cpcahil
* first cut at patch 4
*
* Revision 1.9 91/11/20 11:54:11 cpcahil
* interim checkin
*
* Revision 1.8 90/08/29 21:22:52 cpcahil
* miscellaneous lint fixes
*
* Revision 1.7 90/05/11 00:13:10 cpcahil
* added copyright statment
*
* Revision 1.6 90/02/25 11:01:20 cpcahil
* added support for malloc chain checking.
*
* Revision 1.5 90/02/24 21:50:31 cpcahil
* lots of lint fixes
*
* Revision 1.4 90/02/24 17:29:39 cpcahil
* changed $Header to $Id so full path wouldnt be included as part of rcs
* id string
*
* Revision 1.3 90/02/24 17:20:00 cpcahil
* attempt to get rid of full path in rcs header.
*
* Revision 1.2 90/02/24 15:14:20 cpcahil
* 1. added function header
* 2. changed calls to malloc_warning to conform to new usage
* 3. added setting of malloc_errno
* 4. broke up bad pointer determination so that errno's would be more
* descriptive
*
* Revision 1.1 90/02/22 23:17:43 cpcahil
* Initial revision
*
*/