malloc.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * libc/stdlib/malloc-zarg/malloc.c -- malloc function
  3. *
  4. * Copyright (C) 2002 NEC Corporation
  5. * Copyright (C) 2002 Miles Bader <miles@gnu.org>
  6. *
  7. * This file is subject to the terms and conditions of the GNU Lesser
  8. * General Public License. See the file COPYING.LIB in the main
  9. * directory of this archive for more details.
  10. *
  11. * Written by Miles Bader <miles@gnu.org>
  12. */
  13. #include <stdlib.h>
  14. #include <sys/mman.h>
  15. #include "malloc.h"
  16. #include "heap.h"
  17. /* When we give memory to the heap, start this many bytes after the
  18. beginning of the mmaped block. This is because we must ensure that
  19. malloc return values are aligned to MALLOC_ALIGNMENT, but since we need
  20. to use one word _before_ the beginning of that, we actually want the heap
  21. to return values that are MALLOC_ALIGNMENT aligned - sizeof (size_t).
  22. Since the heap always allocates in multiples of HEAP_GRANULARITY, we can
  23. do this by (1) ensuring that HEAP_GRANULARITY is a multiple of
  24. MALLOC_ALIGNMENT, and (2) making sure that the heap's free areas start
  25. sizeof(size_t) bytes before our required alignment. */
  26. #define MALLOC_HEAP_BLOCK_SHIM (MALLOC_ALIGNMENT - sizeof (size_t))
  27. /* The heap used for small allocations. */
  28. struct heap __malloc_heap = HEAP_INIT;
  29. void *malloc (size_t size)
  30. {
  31. void *mem;
  32. MALLOC_DEBUG ("malloc: %d bytes\n", size);
  33. /* Include an extra word to record the size of the allocated block. */
  34. size += sizeof (size_t);
  35. if (size >= MALLOC_MMAP_THRESHOLD)
  36. /* Use mmap for large allocations. */
  37. {
  38. /* Make sure we request enough memory to align the result correctly,
  39. and that SIZE reflects that mmap hands back whole pages. */
  40. size += MALLOC_ROUND_UP_TO_PAGE_SIZE (MALLOC_ALIGNMENT - sizeof(size_t));
  41. mem = mmap (0, size, PROT_READ | PROT_WRITE,
  42. MAP_SHARED | MAP_ANONYMOUS, 0, 0);
  43. if (mem == MAP_FAILED)
  44. return 0;
  45. }
  46. else
  47. /* Use the heap for small allocations. */
  48. {
  49. mem = __heap_alloc (&__malloc_heap, &size);
  50. if (! mem)
  51. /* We couldn't allocate from the heap, so get some more memory
  52. from the system, add it to the heap, and try again. */
  53. {
  54. /* If we're trying to allocate a block bigger than the default
  55. MALLOC_HEAP_EXTEND_SIZE, make sure we get enough to hold it. */
  56. size_t block_size = (size < MALLOC_HEAP_EXTEND_SIZE
  57. ? MALLOC_HEAP_EXTEND_SIZE
  58. : MALLOC_ROUND_UP_TO_PAGE_SIZE (size));
  59. /* Allocate the new heap block. */
  60. void *block = mmap (0, block_size,
  61. PROT_READ | PROT_WRITE,
  62. MAP_SHARED | MAP_ANONYMOUS, 0, 0);
  63. if (block != MAP_FAILED)
  64. {
  65. /* Put BLOCK into the heap. We first try to append BLOCK to
  66. an existing free area, which is more efficient because it
  67. doesn't require using a `shim' at the beginning (which
  68. would prevent merging free-areas); since mmap often returns
  69. contiguous areas, this is worth it. */
  70. if (! __heap_append_free (&__malloc_heap, block, block_size))
  71. /* Couldn't append, just add BLOCK as a new free-area. */
  72. __heap_free (&__malloc_heap,
  73. block + MALLOC_HEAP_BLOCK_SHIM,
  74. block_size - MALLOC_HEAP_BLOCK_SHIM);
  75. /* Try again to allocate. */
  76. mem = __heap_alloc (&__malloc_heap, &size);
  77. }
  78. }
  79. }
  80. if (mem)
  81. /* Record the size of this block just before the returned address. */
  82. {
  83. *(size_t *)mem = size;
  84. mem = (size_t *)mem + 1;
  85. MALLOC_DEBUG (" malloc: returning 0x%lx (base:0x%lx, total_size:%d)\n",
  86. (long)mem, (long)mem - sizeof (size_t), size);
  87. }
  88. return mem;
  89. }