delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/01/05/12:42:45

From: "Mark E." <snowball3 AT bigfoot DOT com>
To: djgpp-workers AT delorie DOT com
Date: Fri, 5 Jan 2001 12:42:26 -0500
MIME-Version: 1.0
Subject: valloc and memalign draft
Message-ID: <3A55C132.12287.6F26E9@localhost>
X-mailer: Pegasus Mail for Win32 (v3.12c)
Reply-To: djgpp-workers AT delorie DOT com

Hi guys,
This is a draft of valloc (and memalign) designed to used mainly by the GCC's 
garbage collection routines. I designed it to be memory efficient and return 
a pointer that can safely be passed to free(). While a generic valloc is in 
the works for inclusion in libiberty, it's always better to have our own 
version if possible.

I would have split off memalign and valloc, but I wanted to get them working 
first.

*** malloc.c.orig	Wed Jun 28 15:46:34 2000
--- malloc.c	Fri Jan  5 12:30:40 2001
***************
*** 360,362 ****
--- 360,458 ----
    free(ptr);
    return newptr;
  }
+ 
+ /* Make VAL a multiple of ALIGN.  */
+ inline
+ size_t
+ align_val (size_t val, size_t align)
+ {
+   return ((val + (align - 1)) & ~(align - 1));
+ }
+ 
+ /* Split a chunk of previously allocated memory into two chunks in a way
+    that requires both to be released with a call to free().  */
+ void *
+ split_alloc (char *ptr, size_t split_pos)
+ {
+   BLOCK *b1, *b2;
+   char *split_ptr;
+   
+   b1 = (BLOCK *)(ptr - 4);
+ 
+   /* Set location of second pointer and its block info.  */
+   split_ptr = ptr + split_pos;
+   b2 = (BLOCK *)(split_ptr - 4);
+ 
+   /* Temporarily clear chunk-in-use bit so macros work correctly.  */
+   b1->size &= ~1;
+ 
+   /* Set up the two blocks.  */
+   b2->size = b1->size - split_pos;
+   b2->bucket = -1;
+   b1->size = split_pos - 8;
+   
+   ENDSZ(b1) = b1->size;
+   ENDSZ(b2) = b2->size;
+   CHECK(b1);
+   CHECK(b2);
+ 
+   /* Finish up by setting the chunk-in-use bit for the first chunk and
+      returning a pointer to the chunk just split off.  */
+   ENDSZ(b1) |= 1;
+   b1->size |= 1;
+   
+   RET (b2);
+ }
+ 
+ /* Return a block of memory AMT bytes long whose address is a multiple
+    ALIGN.  ALIGN must be a power of 2.  */
+    
+ void *
+ memalign (size_t align, size_t amt)
+ {
+   char *ptr, *aligned_ptr;
+   BLOCK *b;
+   size_t alloc_size, before_size, after_size;
+ 
+   if (align != align_val(align, align))
+     return NULL;
+ 
+   if (align < ALIGN)
+     align = ALIGN;
+     
+   amt = align_val (amt, ALIGN);
+   alloc_size = amt + align;
+   
+   ptr = malloc(alloc_size);
+   if (ptr == NULL)
+     return ptr;
+ 
+   aligned_ptr = (char *)align_val((size_t)ptr, align);
+ 
+   /* Release any space between the malloc'ed pointer
+      and the aligned pointer.  */
+   before_size = (aligned_ptr - ptr);
+   if (before_size)
+   {
+     aligned_ptr = split_alloc (ptr, before_size);
+     free (ptr);
+   }
+ 
+   /* Release extra space not requested if it's large enough
+      to bother with.  */
+   after_size = alloc_size - amt - 8;
+   if (after_size > 8)
+   {
+     char *after = split_alloc (aligned_ptr, amt + 8);
+     free (after);
+   }
+ 
+   return aligned_ptr;
+ }
+ 
+ void *
+ valloc (size_t amt)
+ {
+   return memalign (getpagesize(), amt);
+ }
+ 

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019