[comp.sys.amiga.tech] Manx-C and realloc

ng@maxwell.physics.purdue.edu (Nicholas J. Giordano) (04/07/90)

I am using Manx 3.6a, and had the need for realloc() the other
day.  Unfortunately the linker couldn't find it, and neither could I!

I am using 16 bit ints.  realloc() doesn't seem to be in c.lib, or
heapmem.o.  I seem to recall that this has been discussed several times
before in this group, but I don't remember the answer.

Sorry for the duplication, but where is realloc()???

Nick
ng@maxwell.physics.purdue.edu

crash@ckctpa.UUCP (Frank J. Edwards) (04/07/90)

>I am using Manx 3.6a, and had the need for realloc() the other
>day.  Unfortunately the linker couldn't find it, and neither could I!
>
>I am using 16 bit ints.  realloc() doesn't seem to be in c.lib, or
>heapmem.o.  I seem to recall that this has been discussed several times
>before in this group, but I don't remember the answer.
>
>Sorry for the duplication, but where is realloc()???
>
>Nick
>ng@maxwell.physics.purdue.edu

The realloc() routine is in heapmem.o in your Library directory.  There
are multiple versions, i.e. ".o32", ".ol32", etc, for each of the memory
models.

However, there's a bug in the 16-bit int version.  Use the one included
here instead.  This came from the Manx BBS, so it shouldn't be a problem
to post it here.  You will need to compile it once for each memory model
that you intend to use.

Good Luck!!!

----- cut here ----- cut here ----- cut here ----- cut here -----
/* Copyright (C) 1987 by Manx Software Systems, Inc. */

unsigned long _Heapsize = 40 * 1024L;

typedef long size_t;
#define bump(p,i) ((l_t *)((char *)(p)+(i)))
#define ptrdiff(p1,p2) (unsigned long)((char *)(p1)-(char *)(p2))

typedef struct list {
	struct list *next;
} l_t;

static l_t first, *current;
static l_t *endmarker = &first, *restart = &first;
static size_t keep;

#define INUSE	1
#define inuse(p) (*(size_t *)(p)&INUSE)
#define markblk(p) (*(size_t *)(p) |= INUSE)
#define unmark(p) (*(size_t *)(p) &= ~INUSE)
#define chain(p)	((l_t *)(*(size_t *)(p) & ~INUSE))

#define BLOCK	(512*sizeof(l_t))	/* # of bytes to ask sbrk for */

char *realloc(area, size)
register char *area; unsigned size;
{
	register char *cp, *end;
	size_t osize;
	char *malloc();

	end = (char *)chain((l_t *)area-1);
	if ((osize = ptrdiff(end, area)) > size) {
		osize = size;
		end = (char *)bump(area, osize);
	}
	free(area);
	if ((cp = malloc(size)) != 0 && cp != area) {
		movmem(area, cp, (int) osize);
		/*               ^^^^^  THE BUG!  This was missing! */
		if ((char *)current >= area && (char *)current < end)
			*(size_t *)bump(cp, ptrdiff(current,area)) = keep;
	}
	return cp;
}

char *lmalloc(size)
unsigned long size;
{
	register l_t *ptr, *temp, *lastfree;
	register size_t len;
	int times;
	char *sbrk();

	size = ((size+sizeof(l_t)*2-1)/sizeof(l_t))*sizeof(l_t);
	if (current == 0) {
		first.next = &first;
		markblk(&first);
		current = &first;
	}
	for (times = 0, lastfree = ptr = current ; ; ptr = chain(ptr)) {
		if (ptr == endmarker) {
			if (++times > 1) {
				len = BLOCK;
				if ((temp = (l_t *)sbrk((int)len)) == (l_t *)-1)
					return 0;
				if (temp != bump(ptr,sizeof(l_t))) {
					/* non-contiguous allocation */
					ptr->next = temp;
					markblk(ptr);
					len -= sizeof(l_t);
					ptr = temp;
				}
				temp = bump(ptr, len);
				ptr->next = temp;
				temp->next = &first;	/* new end marker */
				markblk(temp);
				endmarker = temp;
				if (chain(lastfree) == ptr)
					ptr = lastfree;
			}
		}
		if (inuse(ptr))
			continue;
		lastfree = ptr;
		while (!inuse(temp = chain(ptr)))
			ptr->next = temp->next;
		len = ptrdiff(temp,ptr);
		if (len >= size) {
			if (len > size) {
				ptr->next = bump(ptr, size);
				keep = *(size_t *)ptr->next;
				ptr->next->next = temp;
			}
			current = ptr->next;
			markblk(ptr);
			return (char *)(ptr+1);
		}
	}
}

char *malloc(size)
unsigned size;
{
	return(lmalloc((unsigned long)size));
}

free(p)
char *p;
{
	register l_t *ptr;

	ptr = (l_t *)p - 1;
	if (!inuse(ptr))
		return -1;
	unmark(ptr);
	current = ptr;
	return 0;
}

#include	<exec/types.h>
#include	<exec/memory.h>

char *AllocMem();

static char *data;
static size_t amt;

static cleanup()
{
	FreeMem(data, amt);
	data = 0;
}

char *sbrk(size)
unsigned size;
{
	register char *cp;
	static char *ptr;
	extern int (*_cln)();

	if (size&1)
		size++;
	if (data == 0) {
		_cln = cleanup;
		amt = _Heapsize;
		while ((data = AllocMem(amt, 0L)) == 0)
			amt -= 1024;
		ptr = data;
	}
	if (ptr+size >= data+amt)
		return(-1);
	cp = ptr;
	ptr += size;
	return(cp);
}
----- cut here ----- cut here ----- cut here ----- cut here -----
-----
Frank J. Edwards		ComputerKnowledge Corp
2677 Arjay Court		12740 Hillcrest, Suite 212
Palm Harbor, FL  34684-4505	Dallas, TX  75230
Phone:  (813) 786-3675		(214) 385-9700 / (800) 227-9700

Sullivan@cup.portal.com (sullivan - segall) (04/08/90)

>
>
>I am using Manx 3.6a, and had the need for realloc() the other
>day.  Unfortunately the linker couldn't find it, and neither could I!
>
>I am using 16 bit ints.  realloc() doesn't seem to be in c.lib, or
>heapmem.o.  I seem to recall that this has been discussed several times
>before in this group, but I don't remember the answer.
>
>Sorry for the duplication, but where is realloc()???
>
>Nick
>ng@maxwell.physics.purdue.edu

I think it was left out of the distribution.  Try:

#define realloc(x) (free(x),malloc(x))

_ 
                           -Sullivan Segall
_________________________________________________________________
 
/V\  Sullivan  was the first to learn how to jump  without moving.
 '   Is it not proper that the student should surpass the teacher?
To Quote the immortal Socrates: "I drank what?" -Sullivan
_________________________________________________________________
 
Mail to: ...sun!portal!cup.portal.com!Sullivan or
         Sullivan@cup.portal.com
 

Sullivan@cup.portal.com (sullivan - segall) (04/08/90)

>
>
>I am using Manx 3.6a, and had the need for realloc() the other
>day.  Unfortunately the linker couldn't find it, and neither could I!
>
>I am using 16 bit ints.  realloc() doesn't seem to be in c.lib, or
>heapmem.o.  I seem to recall that this has been discussed several times
>before in this group, but I don't remember the answer.
>
>Sorry for the duplication, but where is realloc()???
>
>Nick
>ng@maxwell.physics.purdue.edu

Gag! I wrote:

	#define realloc(x) (free(x),malloc(x))

what I meant to write:

	#define realloc(x,s) (free(x),malloc(x,s))

This definition requires an ANSI compliant compiler.  The comma 
operator (",") always returns its second argument as its value.
Other than that this is good ANSI C, this is completely untested
on Rev 5.0 of the Manx compiler.
 
                           -Sullivan Segall
_________________________________________________________________
 
/V\  Sullivan  was the first to learn how to jump  without moving.
 '   Is it not proper that the student should surpass the teacher?
To Quote the immortal Socrates: "I drank what?" -Sullivan
_________________________________________________________________
 
Mail to: ...sun!portal!cup.portal.com!Sullivan or
         Sullivan@cup.portal.com
 

andrewt@watnow.waterloo.edu (Andrew Thomas) (04/10/90)

In article <28705@cup.portal.com> Sullivan@cup.portal.com (sullivan - segall) writes:
> >I am using Manx 3.6a, and had the need for realloc() the other
> >day.  Unfortunately the linker couldn't find it, and neither could I!
> 
> 	#define realloc(x,s) (free(x),malloc(x,s))

Doesn't realloc also copy the contents of the original memory, so you
would need something like:

void* realloc (void* x, int oldsize, int size)
{
  void*	y;

  if (size == 0) return (NULL);
  y = (void*) malloc (size);
  if (y == NULL) return (NULL);
  if (oldsize > size) oldsize = size;
  bcopy (x, y, oldsize);
  free (x);
  return (y);
}

Realloc guarantees that the contents don't change from the old chunk
of memory to the new one, up to the smaller of the two block sizes.
Without knowing the format of the memory list header, you cannot find
the size of the old chunk, so you have to send it to the homebrew
realloc yourself.  This is why realloc is supposed to be part of the
standard memory management library.

The above is UNIX code, not Amiga.  I have never encountered a
two-argument malloc command (shows how much Amiga programming I do).
In order for the preceding #define to work, though, malloc (x,y) would
have to be identical to realloc(x,y) except that it does not free x.
This I doubt.

Hope this helps.
--

Andrew Thomas
andrewt@watnow.waterloo.edu	Systems Design Eng.	University of Waterloo
"If a million people do a stupid thing, it's still a stupid thing." - Opus

Sullivan@cup.portal.com (sullivan - segall) (04/12/90)

>In article <28705@cup.portal.com> Sullivan@cup.portal.com (sullivan - segall) writ
e
>s:
>> >I am using Manx 3.6a, and had the need for realloc() the other
>> >day.  Unfortunately the linker couldn't find it, and neither could I!
>> 
>> 	#define realloc(x,s) (free(x),malloc(x,s))
>
>Doesn't realloc also copy the contents of the original memory, so you
>would need something like:
>
>void* realloc (void* x, int oldsize, int size)
>{
>  void*	y;
>
>  if (size == 0) return (NULL);
>  y = (void*) malloc (size);
>  if (y == NULL) return (NULL);
>  if (oldsize > size) oldsize = size;
>  bcopy (x, y, oldsize);
>  free (x);
>  return (y);
>}
>
>Realloc guarantees that the contents don't change from the old chunk
>of memory to the new one, up to the smaller of the two block sizes.
>Without knowing the format of the memory list header, you cannot find
>the size of the old chunk, so you have to send it to the homebrew
>realloc yourself.  This is why realloc is supposed to be part of the
>standard memory management library.
>
Yeah, I noticed the problem with my post about 10 minutes after sending
it, but since Portal has no way of unsending a message I was stuck.

In general it is ok to memcpy the new size. (rather than the smaller
of the two.)  The only case where this would fail is when the original
is just on the edge of a physical memory barrier.  Otherwise the memcpy
will succeed and just put a bit of garbage at the end of your new allocation.
Really the pointer X shouldn't be used after it is freed either.  I really
meant that post as a quick kludge.  Someone else posted the library source
code for MANX malloc, ad free.

                           -Sullivan Segall
_________________________________________________________________
 
/V\  Sullivan  was the first to learn how to jump  without moving.
 '   Is it not proper that the student should surpass the teacher?
To Quote the immortal Socrates: "I drank what?" -Sullivan
_________________________________________________________________
 
Mail to: ...sun!portal!cup.portal.com!Sullivan or
         Sullivan@cup.portal.com