Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Memory allocator

  • Loading branch information...
commit 6707cd12c1862eb5de86038a3ff5787171265ae0 1 parent 3f1fd02
Sébastien Bourdeauducq authored June 02, 2012
4  Makefile
@@ -2,9 +2,9 @@ MISPDIR=.
2 2
 include $(MISPDIR)/common.mak
3 3
 
4 4
 OBJECTS=crt0.o isr.o luainit.o main.o
5  
-OURLIBS=m yaffs2 glue lua
  5
+OURLIBS=m mm yaffs2 glue lua
6 6
 
7  
-CFLAGS+=-I$(MISPDIR)/libm/include -I$(LUADIR)/src
  7
+CFLAGS+=-I$(MISPDIR)/libm/include -I$(MISPDIR)/libmm/include -I$(LUADIR)/src
8 8
 
9 9
 all: misp.bin
10 10
 
22  libmm/Makefile
... ...
@@ -0,0 +1,22 @@
  1
+MISPDIR=..
  2
+include $(MISPDIR)/common.mak
  3
+
  4
+CFLAGS+=-I$(MISPDIR)/libmm/include
  5
+OBJECTS=mm_addfreechunk.o mm_free.o mm_mallinfo.o mm_memalign.o mm_shrinkchunk.o mm_zalloc.o mm_calloc.o mm_initialize.o mm_malloc.o mm_realloc.o mm_size2ndx.o
  6
+
  7
+all: libmm.a
  8
+
  9
+# pull in dependency info for *existing* .o files
  10
+-include $(OBJECTS:.o=.d)
  11
+
  12
+libmm.a: $(OBJECTS)
  13
+	$(AR) clr libmm.a $(OBJECTS)
  14
+	$(RANLIB) libmm.a
  15
+
  16
+%.o: %.c
  17
+	$(compile-dep)
  18
+
  19
+.PHONY: clean
  20
+
  21
+clean:
  22
+	rm -f $(OBJECTS) $(OBJECTS:.o=.d) libmm.a .*~ *~
24  libmm/include/malloc.h
... ...
@@ -0,0 +1,24 @@
  1
+#ifndef __MALLOC_H
  2
+#define __MALLOC_H
  3
+
  4
+struct mallinfo
  5
+{
  6
+  int arena;    /* This is the total size of memory allocated
  7
+                 * for use by malloc in bytes. */
  8
+  int ordblks;  /* This is the number of free (not in use) chunks */
  9
+  int mxordblk; /* Size of the largest free (not in use) chunk */
  10
+  int uordblks; /* This is the total size of memory occupied by
  11
+                 * chunks handed out by malloc. */
  12
+  int fordblks; /* This is the total size of memory occupied
  13
+                 * by free (not in use) chunks.*/
  14
+};
  15
+
  16
+struct mallinfo mallinfo(void);
  17
+void *memalign(size_t boundary, size_t size);
  18
+
  19
+/* Those are non-standard */
  20
+void mm_initialize(void *heapstart, size_t heapsize);
  21
+void mm_addregion(void *heapstart, size_t heapsize);
  22
+void *zalloc(size_t size);
  23
+
  24
+#endif /* __MALLOC_H */
74  libmm/mm_addfreechunk.c
... ...
@@ -0,0 +1,74 @@
  1
+/************************************************************************
  2
+ * mm/mm_addfreechunk.c
  3
+ *
  4
+ *   Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
  5
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  6
+ *
  7
+ * Redistribution and use in source and binary forms, with or without
  8
+ * modification, are permitted provided that the following conditions
  9
+ * are met:
  10
+ *
  11
+ * 1. Redistributions of source code must retain the above copyright
  12
+ *    notice, this list of conditions and the following disclaimer.
  13
+ * 2. Redistributions in binary form must reproduce the above copyright
  14
+ *    notice, this list of conditions and the following disclaimer in
  15
+ *    the documentation and/or other materials provided with the
  16
+ *    distribution.
  17
+ * 3. Neither the name NuttX nor the names of its contributors may be
  18
+ *    used to endorse or promote products derived from this software
  19
+ *    without specific prior written permission.
  20
+ *
  21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32
+ * POSSIBILITY OF SUCH DAMAGE.
  33
+ *
  34
+ ************************************************************************/
  35
+
  36
+#include "mm_environment.h"
  37
+#include "mm_internal.h"
  38
+
  39
+/************************************************************************
  40
+ * mm_addfreechunk
  41
+ *
  42
+ * Description:
  43
+ *   Add a free chunk to the node next
  44
+ *
  45
+ ************************************************************************/
  46
+
  47
+void mm_addfreechunk(struct mm_freenode_s *node)
  48
+{
  49
+  struct mm_freenode_s *next;
  50
+  struct mm_freenode_s *prev;
  51
+
  52
+  /* Convert the size to a nodelist index */
  53
+
  54
+  int ndx = mm_size2ndx(node->size);
  55
+
  56
+  /* Now put the new node int the next */
  57
+
  58
+  for (prev = &g_nodelist[ndx], next = g_nodelist[ndx].flink;
  59
+       next && next->size && next->size < node->size;
  60
+       prev = next, next = next->flink);
  61
+
  62
+  /* Does it go in mid next or at the end? */
  63
+
  64
+  prev->flink = node;
  65
+  node->blink = prev;
  66
+  node->flink = next;
  67
+
  68
+  if (next)
  69
+    {
  70
+      /* The new node goes between prev and next */
  71
+
  72
+      next->blink = node;
  73
+    }
  74
+}
56  libmm/mm_calloc.c
... ...
@@ -0,0 +1,56 @@
  1
+/************************************************************************
  2
+ * mm_calloc.c
  3
+ *
  4
+ *   Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
  5
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  6
+ *
  7
+ * Redistribution and use in source and binary forms, with or without
  8
+ * modification, are permitted provided that the following conditions
  9
+ * are met:
  10
+ *
  11
+ * 1. Redistributions of source code must retain the above copyright
  12
+ *    notice, this list of conditions and the following disclaimer.
  13
+ * 2. Redistributions in binary form must reproduce the above copyright
  14
+ *    notice, this list of conditions and the following disclaimer in
  15
+ *    the documentation and/or other materials provided with the
  16
+ *    distribution.
  17
+ * 3. Neither the name NuttX nor the names of its contributors may be
  18
+ *    used to endorse or promote products derived from this software
  19
+ *    without specific prior written permission.
  20
+ *
  21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32
+ * POSSIBILITY OF SUCH DAMAGE.
  33
+ *
  34
+ ************************************************************************/
  35
+
  36
+#include "mm_environment.h"
  37
+#include "mm_internal.h"
  38
+
  39
+/************************************************************************
  40
+ * calloc
  41
+ *
  42
+ * Descripton:
  43
+ *   calloc calculates the size and calls zalloc
  44
+ ************************************************************************/
  45
+
  46
+void *calloc(size_t n, size_t elem_size)
  47
+{
  48
+  void *ret = NULL;
  49
+
  50
+  if (n > 0 && elem_size > 0)
  51
+    {
  52
+      ret = zalloc(n * elem_size);
  53
+    }
  54
+
  55
+  return ret;
  56
+}
57  libmm/mm_environment.h
... ...
@@ -0,0 +1,57 @@
  1
+/****************************************************************************
  2
+ * mm/mm_environment.h
  3
+ *
  4
+ *   Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
  5
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  6
+ *
  7
+ * Redistribution and use in source and binary forms, with or without
  8
+ * modification, are permitted provided that the following conditions
  9
+ * are met:
  10
+ *
  11
+ * 1. Redistributions of source code must retain the above copyright
  12
+ *    notice, this list of conditions and the following disclaimer.
  13
+ * 2. Redistributions in binary form must reproduce the above copyright
  14
+ *    notice, this list of conditions and the following disclaimer in
  15
+ *    the documentation and/or other materials provided with the
  16
+ *    distribution.
  17
+ * 3. Neither the name NuttX nor the names of its contributors may be
  18
+ *    used to endorse or promote products derived from this software
  19
+ *    without specific prior written permission.
  20
+ *
  21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32
+ * POSSIBILITY OF SUCH DAMAGE.
  33
+ *
  34
+ ****************************************************************************/
  35
+
  36
+#ifndef __MM_ENVIRONMENT_H
  37
+#define __MM_ENVIRONMENT_H
  38
+
  39
+#include <stdio.h>
  40
+#include <stdlib.h>
  41
+#include <stdint.h>
  42
+#include <string.h>
  43
+#include <errno.h>
  44
+#include <assert.h>
  45
+#include <malloc.h>
  46
+
  47
+#define mm_errno errno
  48
+#ifdef MM_DEBUG
  49
+#define mvdbg(format, arg...) printf(format, ##arg)
  50
+#else
  51
+#define mvdbg(format, arg...)
  52
+#endif
  53
+
  54
+#define ASSERT(e)      assert(e)
  55
+#define DEBUGASSERT(e) assert(e)
  56
+
  57
+#endif /* __MM_ENVIRONMENT_H */
129  libmm/mm_free.c
... ...
@@ -0,0 +1,129 @@
  1
+/************************************************************************
  2
+ * mm/mm_free.c
  3
+ *
  4
+ *   Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
  5
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  6
+ *
  7
+ * Redistribution and use in source and binary forms, with or without
  8
+ * modification, are permitted provided that the following conditions
  9
+ * are met:
  10
+ *
  11
+ * 1. Redistributions of source code must retain the above copyright
  12
+ *    notice, this list of conditions and the following disclaimer.
  13
+ * 2. Redistributions in binary form must reproduce the above copyright
  14
+ *    notice, this list of conditions and the following disclaimer in
  15
+ *    the documentation and/or other materials provided with the
  16
+ *    distribution.
  17
+ * 3. Neither the name NuttX nor the names of its contributors may be
  18
+ *    used to endorse or promote products derived from this software
  19
+ *    without specific prior written permission.
  20
+ *
  21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32
+ * POSSIBILITY OF SUCH DAMAGE.
  33
+ *
  34
+ ************************************************************************/
  35
+
  36
+#include <assert.h>
  37
+#include "mm_environment.h"
  38
+#include "mm_internal.h"
  39
+
  40
+/************************************************************************
  41
+ * free
  42
+ *
  43
+ * Description:
  44
+ *   Returns a chunk of memory into the list of free nodes,
  45
+ *   merging with adjacent free chunks if possible.
  46
+ *
  47
+ ************************************************************************/
  48
+
  49
+void free(void *mem)
  50
+{
  51
+  struct mm_freenode_s *node;
  52
+  struct mm_freenode_s *prev;
  53
+  struct mm_freenode_s *next;
  54
+
  55
+  mvdbg("Freeing %p\n", mem);
  56
+
  57
+  /* Protect against attempts to free a NULL reference */
  58
+
  59
+  if (!mem)
  60
+    {
  61
+      return;
  62
+    }
  63
+
  64
+  /* Map the memory chunk into a free node */
  65
+
  66
+  node = (struct mm_freenode_s *)((char*)mem - SIZEOF_MM_ALLOCNODE);
  67
+  node->preceding &= ~MM_ALLOC_BIT;
  68
+
  69
+  /* Check if the following node is free and, if so, merge it */
  70
+
  71
+  next = (struct mm_freenode_s *)((char*)node + node->size);
  72
+  if ((next->preceding & MM_ALLOC_BIT) == 0)
  73
+    {
  74
+      struct mm_allocnode_s *andbeyond;
  75
+
  76
+      /* Get the node following the next node (which will
  77
+       * become the new next node). We know that we can never
  78
+       * index past the tail chunk because it is always allocated.
  79
+       */
  80
+
  81
+      andbeyond = (struct mm_allocnode_s*)((char*)next + next->size);
  82
+
  83
+      /* Remove the next node.  There must be a predecessor,
  84
+       * but there may not be a successor node.
  85
+       */
  86
+
  87
+      DEBUGASSERT(next->blink);
  88
+      next->blink->flink = next->flink;
  89
+      if (next->flink)
  90
+        {
  91
+          next->flink->blink = next->blink;
  92
+        }
  93
+
  94
+      /* Then merge the two chunks */
  95
+
  96
+      node->size          += next->size;
  97
+      andbeyond->preceding =  node->size | (andbeyond->preceding & MM_ALLOC_BIT);
  98
+      next                 = (struct mm_freenode_s *)andbeyond;
  99
+    }
  100
+
  101
+  /* Check if the preceding node is also free and, if so, merge
  102
+   * it with this node
  103
+   */
  104
+
  105
+  prev = (struct mm_freenode_s *)((char*)node - node->preceding);
  106
+  if ((prev->preceding & MM_ALLOC_BIT) == 0)
  107
+    {
  108
+      /* Remove the node.  There must be a predecessor, but there may
  109
+       * not be a successor node.
  110
+       */
  111
+
  112
+      DEBUGASSERT(prev->blink);
  113
+      prev->blink->flink = prev->flink;
  114
+      if (prev->flink)
  115
+        {
  116
+          prev->flink->blink = prev->blink;
  117
+        }
  118
+
  119
+      /* Then merge the two chunks */
  120
+
  121
+      prev->size     += node->size;
  122
+      next->preceding = prev->size | (next->preceding & MM_ALLOC_BIT);
  123
+      node            = prev;
  124
+    }
  125
+
  126
+  /* Add the merged node to the nodelist */
  127
+
  128
+  mm_addfreechunk(node);
  129
+}
184  libmm/mm_initialize.c
... ...
@@ -0,0 +1,184 @@
  1
+/****************************************************************************
  2
+ * mm/mm_initialize.c
  3
+ *
  4
+ *   Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
  5
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  6
+ *
  7
+ * Redistribution and use in source and binary forms, with or without
  8
+ * modification, are permitted provided that the following conditions
  9
+ * are met:
  10
+ *
  11
+ * 1. Redistributions of source code must retain the above copyright
  12
+ *    notice, this list of conditions and the following disclaimer.
  13
+ * 2. Redistributions in binary form must reproduce the above copyright
  14
+ *    notice, this list of conditions and the following disclaimer in
  15
+ *    the documentation and/or other materials provided with the
  16
+ *    distribution.
  17
+ * 3. Neither the name NuttX nor the names of its contributors may be
  18
+ *    used to endorse or promote products derived from this software
  19
+ *    without specific prior written permission.
  20
+ *
  21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32
+ * POSSIBILITY OF SUCH DAMAGE.
  33
+ *
  34
+ ****************************************************************************/
  35
+
  36
+#include "mm_environment.h"
  37
+#include "mm_internal.h"
  38
+
  39
+/* This is the size of the heap provided to mm */
  40
+
  41
+size_t g_heapsize;
  42
+
  43
+/* This is the first and last nodes of the heap */
  44
+
  45
+struct mm_allocnode_s *g_heapstart[CONFIG_MM_REGIONS];
  46
+struct mm_allocnode_s *g_heapend[CONFIG_MM_REGIONS];
  47
+
  48
+#if CONFIG_MM_REGIONS > 1
  49
+int g_nregions;
  50
+#endif
  51
+
  52
+/* All free nodes are maintained in a doubly linked list.  This
  53
+ * array provides some hooks into the list at various points to
  54
+ * speed searches for free nodes.
  55
+ */
  56
+
  57
+struct mm_freenode_s g_nodelist[MM_NNODES];
  58
+
  59
+/****************************************************************************
  60
+ * Public Functions
  61
+ ****************************************************************************/
  62
+
  63
+/****************************************************************************
  64
+ * Function:  mm_initialize
  65
+ *
  66
+ * Description:
  67
+ *   This is an internal OS function called only at power-up
  68
+ *   boot time.
  69
+ *
  70
+ * Parameters:
  71
+ *   heapstart - Start of the initial heap region
  72
+ *   heapsize  - Size of the initial heap region
  73
+ *
  74
+ * Return Value:
  75
+ *   None
  76
+ *
  77
+ * Assumptions:
  78
+ *
  79
+ ****************************************************************************/
  80
+
  81
+void mm_initialize(void *heapstart, size_t heapsize)
  82
+{
  83
+  int i;
  84
+
  85
+  mvdbg("Heap: start=%p size=%u\n", heapstart, heapsize);
  86
+
  87
+  CHECK_ALLOCNODE_SIZE;
  88
+  CHECK_FREENODE_SIZE;
  89
+
  90
+  /* Set up global variables */
  91
+
  92
+  g_heapsize = 0;
  93
+
  94
+#if CONFIG_MM_REGIONS > 1
  95
+  g_nregions = 0;
  96
+#endif
  97
+
  98
+  /* Initialize the node array */
  99
+
  100
+  memset(g_nodelist, 0, sizeof(struct mm_freenode_s) * MM_NNODES);
  101
+  for (i = 1; i < MM_NNODES; i++)
  102
+    {
  103
+      g_nodelist[i-1].flink = &g_nodelist[i];
  104
+      g_nodelist[i].blink   = &g_nodelist[i-1];
  105
+    }
  106
+
  107
+  /* Add the initial region of memory to the heap */
  108
+
  109
+  mm_addregion(heapstart, heapsize);
  110
+}
  111
+
  112
+/****************************************************************************
  113
+ * Function:  mm_addregion
  114
+ *
  115
+ * Description:
  116
+ *   This function gives a region of contiguous memory to
  117
+ *   the memory manager
  118
+ *
  119
+ * Parameters:
  120
+ *   heapstart - Start of the heap region
  121
+ *   heapsize  - Size of the heap region
  122
+ *
  123
+ * Return Value:
  124
+ *   None
  125
+ *
  126
+ * Assumptions:
  127
+ *
  128
+ ****************************************************************************/
  129
+
  130
+void mm_addregion(void *heapstart, size_t heapsize)
  131
+{
  132
+  struct mm_freenode_s *node;
  133
+  uintptr_t heapbase;
  134
+  uintptr_t heapend;
  135
+#if CONFIG_MM_REGIONS > 1
  136
+  int IDX = g_nregions;
  137
+#else
  138
+# define IDX 0
  139
+#endif
  140
+
  141
+  /* Adjust the provide heap start and size so that they are
  142
+   * both aligned with the MM_MIN_CHUNK size.
  143
+   */
  144
+
  145
+  heapbase = MM_ALIGN_UP((uintptr_t)heapstart);
  146
+  heapend  = MM_ALIGN_DOWN((uintptr_t)heapstart + (uintptr_t)heapsize);
  147
+  heapsize = heapend - heapbase;
  148
+
  149
+  mvdbg("Region %d: base=%p size=%u\n", IDX+1, heapstart, heapsize);
  150
+
  151
+  /* Add the size of this region to the total size of the heap */
  152
+
  153
+  g_heapsize += heapsize;
  154
+
  155
+  /* Create two "allocated" guard nodes at the beginning and end of
  156
+   * the heap.  These only serve to keep us from allocating outside
  157
+   * of the heap.
  158
+   * 
  159
+   * And create one free node between the guard nodes that contains
  160
+   * all available memory.
  161
+   */
  162
+
  163
+  g_heapstart[IDX]            = (struct mm_allocnode_s *)heapbase;
  164
+  g_heapstart[IDX]->size      = SIZEOF_MM_ALLOCNODE;
  165
+  g_heapstart[IDX]->preceding = MM_ALLOC_BIT;
  166
+
  167
+  node                        = (struct mm_freenode_s *)(heapbase + SIZEOF_MM_ALLOCNODE);
  168
+  node->size                  = heapsize - 2*SIZEOF_MM_ALLOCNODE;
  169
+  node->preceding             = SIZEOF_MM_ALLOCNODE;
  170
+
  171
+  g_heapend[IDX]              = (struct mm_allocnode_s *)(heapend - SIZEOF_MM_ALLOCNODE);
  172
+  g_heapend[IDX]->size        = SIZEOF_MM_ALLOCNODE;
  173
+  g_heapend[IDX]->preceding   = node->size | MM_ALLOC_BIT;
  174
+
  175
+#undef IDX
  176
+
  177
+#if CONFIG_MM_REGIONS > 1
  178
+  g_nregions++;
  179
+#endif
  180
+
  181
+  /* Add the single, large free node to the nodelist */
  182
+
  183
+  mm_addfreechunk(node);
  184
+}
148  libmm/mm_internal.h
... ...
@@ -0,0 +1,148 @@
  1
+/************************************************************************
  2
+ * mm/mm_internal.h
  3
+ *
  4
+ *   Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
  5
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  6
+ *
  7
+ * Redistribution and use in source and binary forms, with or without
  8
+ * modification, are permitted provided that the following conditions
  9
+ * are met:
  10
+ *
  11
+ * 1. Redistributions of source code must retain the above copyright
  12
+ *    notice, this list of conditions and the following disclaimer.
  13
+ * 2. Redistributions in binary form must reproduce the above copyright
  14
+ *    notice, this list of conditions and the following disclaimer in
  15
+ *    the documentation and/or other materials provided with the
  16
+ *    distribution.
  17
+ * 3. Neither the name NuttX nor the names of its contributors may be
  18
+ *    used to endorse or promote products derived from this software
  19
+ *    without specific prior written permission.
  20
+ *
  21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32
+ * POSSIBILITY OF SUCH DAMAGE.
  33
+ *
  34
+ ************************************************************************/
  35
+
  36
+#ifndef __MM_INTERNAL_H
  37
+#define __MM_INTERNAL_H
  38
+
  39
+/* Chunk Header Definitions *********************************************/
  40
+/* These definitions define the characteristics of allocator
  41
+ *
  42
+ * MM_MIN_SHIFT is used to define MM_MIN_CHUNK.
  43
+ * MM_MIN_CHUNK - is the smallest physical chunk that can
  44
+ *   be allocated.  It must be at least a large as
  45
+ *   sizeof(struct mm_freenode_s).  Larger values may
  46
+ *   improve performance slightly, but will waste memory
  47
+ *   due to quantization losses.
  48
+ *
  49
+ * MM_MAX_SHIFT is used to define MM_MAX_CHUNK
  50
+ * MM_MAX_CHUNK is the largest, contiguous chunk of memory
  51
+ *   that can be allocated.  It can range from 16-bytes to
  52
+ *   4Gb.  Larger values of MM_MAX_SHIFT can cause larger
  53
+ *   data structure sizes and, perhaps, minor performance
  54
+ *   losses.
  55
+ */
  56
+
  57
+# define MM_MIN_SHIFT      4  /* 16 bytes */
  58
+# define MM_MAX_SHIFT     22  /*  4 Mb */
  59
+
  60
+/* All other definitions derive from these two */
  61
+
  62
+#define MM_MIN_CHUNK     (1 << MM_MIN_SHIFT)
  63
+#define MM_MAX_CHUNK     (1 << MM_MAX_SHIFT)
  64
+#define MM_NNODES        (MM_MAX_SHIFT - MM_MIN_SHIFT + 1)
  65
+
  66
+#define MM_GRAN_MASK     (MM_MIN_CHUNK-1)
  67
+#define MM_ALIGN_UP(a)   (((a) + MM_GRAN_MASK) & ~MM_GRAN_MASK)
  68
+#define MM_ALIGN_DOWN(a) ((a) & ~MM_GRAN_MASK)
  69
+
  70
+/* An allocated chunk is distinguished from a free chunk by
  71
+ * bit 31 of the 'preceding' chunk size.  If set, then this is
  72
+ * an allocated chunk.
  73
+ */
  74
+
  75
+#define MM_ALLOC_BIT    0x80000000
  76
+#define MM_IS_ALLOCATED(n) \
  77
+  ((int)((struct mm_allocnode_s*)(n)->preceding) < 0))
  78
+
  79
+
  80
+/* Determine the size of the chunk size/offset type */
  81
+
  82
+typedef size_t mmsize_t;
  83
+#define MMSIZE_MAX SIZE_MAX
  84
+
  85
+#define CONFIG_MM_REGIONS 1
  86
+
  87
+/* This describes an allocated chunk.  An allocated chunk is
  88
+ * distinguished from a free chunk by bit 15/31 of the 'preceding' chunk
  89
+ * size.  If set, then this is an allocated chunk.
  90
+ */
  91
+
  92
+struct mm_allocnode_s
  93
+{
  94
+  mmsize_t size;           /* Size of this chunk */
  95
+  mmsize_t preceding;      /* Size of the preceding chunk */
  96
+};
  97
+
  98
+/* What is the size of the allocnode? */
  99
+
  100
+#define SIZEOF_MM_ALLOCNODE   8
  101
+
  102
+#define CHECK_ALLOCNODE_SIZE \
  103
+  DEBUGASSERT(sizeof(struct mm_allocnode_s) == SIZEOF_MM_ALLOCNODE)
  104
+
  105
+/* This describes a free chunk */
  106
+
  107
+struct mm_freenode_s
  108
+{
  109
+  mmsize_t size;                   /* Size of this chunk */
  110
+  mmsize_t preceding;              /* Size of the preceding chunk */
  111
+  struct mm_freenode_s *flink; /* Supports a doubly linked list */
  112
+  struct mm_freenode_s *blink;
  113
+};
  114
+
  115
+/* What is the size of the freenode? */
  116
+
  117
+#define SIZEOF_MM_FREENODE     16
  118
+
  119
+#define CHECK_FREENODE_SIZE \
  120
+  DEBUGASSERT(sizeof(struct mm_freenode_s) == SIZEOF_MM_FREENODE)
  121
+
  122
+
  123
+/* This is the size of the heap provided to mm */
  124
+extern size_t  g_heapsize;
  125
+
  126
+/* This is the first and last nodes of the heap */
  127
+extern struct mm_allocnode_s *g_heapstart[CONFIG_MM_REGIONS];
  128
+extern struct mm_allocnode_s *g_heapend[CONFIG_MM_REGIONS];
  129
+
  130
+#if CONFIG_MM_REGIONS > 1
  131
+extern int g_nregions;
  132
+#else
  133
+#define g_nregions 1
  134
+#endif
  135
+
  136
+/* All free nodes are maintained in a doubly linked list.  This
  137
+ * array provides some hooks into the list at various points to
  138
+ * speed searches for free nodes.
  139
+ */
  140
+
  141
+extern struct mm_freenode_s g_nodelist[MM_NNODES];
  142
+
  143
+extern void       mm_shrinkchunk(struct mm_allocnode_s *node,
  144
+                                 size_t size);
  145
+extern void       mm_addfreechunk(struct mm_freenode_s *node);
  146
+extern int        mm_size2ndx(size_t size);
  147
+
  148
+#endif /* __MM_INTERNAL_H */
104  libmm/mm_mallinfo.c
... ...
@@ -0,0 +1,104 @@
  1
+/****************************************************************************
  2
+ * mm/mm_mallinfo.c
  3
+ *
  4
+ *   Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
  5
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  6
+ *
  7
+ * Redistribution and use in source and binary forms, with or without
  8
+ * modification, are permitted provided that the following conditions
  9
+ * are met:
  10
+ *
  11
+ * 1. Redistributions of source code must retain the above copyright
  12
+ *    notice, this list of conditions and the following disclaimer.
  13
+ * 2. Redistributions in binary form must reproduce the above copyright
  14
+ *    notice, this list of conditions and the following disclaimer in
  15
+ *    the documentation and/or other materials provided with the
  16
+ *    distribution.
  17
+ * 3. Neither the name NuttX nor the names of its contributors may be
  18
+ *    used to endorse or promote products derived from this software
  19
+ *    without specific prior written permission.
  20
+ *
  21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32
+ * POSSIBILITY OF SUCH DAMAGE.
  33
+ *
  34
+ ****************************************************************************/
  35
+
  36
+#include "mm_environment.h"
  37
+#include "mm_internal.h"
  38
+
  39
+
  40
+/****************************************************************************
  41
+ * mallinfo
  42
+ *
  43
+ * Description:
  44
+ *   mallinfo returns a copy of updated current mallinfo.
  45
+ *
  46
+ ****************************************************************************/
  47
+
  48
+struct mallinfo mallinfo(void)
  49
+{
  50
+  struct mm_allocnode_s *node;
  51
+  size_t mxordblk = 0; 
  52
+  int    ordblks  = 0;  /* Number of non-inuse chunks */
  53
+  size_t uordblks = 0;  /* Total allocated space */
  54
+  size_t fordblks = 0;  /* Total non-inuse space */
  55
+#if CONFIG_MM_REGIONS > 1
  56
+  int region;
  57
+#else
  58
+# define region 0
  59
+#endif
  60
+  static struct mallinfo info;
  61
+
  62
+  /* Visit each region */
  63
+
  64
+#if CONFIG_MM_REGIONS > 1
  65
+  for (region = 0; region < g_nregions; region++)
  66
+#endif
  67
+    {
  68
+      /* Visit each node in the region */
  69
+
  70
+      for (node = g_heapstart[region];
  71
+           node < g_heapend[region];
  72
+           node = (struct mm_allocnode_s *)((char*)node + node->size))
  73
+        {
  74
+          mvdbg("region=%d node=%p preceding=%p\n", region, node, node->preceding);
  75
+          if (node->preceding & MM_ALLOC_BIT)
  76
+            {
  77
+              uordblks += node->size;
  78
+            }
  79
+          else
  80
+            {
  81
+              ordblks++;
  82
+              fordblks += node->size;
  83
+              if (node->size > mxordblk)
  84
+                {
  85
+                  mxordblk = node->size;
  86
+                }
  87
+            }
  88
+        }
  89
+
  90
+      mvdbg("region=%d node=%p g_heapend=%p\n", region, node, g_heapend[region]);
  91
+      DEBUGASSERT(node == g_heapend[region]);
  92
+      uordblks += SIZEOF_MM_ALLOCNODE; /* account for the tail node */
  93
+    }
  94
+#undef region
  95
+
  96
+  DEBUGASSERT(uordblks + fordblks == g_heapsize);
  97
+
  98
+  info.arena    = g_heapsize;
  99
+  info.ordblks  = ordblks;
  100
+  info.mxordblk = mxordblk;
  101
+  info.uordblks = uordblks;
  102
+  info.fordblks = fordblks;
  103
+  return info;
  104
+}
160  libmm/mm_malloc.c
... ...
@@ -0,0 +1,160 @@
  1
+/************************************************************
  2
+ * mm/mm_malloc.c
  3
+ *
  4
+ *   Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
  5
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  6
+ *
  7
+ * Redistribution and use in source and binary forms, with or without
  8
+ * modification, are permitted provided that the following conditions
  9
+ * are met:
  10
+ *
  11
+ * 1. Redistributions of source code must retain the above copyright
  12
+ *    notice, this list of conditions and the following disclaimer.
  13
+ * 2. Redistributions in binary form must reproduce the above copyright
  14
+ *    notice, this list of conditions and the following disclaimer in
  15
+ *    the documentation and/or other materials provided with the
  16
+ *    distribution.
  17
+ * 3. Neither the name NuttX nor the names of its contributors may be
  18
+ *    used to endorse or promote products derived from this software
  19
+ *    without specific prior written permission.
  20
+ *
  21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32
+ * POSSIBILITY OF SUCH DAMAGE.
  33
+ *
  34
+ ************************************************************/
  35
+
  36
+#include "mm_environment.h"
  37
+#include "mm_internal.h"
  38
+
  39
+/************************************************************
  40
+ * malloc
  41
+ *
  42
+ * Description:
  43
+ *  Find the smallest chunk that satisfies the request.
  44
+ *  Take the memory from that chunk, save the remaining,
  45
+ *  smaller chunk (if any).
  46
+ *
  47
+ *  8-byte alignment of the allocated data is assured.
  48
+ *
  49
+ ************************************************************/
  50
+
  51
+void *malloc(size_t size)
  52
+{
  53
+  struct mm_freenode_s *node;
  54
+  void *ret = NULL;
  55
+  int ndx;
  56
+
  57
+  /* Handle bad sizes */
  58
+
  59
+  if (size <= 0)
  60
+    {
  61
+      return NULL;
  62
+    }
  63
+
  64
+  /* Adjust the size to account for (1) the size of the allocated
  65
+   * node and (2) to make sure that it is an even multiple of
  66
+   * our granule size.
  67
+   */
  68
+
  69
+  size = MM_ALIGN_UP(size + SIZEOF_MM_ALLOCNODE);
  70
+
  71
+  /* Get the location in the node list to start the search.
  72
+   * Special case really big alloctions
  73
+   */
  74
+
  75
+  if (size >= MM_MAX_CHUNK)
  76
+    {
  77
+      ndx = MM_NNODES-1;
  78
+    }
  79
+  else
  80
+    {
  81
+      /* Convert the request size into a nodelist index */
  82
+
  83
+      ndx = mm_size2ndx(size);
  84
+    }
  85
+
  86
+  /* Search for a large enough chunk in the list of nodes.
  87
+   * This list is ordered by size, but will have occasional
  88
+   * zero sized nodes as we visit other g_nodelist[] entries.
  89
+   */
  90
+
  91
+  for (node = g_nodelist[ndx].flink;
  92
+       node && node->size < size;
  93
+       node = node->flink);
  94
+
  95
+  /* If we found a node with non-zero size, then this is one
  96
+   * to use. Since the list is ordered, we know that is must be
  97
+   * best fitting chunk available.
  98
+   */
  99
+
  100
+  if (node)
  101
+    {
  102
+      struct mm_freenode_s *remainder;
  103
+      struct mm_freenode_s *next;
  104
+      size_t remaining;
  105
+
  106
+      /* Remove the node.  There must be a predecessor, but there may
  107
+       * not be a successor node.
  108
+       */
  109
+
  110
+      DEBUGASSERT(node->blink);
  111
+      node->blink->flink = node->flink;
  112
+      if (node->flink)
  113
+        {
  114
+          node->flink->blink = node->blink;
  115
+        }
  116
+
  117
+      /* Check if we have to split the free node into one of the
  118
+       * allocated size and another smaller freenode.  In some
  119
+       * cases, the remaining bytes can be smaller (they may be
  120
+       * SIZEOF_MM_ALLOCNODE).  In that case, we will just carry
  121
+       * the few wasted bytes at the end of the allocation.
  122
+       */
  123
+
  124
+      remaining = node->size - size;
  125
+      if (remaining >= SIZEOF_MM_FREENODE)
  126
+        {
  127
+          /* Get a pointer to the next node in physical memory */
  128
+
  129
+          next = (struct mm_freenode_s*)(((char*)node) + node->size);
  130
+
  131
+          /* Create the remainder node */
  132
+
  133
+          remainder = (struct mm_freenode_s*)(((char*)node) + size);
  134
+          remainder->size = remaining;
  135
+          remainder->preceding = size;
  136
+
  137
+          /* Adjust the size of the node under consideration */
  138
+
  139
+          node->size = size;
  140
+
  141
+          /* Adjust the 'preceding' size of the (old) next node,
  142
+           * preserving the allocated flag.
  143
+           */
  144
+
  145
+          next->preceding = remaining | (next->preceding & MM_ALLOC_BIT);
  146
+
  147
+          /* Add the remainder back into the nodelist */
  148
+
  149
+          mm_addfreechunk(remainder);
  150
+        }
  151
+
  152
+      /* Handle the case of an exact size match */
  153
+
  154
+      node->preceding |= MM_ALLOC_BIT;
  155
+      ret = (void*)((char*)node + SIZEOF_MM_ALLOCNODE);
  156
+    }
  157
+
  158
+  mvdbg("Allocated %p, size %d\n", ret, size);
  159
+  return ret;
  160
+}
190  libmm/mm_memalign.c
... ...
@@ -0,0 +1,190 @@
  1
+/************************************************************
  2
+ * mm/mm_memalign.c
  3
+ *
  4
+ *   Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
  5
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  6
+ *
  7
+ * Redistribution and use in source and binary forms, with or without
  8
+ * modification, are permitted provided that the following conditions
  9
+ * are met:
  10
+ *
  11
+ * 1. Redistributions of source code must retain the above copyright
  12
+ *    notice, this list of conditions and the following disclaimer.
  13
+ * 2. Redistributions in binary form must reproduce the above copyright
  14
+ *    notice, this list of conditions and the following disclaimer in
  15
+ *    the documentation and/or other materials provided with the
  16
+ *    distribution.
  17
+ * 3. Neither the name NuttX nor the names of its contributors may be
  18
+ *    used to endorse or promote products derived from this software
  19
+ *    without specific prior written permission.
  20
+ *
  21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32
+ * POSSIBILITY OF SUCH DAMAGE.
  33
+ *
  34
+ ************************************************************/
  35
+
  36
+#include "mm_environment.h"
  37
+#include "mm_internal.h"
  38
+
  39
+/************************************************************
  40
+ * memalign
  41
+ *
  42
+ * Description:
  43
+ *   memalign requests more than enough space from malloc,
  44
+ *   finds a region within that chunk that meets the alignment
  45
+ *   request and then frees any leading or trailing space. 
  46
+ *
  47
+ *   The alignment argument must be a power of two (not
  48
+ *   checked).  8-byte alignment is guaranteed by normal
  49
+ *   malloc calls.
  50
+ *
  51
+ ************************************************************/
  52
+
  53
+void *memalign(size_t alignment, size_t size)
  54
+{
  55
+  struct mm_allocnode_s *node;
  56
+  size_t rawchunk;
  57
+  size_t alignedchunk;
  58
+  size_t mask = (size_t)(alignment - 1);
  59
+  size_t allocsize;
  60
+
  61
+  /* If this requested alignement less than or equal to the
  62
+   * natural alignment of malloc, then just let malloc do the
  63
+   * work.
  64
+   */
  65
+
  66
+  if (alignment <= MM_MIN_CHUNK)
  67
+    {
  68
+      return malloc(size);
  69
+    }
  70
+
  71
+  /* Adjust the size to account for (1) the size of the allocated
  72
+   * node, (2) to make sure that it is an even multiple of
  73
+   * our granule size, and to include the alignment amount.
  74
+   *
  75
+   * Notice that we increase the allocation size by twice the
  76
+   * the requested alignment.  We do this so that there will
  77
+   * be at least two valid alignment points within the allocated
  78
+   * memory.
  79
+   *
  80
+   * NOTE:  These are sizes given to malloc and not chunk sizes.
  81
+   * The do not include SIZEOF_MM_ALLOCNODE.
  82
+   */
  83
+
  84
+  size      = MM_ALIGN_UP(size);   /* Make multiples of our granule size */
  85
+  allocsize = size + 2*alignment;  /* Add double full alignment size */
  86
+
  87
+  /* Then malloc that size */
  88
+
  89
+  rawchunk = (size_t)malloc(allocsize);
  90
+  if (rawchunk == 0)
  91
+    {
  92
+      return NULL;
  93
+    }
  94
+
  95
+  /* Get the node associated with the allocation and the next
  96
+   * node after the allocation.
  97
+   */
  98
+
  99
+  node = (struct mm_allocnode_s*)(rawchunk - SIZEOF_MM_ALLOCNODE);
  100
+
  101
+  /* Find the aligned subregion */
  102
+
  103
+  alignedchunk = (rawchunk + mask) & ~mask;
  104
+
  105
+  /* Check if there is free space at the beginning of the aligned chunk */
  106
+
  107
+  if (alignedchunk != rawchunk)
  108
+    {
  109
+      struct mm_allocnode_s *newnode;
  110
+      struct mm_allocnode_s *next;
  111
+      size_t precedingsize;
  112
+
  113
+      /* Get the node the next node after the allocation. */
  114
+
  115
+      next = (struct mm_allocnode_s*)((char*)node + node->size);
  116
+
  117
+      /* Make sure that there is space to convert the preceding mm_allocnode_s
  118
+       * into an mm_freenode_s.  I think that this should always be true
  119
+       */
  120
+
  121
+      DEBUGASSERT(alignedchunk >= rawchunk + 8);
  122
+
  123
+      newnode = (struct mm_allocnode_s*)(alignedchunk - SIZEOF_MM_ALLOCNODE);
  124
+
  125
+      /* Preceding size is full size of the new 'node,' including
  126
+       * SIZEOF_MM_ALLOCNODE
  127
+       */
  128
+
  129
+      precedingsize = (size_t)newnode - (size_t)node;
  130
+
  131
+      /* If we were unlucky, then the alignedchunk can lie in such
  132
+       * a position that precedingsize < SIZEOF_NODE_FREENODE.  We 
  133
+       * can't let that happen because we are going to cast 'node' to
  134
+       * struct mm_freenode_s below.  This is why we allocated memory
  135
+       * large enough to support two alignment points.  In this case,
  136
+       * we will simply use the second alignment point.
  137
+       */
  138
+
  139
+      if (precedingsize < SIZEOF_MM_FREENODE)
  140
+        {
  141
+          alignedchunk += alignment;
  142
+          newnode       = (struct mm_allocnode_s*)(alignedchunk - SIZEOF_MM_ALLOCNODE);
  143
+          precedingsize = (size_t)newnode - (size_t)node;
  144
+        }
  145
+
  146
+      /* Set up the size of the new node */
  147
+
  148
+      newnode->size = (size_t)next - (size_t)newnode;
  149
+      newnode->preceding = precedingsize | MM_ALLOC_BIT;
  150
+
  151
+      /* Reduce the size of the original chunk and mark it not allocated, */
  152
+
  153
+      node->size = precedingsize;
  154
+      node->preceding &= ~MM_ALLOC_BIT;
  155
+
  156
+      /* Fix the preceding size of the next node */
  157
+
  158
+      next->preceding = newnode->size | (next->preceding & MM_ALLOC_BIT);
  159
+
  160
+      /* Convert the newnode chunk size back into malloc-compatible
  161
+       * size by subtracting the header size SIZEOF_MM_ALLOCNODE.
  162
+       */
  163
+
  164
+      allocsize = newnode->size - SIZEOF_MM_ALLOCNODE;
  165
+
  166
+      /* Add the original, newly freed node to the free nodelist */
  167
+
  168
+      mm_addfreechunk((struct mm_freenode_s *)node);
  169
+
  170
+      /* Replace the original node with the newlay realloaced,
  171
+       * aligned node
  172
+       */
  173
+
  174
+      node = newnode;
  175
+    }
  176
+
  177
+  /* Check if there is free space at the end of the aligned chunk */
  178
+
  179
+  if (allocsize > size)
  180
+    {
  181
+      /* Shrink the chunk by that much -- remember, mm_shrinkchunk
  182
+       * wants internal chunk sizes that include SIZEOF_MM_ALLOCNODE,
  183
+       * and not the malloc-compatible sizes that we have.
  184
+       */
  185
+
  186
+      mm_shrinkchunk(node, size + SIZEOF_MM_ALLOCNODE);
  187
+    }
  188
+
  189
+  return (void*)alignedchunk;
  190
+}
328  libmm/mm_realloc.c
... ...
@@ -0,0 +1,328 @@
  1
+/************************************************************
  2
+ * mm/mm_realloc.c
  3
+ *
  4
+ *   Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
  5
+ *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  6
+ *
  7
+ * Redistribution and use in source and binary forms, with or without
  8
+ * modification, are permitted provided that the following conditions
  9
+ * are met:
  10
+ *
  11
+ * 1. Redistributions of source code must retain the above copyright
  12
+ *    notice, this list of conditions and the following disclaimer.
  13
+ * 2. Redistributions in binary form must reproduce the above copyright
  14
+ *    notice, this list of conditions and the following disclaimer in
  15
+ *    the documentation and/or other materials provided with the
  16
+ *    distribution.
  17
+ * 3. Neither the name NuttX nor the names of its contributors may be
  18
+ *    used to endorse or promote products derived from this software
  19
+ *    without specific prior written permission.
  20
+ *