Mail Archives: djgpp-workers/2001/01/05/12:42:45
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 -