diff options
Diffstat (limited to 'libc/stdlib')
| -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 + | 
