diff options
author | Eric Andersen <andersen@codepoet.org> | 2003-12-30 01:41:14 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2003-12-30 01:41:14 +0000 |
commit | 4c9086ee4afde4257a4b4a8f55e05932d1b6acfd (patch) | |
tree | 4db5d307a3ed93eb7c1fa1ec3a75b25243ce6913 | |
parent | e5104517c1812dbee65e0994650e92e8d99dc9c0 (diff) |
Update and restore malloc-simple. Slow as molasses, but trivially
simple and releases memory immediately when asked to do so.
-Erik
-rw-r--r-- | libc/stdlib/malloc-simple/Makefile | 44 | ||||
-rw-r--r-- | libc/stdlib/malloc-simple/alloc.c | 189 |
2 files changed, 233 insertions, 0 deletions
diff --git a/libc/stdlib/malloc-simple/Makefile b/libc/stdlib/malloc-simple/Makefile new file mode 100644 index 000000000..1da7a672c --- /dev/null +++ b/libc/stdlib/malloc-simple/Makefile @@ -0,0 +1,44 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org> +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Derived in part from the Linux-8086 C library, the GNU C Library, and several +# other sundry sources. Files within this library are copyright by their +# respective copyright holders. + +TOPDIR=../../../ +include $(TOPDIR)Rules.mak + +MSRC=alloc.c +MOBJ=malloc.o realloc.o free.o calloc.o memalign.o +OBJS=$(MOBJ) + + +all: $(OBJS) $(LIBC) + +$(LIBC): ar-target + +ar-target: $(OBJS) + $(AR) $(ARFLAGS) $(LIBC) $(OBJS) + +$(MOBJ): $(MSRC) + $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o + $(STRIPTOOL) -x -R .note -R .comment $*.o + +clean: + rm -f *.[oa] *~ core + diff --git a/libc/stdlib/malloc-simple/alloc.c b/libc/stdlib/malloc-simple/alloc.c new file mode 100644 index 000000000..ee0135581 --- /dev/null +++ b/libc/stdlib/malloc-simple/alloc.c @@ -0,0 +1,189 @@ +/* alloc.c + * + * Written by Erik Andersen <andersee@debian.org> + * LGPLv2 + * + * Parts of the memalign code were stolen from malloc-930716. + */ + +#include <features.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> + + +#ifdef L_malloc +void *malloc(size_t size) +{ + void *result; + + if (unlikely(size == 0)) { +#if defined(__MALLOC_GLIBC_COMPAT__) + size++; +#else + /* Some programs will call malloc (0). Lets be strict and return NULL */ + return 0; +#endif + } + +#ifdef __UCLIBC_HAS_MMU__ + result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + if (result == MAP_FAILED) + return 0; + * (size_t *) result = size; + return(result + sizeof(size_t)); +#else + result = mmap((void *) 0, size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, 0, 0); + if (result == MAP_FAILED) + return 0; + return(result); +#endif +} +#endif + +#ifdef L_calloc +void *calloc(size_t num, size_t size) +{ + void *ptr = malloc(num * size); + if (ptr) + memset(ptr, 0, num * size); + return ptr; +} +#endif + +#ifdef L_realloc +void *realloc(void *ptr, size_t size) +{ + void *newptr = NULL; + + if (!ptr) + return malloc(size); + if (!size) { + free(ptr); + return malloc(0); + } + + newptr = malloc(size); + if (newptr) { + memcpy(newptr, ptr, +#ifdef __UCLIBC_HAS_MMU__ + *((size_t *) (ptr - sizeof(size_t))) +#else + size +#endif + ); + free(ptr); + } + return newptr; +} +#endif + +#ifdef L_free +extern int weak_function __libc_free_aligned(void *ptr); +void free(void *ptr) +{ + if (ptr == NULL) + return; + if (unlikely(__libc_free_aligned!=NULL)) { + if (__libc_free_aligned(ptr)) { + return; + } + } +#ifdef __UCLIBC_HAS_MMU__ + ptr -= sizeof(size_t); + munmap(ptr, * (size_t *) ptr + sizeof(size_t)); +#else + munmap(ptr, 0); +#endif +} +#endif + +#ifdef L_memalign +#ifdef __UCLIBC_HAS_THREADS__ +#include <pthread.h> +extern pthread_mutex_t __malloclock; +# define LOCK __pthread_mutex_lock(&__malloclock) +# define UNLOCK __pthread_mutex_unlock(&__malloclock); +#else +# define LOCK +# define UNLOCK +#endif + +/* List of blocks allocated with memalign or valloc */ +struct alignlist +{ + struct alignlist *next; + __ptr_t aligned; /* The address that memaligned returned. */ + __ptr_t exact; /* The address that malloc returned. */ +}; +struct alignlist *_aligned_blocks; + +/* Return memory to the heap. */ +int __libc_free_aligned(void *ptr) +{ + struct alignlist *l; + + if (ptr == NULL) + return 0; + + LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) { + if (l->aligned == ptr) { + /* Mark the block as free */ + l->aligned = NULL; + ptr = l->exact; +#ifdef __UCLIBC_HAS_MMU__ + ptr -= sizeof(size_t); + munmap(ptr, * (size_t *) ptr + sizeof(size_t)); +#else + munmap(ptr, 0); +#endif + return 1; + } + } + UNLOCK; + return 0; +} +void * memalign (size_t alignment, size_t size) +{ + void * result; + unsigned long int adj; + + result = malloc (size + alignment - 1); + if (result == NULL) + return NULL; + adj = (unsigned long int) ((unsigned long int) ((char *) result - + (char *) NULL)) % alignment; + if (adj != 0) + { + struct alignlist *l; + LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == NULL) + /* This slot is free. Use it. */ + break; + if (l == NULL) + { + l = (struct alignlist *) malloc (sizeof (struct alignlist)); + if (l == NULL) { + free(result); + UNLOCK; + return NULL; + } + l->next = _aligned_blocks; + _aligned_blocks = l; + } + l->exact = result; + result = l->aligned = (char *) result + alignment - adj; + UNLOCK; + } + + return result; +} +#endif + |