Subject: Re: malloc_usable_size () call under NetBSD
To: None <current-users@netbsd.org>
From: Christos Zoulas <christos@astron.com>
List: current-users
Date: 07/20/2007 16:00:33
In article <46A08CAD.8090603@free.fr>, Vincent  <10.50@free.fr> wrote:
>Hi there,
>
>I've tried to compiled the XaraLX vector graphics program that seems to 
>have been ported on FreeBSD. However, it fails at the first file, 
>complaining to lack the "malloc_usable_size ()" system call. After a bit 
>of googling (™), I found that this call had been added on FreeBSD 7 (so 
>that's pretty recent). Wherefore, question: how to emulate this call 
>under NetBSD, if this is possible.

This is not a system call it is a libc function. It takes as an argument
a pointer that was previously returned by malloc(3) and returns the
allocated space for that pointer.

Here's an untested patch...

christos

Index: malloc.c
===================================================================
RCS file: /cvsroot/src/lib/libc/stdlib/malloc.c,v
retrieving revision 1.48
diff -u -u -r1.48 malloc.c
--- malloc.c	24 Nov 2006 19:37:02 -0000	1.48
+++ malloc.c	20 Jul 2007 15:59:47 -0000
@@ -778,6 +778,63 @@
     return result;
 }
 
+size_t
+malloc_usable_size(void *ptr)
+{
+    size_t idx = ptr2idx(ptr);
+    struct pginfo **mp;
+
+    if (idx < malloc_pageshift) {
+	wrtwarning("junk pointer, too low to make sense.\n");
+	return (size_t)-1;
+    }
+
+    if (idx > last_idx) {
+	wrtwarning("junk pointer, too high to make sense.\n");
+	return (size_t)-1;
+    }
+
+    mp = &page_dir[idx];
+
+    if (*mp == MALLOC_FIRST) {			/* Page allocation */
+
+	/* Check the pointer */
+	if ((size_t)(uintptr_t)ptr & malloc_pagemask) {
+	    wrtwarning("modified (page-) pointer.\n");
+	    return (size_t)-1;
+	}
+
+	/* Find the size in bytes */
+	for (osize = malloc_pagesize; *++mp == MALLOC_FOLLOW;)
+	    osize += malloc_pagesize;
+
+	return osize;
+
+    } else if (*mp >= MALLOC_MAGIC) {		/* Chunk allocation */
+
+	/* Check the pointer for sane values */
+	if (((size_t)(uintptr_t)ptr & ((*mp)->size-1))) {
+	    wrtwarning("modified (chunk-) pointer.\n");
+	    return (size_t)-1;
+	}
+
+	/* Find the chunk index in the page */
+	i = ((size_t)(uintptr_t)ptr & malloc_pagemask) >> (*mp)->shift;
+
+	/* Verify that it isn't a free chunk already */
+        if ((*mp)->bits[i/MALLOC_BITS] & (1<<(i%MALLOC_BITS))) {
+	    wrtwarning("chunk is already free.\n");
+	    return (size_t)-1;
+	}
+
+	return (*mp)->size;
+
+    } else {
+	wrtwarning("pointer to wrong page.\n");
+	return (size_t)-1;
+    }
+}
+
 /*
  * Change the size of an allocation.
  */