Re: Adding realloc()

2002-03-12 Thread Alfred Perlstein

* Archie Cobbs [EMAIL PROTECTED] [020311 22:00] wrote:
 Hi,
 
 I've had the need for a realloc() in the kernel several times
 before and am having it once again. Finally figured it's time to
 do something about it.
 
 Does anyone have problems with the attached patch? This patch adds
 realloc() and also fixes the semantics of free() to be consistent
 with userland, in that free(NULL) is legal and does nothing. This
 will make it possible to simplify some netgraph code and probably
 other stuff too. Reviews appreciated as well.

Where is the update to malloc(9)?  What about reallocf?

-Alfred

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Adding realloc()

2002-03-12 Thread Archie Cobbs

Alfred Perlstein writes:
  I've had the need for a realloc() in the kernel several times
  before and am having it once again. Finally figured it's time to
  do something about it.
 
 Where is the update to malloc(9)?  What about reallocf?

Good points, thanks.. try this one instead.

-Archie

__
Archie Cobbs * Packet Design * http://www.packetdesign.com


Index: sys/kern/kern_malloc.c
===
RCS file: /home/ncvs/src/sys/kern/kern_malloc.c,v
retrieving revision 1.93
diff -u -r1.93 kern_malloc.c
--- kern_malloc.c	12 Sep 2001 08:37:44 -	1.93
+++ kern_malloc.c	12 Mar 2002 22:34:35 -
 -57,6 +57,16 
 #include machine/cpu.h
 #endif
 
+/*
+ * When realloc() is called, if the new size is sufficiently smaller than
+ * the old size, realloc() will allocate a new, smaller block to avoid
+ * wasting memory. 'Sufficiently smaller' is defined as: newsize =
+ * oldsize / 2^n, where REALLOC_FRACTION defines the value of 'n'.
+ */
+#ifndef REALLOC_FRACTION
+#define	REALLOC_FRACTION	1	/* new block if = half the size */
+#endif
+
 MALLOC_DEFINE(M_CACHE, cache, Various Dynamically allocated caches);
 MALLOC_DEFINE(M_DEVBUF, devbuf, device driver memory);
 MALLOC_DEFINE(M_TEMP, temp, misc temporary data buffers);
 -294,6 +304,10 
 #endif
 	register struct malloc_type *ksp = type;
 
+	/* free(NULL, ...) does nothing */
+	if (addr == NULL)
+		return;
+
 	KASSERT(kmembase = (char *)addr  (char *)addr  kmemlimit,
 	(free: address %p out of range, (void *)addr));
 	kup = btokup(addr);
 -397,6 +411,66 
 #endif
 	splx(s);
 	mtx_unlock(malloc_mtx);
+}
+
+/*
+ *	realloc: change the size of a memory block
+ */
+void *
+realloc(addr, size, type, flags)
+	void *addr;
+	unsigned long size;
+	struct malloc_type *type;
+	int flags;
+{
+	struct kmemusage *kup;
+	unsigned long alloc;
+	void *newaddr;
+
+	/* realloc(NULL, ...) is equivalent to malloc(...) */
+	if (addr == NULL)
+		return (malloc(size, type, flags));
+
+	/* Sanity check */
+	KASSERT(kmembase = (char *)addr  (char *)addr  kmemlimit,
+	(realloc: address %p out of range, (void *)addr));
+
+	/* Get the size of the original block */
+	kup = btokup(addr);
+	alloc = 1  kup-ku_indx;
+	if (alloc  MAXALLOCSAVE)
+		alloc = kup-ku_pagecnt  PAGE_SHIFT;
+
+	/* Reuse the original block if appropriate */
+	if (size = alloc
+	 (size  (alloc  REALLOC_FRACTION) || alloc == MINALLOCSIZE))
+		return (addr);
+
+	/* Allocate a new, bigger (or smaller) block */
+	if ((newaddr = malloc(size, type, flags)) == NULL)
+		return (NULL);
+
+	/* Copy over original contents */
+	bcopy(addr, newaddr, min(size, alloc));
+	free(addr, type);
+	return (newaddr);
+}
+
+/*
+ *	reallocf: same as realloc() but free memory on failure.
+ */
+void *
+reallocf(addr, size, type, flags)
+	void *addr;
+	unsigned long size;
+	struct malloc_type *type;
+	int flags;
+{
+	void *mem;
+
+	if ((mem = realloc(addr, size, type, flags)) == NULL)
+		free(addr, type);
+	return (mem);
 }
 
 /*
Index: sys/sys/malloc.h
===
RCS file: /home/ncvs/src/sys/sys/malloc.h,v
retrieving revision 1.54
diff -u -r1.54 malloc.h
--- malloc.h	10 Aug 2001 06:37:04 -	1.54
+++ malloc.h	12 Mar 2002 22:34:46 -
 -173,6 +173,10 
 void	*malloc __P((unsigned long size, struct malloc_type *type, int flags));
 void	malloc_init __P((void *));
 void	malloc_uninit __P((void *));
+void	*realloc __P((void *addr, unsigned long size,
+		  struct malloc_type *type, int flags));
+void	*reallocf __P((void *addr, unsigned long size,
+		  struct malloc_type *type, int flags));
 #endif /* _KERNEL */
 
 #endif /* !_SYS_MALLOC_H_ */
Index: share/man/man9/malloc.9
===
RCS file: /home/ncvs/src/share/man/man9/malloc.9,v
retrieving revision 1.21
diff -u -r1.21 malloc.9
--- malloc.9	1 Oct 2001 16:09:25 -	1.21
+++ malloc.9	12 Mar 2002 22:34:57 -
 -54,18 +54,63 
 .Ft void
 .Fn free void *addr struct malloc_type *type
 .Fn FREE void *addr struct malloc_type *type
+.Ft void *
+.Fn realloc void *addr unsigned long size struct malloc_type *type int flags
+.Ft void *
+.Fn reallocf void *addr unsigned long size struct malloc_type *type int flags
 .Sh DESCRIPTION
 The
 .Fn malloc
 function allocates uninitialized memory in kernel address space for an
 object whose size is specified by
 .Fa size .
+.Pp
 .Fn free
 releases memory at address
 .Fa addr
 that was previously allocated by
 .Fn malloc
-for re-use.  The memory is not zeroed.
+for re-use.
+The memory is not zeroed.
+If
+.Fa addr
+is
+.Dv NULL ,
+then
+.Fn free
+does nothing.
+.Pp
+The
+.Fn realloc
+function changes the size of the previously allocated memory referenced by
+.Fa addr
+to
+.Fa size
+bytes.
+The contents of the memory are unchanged up to the lesser of the new and
+old sizes.
+Note that the returned value may 

Re: Adding realloc()

2002-03-12 Thread Alfred Perlstein

* Archie Cobbs [EMAIL PROTECTED] [020312 14:45] wrote:
 Alfred Perlstein writes:
   I've had the need for a realloc() in the kernel several times
   before and am having it once again. Finally figured it's time to
   do something about it.
  
  Where is the update to malloc(9)?  What about reallocf?
 
 Good points, thanks.. try this one instead.

That looks ok, afaik you could do some vm tricks to avoid having
to malloc/free when doing realloc()'s that are larger than PAGE_SIZE.

-Alfred

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Re: Adding realloc()

2002-03-12 Thread Archie Cobbs

Alfred Perlstein writes:
I've had the need for a realloc() in the kernel several times
before and am having it once again. Finally figured it's time to
do something about it.
   
   Where is the update to malloc(9)?  What about reallocf?
  
  Good points, thanks.. try this one instead.
 
 That looks ok, afaik you could do some vm tricks to avoid having
 to malloc/free when doing realloc()'s that are larger than PAGE_SIZE.

Yeah I was wondering about that  how hard it would be.
That'd be the next step I guess.. thanks for the comments.

-Archie

__
Archie Cobbs * Packet Design * http://www.packetdesign.com

To Unsubscribe: send mail to [EMAIL PROTECTED]
with unsubscribe freebsd-current in the body of the message



Adding realloc()

2002-03-11 Thread Archie Cobbs

Hi,

I've had the need for a realloc() in the kernel several times
before and am having it once again. Finally figured it's time to
do something about it.

Does anyone have problems with the attached patch? This patch adds
realloc() and also fixes the semantics of free() to be consistent
with userland, in that free(NULL) is legal and does nothing. This
will make it possible to simplify some netgraph code and probably
other stuff too. Reviews appreciated as well.

Thanks,
-Archie

__
Archie Cobbs * Packet Design * http://www.packetdesign.com


Index: kern/kern_malloc.c
===
RCS file: /home/ncvs/src/sys/kern/kern_malloc.c,v
retrieving revision 1.93
diff -u -r1.93 kern_malloc.c
--- kern_malloc.c	12 Sep 2001 08:37:44 -	1.93
+++ kern_malloc.c	12 Mar 2002 00:06:03 -
 -57,6 +57,16 
 #include machine/cpu.h
 #endif
 
+/*
+ * When realloc() is called, if the new size is sufficiently smaller than
+ * the old size, realloc() will allocate a new, smaller block to avoid
+ * wasting memory. 'Sufficiently smaller' is defined as: newsize =
+ * oldsize / 2^n, where REALLOC_FRACTION defines the value of 'n'.
+ */
+#ifndef REALLOC_FRACTION
+#define	REALLOC_FRACTION	1	/* new block if = half the size */
+#endif
+
 MALLOC_DEFINE(M_CACHE, cache, Various Dynamically allocated caches);
 MALLOC_DEFINE(M_DEVBUF, devbuf, device driver memory);
 MALLOC_DEFINE(M_TEMP, temp, misc temporary data buffers);
 -294,6 +304,10 
 #endif
 	register struct malloc_type *ksp = type;
 
+	/* free(NULL, ...) does nothing */
+	if (addr == NULL)
+		return;
+
 	KASSERT(kmembase = (char *)addr  (char *)addr  kmemlimit,
 	(free: address %p out of range, (void *)addr));
 	kup = btokup(addr);
 -397,6 +411,49 
 #endif
 	splx(s);
 	mtx_unlock(malloc_mtx);
+}
+
+/*
+ *	realloc: change the size of a memory block
+ */
+void *
+realloc(addr, size, type, flags)
+	void *addr;
+	unsigned long size;
+	struct malloc_type *type;
+	int flags;
+{
+	struct kmemusage *kup;
+	unsigned long alloc;
+	void *newaddr;
+
+	/* realloc(NULL, ...) is equivalent to malloc(...) */
+	if (addr == NULL)
+		return (malloc(size, type, flags));
+
+	/* Sanity check */
+	KASSERT(kmembase = (char *)addr  (char *)addr  kmemlimit,
+	(realloc: address %p out of range, (void *)addr));
+
+	/* Get the size of the original block */
+	kup = btokup(addr);
+	alloc = 1  kup-ku_indx;
+	if (alloc  MAXALLOCSAVE)
+		alloc = kup-ku_pagecnt  PAGE_SHIFT;
+
+	/* Reuse the original block if appropriate */
+	if (size = alloc
+	 (size  (alloc  REALLOC_FRACTION) || alloc == MINALLOCSIZE))
+		return (addr);
+
+	/* Allocate a new, bigger (or smaller) block */
+	if ((newaddr = malloc(size, type, flags)) == NULL)
+		return (NULL);
+
+	/* Copy over original contents */
+	bcopy(addr, newaddr, min(size, alloc));
+	free(addr, type);
+	return (newaddr);
 }
 
 /*
Index: sys/malloc.h
===
RCS file: /home/ncvs/src/sys/sys/malloc.h,v
retrieving revision 1.54
diff -u -r1.54 malloc.h
--- malloc.h	10 Aug 2001 06:37:04 -	1.54
+++ malloc.h	12 Mar 2002 00:06:12 -
 -173,6 +173,8 
 void	*malloc __P((unsigned long size, struct malloc_type *type, int flags));
 void	malloc_init __P((void *));
 void	malloc_uninit __P((void *));
+void	*realloc __P((void *addr, unsigned long size,
+		  struct malloc_type *type, int flags));
 #endif /* _KERNEL */
 
 #endif /* !_SYS_MALLOC_H_ */