OSDN Git Service

fix static linking of pthread apps
[uclinux-h8/uclibc-ng.git] / libc / stdlib / malloc-simple / alloc.c
index 4c6edd1..a3c068a 100644 (file)
@@ -1,50 +1,53 @@
 /* alloc.c
  *
- * Written by Erik Andersen <andersee@debian.org>
- * LGPLv2
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
  *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+/*
  * Parts of the memalign code were stolen from malloc-930716.
  */
 
-#define _GNU_SOURCE
 #include <features.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #include <errno.h>
 #include <sys/mman.h>
+#include <malloc.h>
 
+extern int weak_function __libc_free_aligned(void *ptr) attribute_hidden;
 
 #ifdef L_malloc
 void *malloc(size_t size)
 {
-    void *result;
+       void *result;
 
-    if (unlikely(size == 0)) {
+       if (unlikely(size == 0)) {
 #if defined(__MALLOC_GLIBC_COMPAT__)
-       size++;
+               size++;
 #else
-       /* Some programs will call malloc (0).  Lets be strict and return NULL */
-       return 0;
+               /* Some programs will call malloc (0).  Lets be strict and return NULL */
+               __set_errno(ENOMEM);
+               return NULL;
 #endif
-    }
+       }
 
-#ifdef __UCLIBC_HAS_MMU__
-    result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE,
-           MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-    if (result == MAP_FAILED)
-       return 0;
-    * (size_t *) result = size;
-    return(result + sizeof(size_t));
+#ifdef __ARCH_USE_MMU__
+# define MMAP_FLAGS MAP_PRIVATE | MAP_ANONYMOUS
 #else
-    result = mmap((void *) 0, size, PROT_READ | PROT_WRITE,
-           MAP_SHARED | MAP_ANONYMOUS, -1, 0);
-    if (result == MAP_FAILED)
-       return 0;
-    return(result);
+# define MMAP_FLAGS MAP_SHARED | MAP_ANONYMOUS | MAP_UNINITIALIZED
 #endif
+
+       result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE,
+                     MMAP_FLAGS, 0, 0);
+       if (result == MAP_FAILED) {
+               __set_errno(ENOMEM);
+               return 0;
+       }
+       * (size_t *) result = size;
+       return(result + sizeof(size_t));
 }
 #endif
 
@@ -60,11 +63,10 @@ void * calloc(size_t nmemb, size_t lsize)
                __set_errno(ENOMEM);
                return NULL;
        }
-       result=malloc(size);
-#if 0
-       /* Standard unix mmap using /dev/zero clears memory so calloc
-        * doesn't need to actually zero anything....
-        */
+       result = malloc(size);
+
+#ifndef __ARCH_USE_MMU__
+       /* mmap'd with MAP_UNINITIALIZED, we have to blank memory ourselves */
        if (result != NULL) {
                memset(result, 0, size);
        }
@@ -76,131 +78,111 @@ void * calloc(size_t nmemb, size_t lsize)
 #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;
+       void *newptr = NULL;
+
+       if (!ptr)
+               return malloc(size);
+       if (!size) {
+               free(ptr);
+               return malloc(0);
+       }
+
+       newptr = malloc(size);
+       if (newptr) {
+               size_t old_size = *((size_t *) (ptr - sizeof(size_t)));
+               memcpy(newptr, ptr, (old_size < size ? old_size : size));
+               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;
+       if (unlikely(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
+       ptr -= sizeof(size_t);
+       munmap(ptr, * (size_t *) ptr + sizeof(size_t));
 }
 #endif
 
 #ifdef L_memalign
-#ifdef __UCLIBC_HAS_THREADS__
-#include <pthread.h>
-pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-# define LOCK  __pthread_mutex_lock(&__malloc_lock)
-# define UNLOCK        __pthread_mutex_unlock(&__malloc_lock);
-#else
-# define LOCK
-# define UNLOCK
-#endif
+
+#include <bits/uClibc_mutex.h>
+__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
+#define __MALLOC_LOCK          __UCLIBC_MUTEX_LOCK(__malloc_lock)
+#define __MALLOC_UNLOCK                __UCLIBC_MUTEX_UNLOCK(__malloc_lock)
 
 /* 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 *next;
+       __ptr_t aligned;        /* The address that memaligned returned.  */
+       __ptr_t exact;  /* The address that malloc returned.  */
 };
-struct alignlist *_aligned_blocks;
+static struct alignlist *_aligned_blocks;
 
 /* Return memory to the heap. */
 int __libc_free_aligned(void *ptr)
 {
-    struct alignlist *l;
-
-    if (ptr == NULL)
-       return 0;
+       struct alignlist *l;
 
-    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;
+       if (ptr == NULL)
+               return 0;
+
+       __MALLOC_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;
+                       ptr -= sizeof(size_t);
+                       munmap(ptr, * (size_t *) ptr + sizeof(size_t));
+                       return 1;
+               }
        }
-    }
-    UNLOCK;
-    return 0;
+       __MALLOC_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;
+       void * result;
+       unsigned long int adj;
+
+       result = malloc (size + alignment - 1);
+       if (result == NULL)
                return NULL;
-           }
-           l->next = _aligned_blocks;
-           _aligned_blocks = l;
+
+       adj = (unsigned long int) ((unsigned long int) ((char *) result - (char *) NULL)) % alignment;
+       if (adj != 0) {
+               struct alignlist *l;
+               __MALLOC_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);
+                               result = NULL;
+                               goto DONE;
+                       }
+                       l->next = _aligned_blocks;
+                       _aligned_blocks = l;
+               }
+               l->exact = result;
+               result = l->aligned = (char *) result + alignment - adj;
+DONE:
+               __MALLOC_UNLOCK;
        }
-       l->exact = result;
-       result = l->aligned = (char *) result + alignment - adj;
-       UNLOCK;
-    }
 
-    return result;
+       return result;
 }
+libc_hidden_def(memalign)
 #endif
-