Subject: Re: realloc
To: Jason Thorpe <thorpej@nas.nasa.gov>
From: Chris G Demetriou <Chris_G_Demetriou@ux2.sp.cs.cmu.edu>
List: tech-kern
Date: 06/04/1996 22:13:11
> If it were useful, a real realloc() would be cool, otherwise, writing a 
> macfs_realloc() that does the simple ralloc algorithm might be appropriate.

I decided to write a real realloc(), that does 'the right (and
efficient) thing' with our memory allocator, etc.

It is below.


It was cloned from 'free()', and hacked to suit.

Notes:
	(1) it compiles on the i386.  i've not tried to run it.
	(2) if allocation fails because M_NOWAIT supplied, doesn't
	    free old block of memory.

I'm sure there are other things to say about it, but i have to leave
to catch a bus right now...  8-)


feel free to debug it, etc.  If the right people think it's
appropriate, I can add it to kern_malloc.c...


chris
============================================================================
/*
 * Change the size of a block of memory.
 */
void *
realloc(curaddr, newsize, type, flags)
	void *curaddr;
	unsigned long newsize;
	int type, flags;
{
	register struct kmemusage *kup;
	long cursize;
	void *newaddr;
#ifdef DIAGNOSTIC
	long alloc;
#endif

	/*
	 * Realloc() with a NULL pointer is the same as malloc().
	 * Realloc() with zero size is the same as free().
	 */
	if (curaddr == NULL)
		return (malloc(newsize, type, flags));
	if (newsize == 0) {
		free(curaddr, type);
		return (NULL);
	}

	/*
	 * Find out how large the old allocation was (and do some
	 * sanity checking).
	 */
	kup = btokup(curaddr);
	cursize = 1 << kup->ku_indx;

#ifdef DIAGNOSTIC
	/*
	 * Check for returns of data that do not point to the
	 * beginning of the allocation.
	 */
	if (cursize > NBPG * CLSIZE)
		alloc = addrmask[BUCKETINDX(NBPG * CLSIZE)];
	else
		alloc = addrmask[kup->ku_indx];
	if (((u_long)curaddr & alloc) != 0)
		panic("realloc: unaligned addr %p, cursize %ld, type %s, mask %ld\n",
			curaddr, cursize, memname[type], alloc);
#endif /* DIAGNOSTIC */

	if (cursize > MAXALLOCSAVE)
		cursize = ctob(kup->ku_pagecnt);

	/*
	 * If we already actually have as much as they want, we're done.
	 */
	if (newsize <= cursize)
		return (curaddr);

	/*
	 * Can't satisfy the allocation with the existing block.
	 * Allocate a new one and copy the data.
	 */
	newaddr = malloc(newsize, type, flags);
	if (newaddr == NULL) {
		/*
		 * Malloc() failed, because flags included M_NOWAIT.
		 * Return NULL to indicate that failure.  The old
		 * pointer is still valid.
		 */
		return NULL;
	}
	bcopy(curaddr, newaddr, cursize);

	/*
	 * We were successful: free the old allocation and return
	 * the new one.
	 */
	free(curaddr, type);
	return (newaddr);
}