OSDN Git Service

Implimented a simple allocation system that does not waste memory.
authorRon Alder <alder@lineo.com>
Thu, 15 Jun 2000 18:01:08 +0000 (18:01 -0000)
committerRon Alder <alder@lineo.com>
Thu, 15 Jun 2000 18:01:08 +0000 (18:01 -0000)
Added realloc. The allocation system was needed to support realloc.

libc/stdlib/malloc/alloc.c

index 5282c14..5e508f9 100644 (file)
@@ -3,6 +3,28 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+struct chunkControl {
+       size_t nodeCount;
+       size_t chunkSize;
+};
+
+struct nodeControl {
+       struct chunkControl *chunk;
+       size_t nodeSize;
+};
+
+#define ROUND_UP_LENGTH(len) ((len+7) & ~0x07)
+
+extern struct nodeControl *mallocNextNode;
+
+#ifdef L_malloc
+/* This variable is a pointer to the next place to allocate from.
+ * Note: This variable makes the code NOT thread save. */
+struct nodeControl *mallocNextNode = 0;
+static size_t PageSize = 0;
+
+#endif
+
 #ifdef L_calloc_dbg
 
 void *
@@ -61,12 +83,64 @@ calloc(size_t num, size_t size)
 void *
 malloc(size_t len)
 {
-  void * result = mmap((void *)0, len, PROT_READ | PROT_WRITE,
-                 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
-  if (result == (void*)-1)
-    return 0;
-    
-  return result;
+       void *result;
+       struct chunkControl *chunk;
+       struct nodeControl  *next;
+       size_t size;
+
+       /* round len up to keep things on even boundaries */
+       len = ROUND_UP_LENGTH(len);
+
+       if (len == 0)
+               return 0;
+
+TryAgain:
+       if (mallocNextNode != 0) {
+               /* first see if this request will fit on this chunk */
+               next  = mallocNextNode;
+               chunk = next->chunk;
+               if (((char *)next + sizeof(struct nodeControl)*2 + len) < 
+                   ((char *)chunk + chunk->chunkSize))
+               {
+                       /* this request will fit, so simply move the next
+                        * pointer ahead and update chunk node count */
+                       next->nodeSize = len;
+                       result = (char *)next + sizeof(struct nodeControl);
+                       chunk->nodeCount++;
+                       next = (struct nodeControl *)
+                                 ((char *)next + (sizeof(struct nodeControl) + len));
+                       next->chunk = chunk;
+                       next->nodeSize = 0;
+                       mallocNextNode = next;
+
+                       return result; /* normal return path */
+               }
+               
+       }
+       
+       /* the request will not fit on this chunk, so get another chunk */
+       if (PageSize == 0) {
+               PageSize = getpagesize();
+       }
+       size = len + (sizeof(struct chunkControl) + (sizeof(struct nodeControl) * 2));
+       if (size < PageSize * 2) {
+               size = PageSize * 2;
+       }
+       size = (size + (PageSize-1)) & ~(PageSize-1);
+
+       chunk = mmap((void *)0, size, PROT_READ | PROT_WRITE,
+                     MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+       if (chunk == (void*)-1)
+               return 0;
+
+       chunk->chunkSize = size;
+       chunk->nodeCount = 0;
+       next             = (struct nodeControl *)
+                                ((char *)chunk + sizeof(struct chunkControl));
+       next->chunk      = chunk;
+       mallocNextNode   = next;
+
+       goto TryAgain;
 }
 
 #endif
@@ -76,7 +150,58 @@ malloc(size_t len)
 void
 free(void * ptr)
 {
-  munmap(ptr, 0);
+       struct chunkControl *chunk;
+       struct nodeControl  *node;
+       
+       if (ptr == 0) {
+               return;
+       }
+       /* get a pointer to the control information for this memory node
+        * and the chunk it belongs to */
+       node  = (struct nodeControl *)ptr - 1;
+       chunk = node->chunk;
+       /* decrement the node count and if it is zero free the chunk */
+       chunk->nodeCount--;
+       if (chunk->nodeCount == 0) {
+               if ((void *)mallocNextNode >= (void *)chunk && 
+                    ((void *)mallocNextNode < (void *)((char *)chunk + chunk->chunkSize)))
+               {
+                       mallocNextNode = 0;
+               }
+               munmap(chunk, chunk->chunkSize);
+       }
 }
 
 #endif
+
+#ifdef L_realloc
+
+void *
+realloc(void *ptr, size_t len)
+{
+       struct nodeControl *node;
+       size_t oldSize;
+       void *new;
+       
+       
+       if (ptr == 0) {
+               return malloc(len);
+       }
+       if (len == 0) {
+               free(ptr);
+               return 0;
+       }
+       node    = (struct nodeControl *)ptr - 1;
+       oldSize = node->nodeSize;
+       if (oldSize >= len) {
+               return ptr;
+       }
+       
+       new = malloc(len);
+       memcpy(new, ptr, len);
+       free(ptr);
+       return new;
+}
+
+#endif
+