summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-03-08 18:29:56 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-03-08 18:29:56 +0000
commit6137a8aa8f69cb0c197efced18d7e49144791666 (patch)
treefda5a4a9a19544410ab1c45ef4b3e83e92894241
parent62bccf6b7538cafa63e0ea91ccb603f58417a49a (diff)
downloadpx4-nuttx-6137a8aa8f69cb0c197efced18d7e49144791666.tar.gz
px4-nuttx-6137a8aa8f69cb0c197efced18d7e49144791666.tar.bz2
px4-nuttx-6137a8aa8f69cb0c197efced18d7e49144791666.zip
Move all memory manager globals to a structure. Pass structure pointer as a handler because MM APIs
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5719 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/ChangeLog4
-rw-r--r--nuttx/TODO67
-rw-r--r--nuttx/arch/arm/src/lm/chip/lm4f_syscontrol.h38
-rw-r--r--nuttx/include/nuttx/kmalloc.h10
-rw-r--r--nuttx/include/nuttx/mm.h14
-rw-r--r--nuttx/mm/Makefile.test37
-rw-r--r--nuttx/mm/mm_addfreechunk.c6
-rw-r--r--nuttx/mm/mm_environment.h14
-rw-r--r--nuttx/mm/mm_free.c38
-rw-r--r--nuttx/mm/mm_initialize.c219
-rw-r--r--nuttx/mm/mm_internal.h102
-rw-r--r--nuttx/mm/mm_mallinfo.c87
-rw-r--r--nuttx/mm/mm_malloc.c41
-rw-r--r--nuttx/mm/mm_memalign.c43
-rw-r--r--nuttx/mm/mm_realloc.c60
-rw-r--r--nuttx/mm/mm_sem.c64
-rw-r--r--nuttx/mm/mm_shrinkchunk.c9
-rw-r--r--nuttx/mm/mm_test.c23
18 files changed, 569 insertions, 307 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 753e4c88c..62d0fe287 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -4281,3 +4281,7 @@
* net/net_poll.c: Handle the missing case. Now tests for not connected
AND not listening. I think that now covers all of the cases including
the missing case noted above. (2013-03-07)
+ * mm/: Move all memory manager globals into a structure. A reference
+ to this structure is now passed internally between mm APIs. This
+ change will (eventually) support multiple heaps and heap allocators.
+
diff --git a/nuttx/TODO b/nuttx/TODO
index 96a4f8c7e..5524fe256 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -1,4 +1,4 @@
-NuttX TODO List (Last updated March 6, 2013)
+NuttX TODO List (Last updated March 8, 2013)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@@ -7,8 +7,8 @@ standards, things that could be improved, and ideas for enhancements.
nuttx/
(10) Task/Scheduler (sched/)
- (1) Memory Managment (mm/)
- (3) Signals (sched/, arch/)
+ (2) Memory Managment (mm/)
+ (4) Signals (sched/, arch/)
(2) pthreads (sched/)
(2) C++ Support
(6) Binary loaders (binfmt/)
@@ -99,7 +99,7 @@ o Task/Scheduler (sched/)
Status: Open.
Priority: Medium Low.
- Title: ON-DEMAND PAGE INCOMPLETE
+ Title: ON-DEMAND PAGING INCOMPLETE
Description: On-demand paging has recently been incorporated into the RTOS.
The design of this feature is described here:
http://www.nuttx.org/NuttXDemandPaging.html.
@@ -253,6 +253,53 @@ o Memory Managment (mm/)
Priority: Medium/Low, a good feature to prevent memory leaks but would
have negative impact on memory usage and code size.
+ Title: MEMORY MANAGEMENT IN THE KERNEL BUILD
+ Description: If the option CONFIG_NUTTX_KERNEL is selected, then NuttX will
+ built as two separate blobs: (1) a monolithic, NuttX kernel,
+ and (2) a user-space application blob. Communication between
+ the two is via traps in order to get from user-mode to kernel-
+ mode.
+
+ At present, the final link of the kernel build fails because
+ of undefined memory allocation logic: kmm_initialize, kmm_addregion,
+ kmalloc, etc. In the flat build, these map to mm_initialize,
+ mm_addregion, malloc, etc. but they are undefined in the kernel
+ build.
+
+ It has not been fully decided how to handle kernel- and user-
+ memory allocations. Here are some ideas:
+
+ 1) Have only a single user-space heap and heap allocator that
+ is shared by both kernel- and user-modes. PROs: Simpler,
+ CONs: Awkward architecture and no security for kernel-mode
+ allocations.
+
+ 2) Have two separate heap partitions and two copies of the
+ memory allocators. PROs: Not two difficult, CONs: Partitioning
+ the heap will not make the best use of heap memory.
+
+ A complication is that the kernel needs to allocate both
+ protected, kernel private as well as user accessible memory
+ (such as for stacks). Perhaps this approach would require
+ three heap partitions.
+
+ 3) Have a classes of two allocators: (1) one that allocates large
+ regions/pages of memory that can be protected or not, and
+ (2) the current memory allocator extended to support sbrk().
+ The would still be kernel- and user-mode instances of the
+ memory allocators. Each would sbrk() as necessary to extend
+ their heap; the pages allocated for the kerne-mode allocator
+ would be protected but the pages allocated for the user-mode
+ allocator would not. PROs: Meets all of the needs. CONs:
+ would limit the size of allocations due to the physical
+ pages. Complex. There would likely be some small memory
+ inefficiencies due to quantization to pages. This really
+ feels like overkill for this class of processor.
+
+ See other kernel build issues under "Build system"
+ Status: Open
+ Priority: Low, unless you need a working kernel build now.
+
o Signals (sched/, arch/)
^^^^^^^^^^^^^^^^^^^^^^^
@@ -281,6 +328,14 @@ o Signals (sched/, arch/)
Status: Open
Priority: Low. Even if there are only 31 usable signals, that is still a lot.
+ Title: USER-MODE SIGNALS
+ Description: In a kernel build (CONFIG_NUTTX_KERNEL). Signal handlers should
+ execute in user mode. This is to prevent a security hole where
+ user code can get control of the system in kernel mode if the signal
+ executes in kernel mode.
+ Status: Open
+ Priority: Low
+
o pthreads (sched/)
^^^^^^^^^^^^^^^^^
@@ -1054,6 +1109,8 @@ o Build system
A similar issue exists in NSH that uses some internal OS
interfaces that would not be available in a kernel build
(such as foreach_task, foreach_mountpoint, etc.).
+
+ See also "Memory Management" for another kernel build issue.
Status: Open
Priority: Low -- the kernel build configuration is not fully fielded
yet.
@@ -1772,7 +1829,7 @@ o z80/z8/ez80/z180 (arch/z80)
Title: ZDS-II COMPILER PROBLEMS
Description: The ZDS-II compiler (version 4.10.1) fails with an internal error
- while compiler mm/mm_initialize. This has been reported as
+ while compiling mm/mm_initialize.c. This has been reported as
incident 81509.
I have found the following workaround that I use to build for the
diff --git a/nuttx/arch/arm/src/lm/chip/lm4f_syscontrol.h b/nuttx/arch/arm/src/lm/chip/lm4f_syscontrol.h
index 9696962c9..e0701c11e 100644
--- a/nuttx/arch/arm/src/lm/chip/lm4f_syscontrol.h
+++ b/nuttx/arch/arm/src/lm/chip/lm4f_syscontrol.h
@@ -416,8 +416,8 @@
#define SYSCON_RCC_OSCSRC_SHIFT 4 /* Bits 5-4: Oscillator Source */
#define SYSCON_RCC_OSCSRC_MASK (0x03 << SYSCON_RCC_OSCSRC_SHIFT)
# define SYSCON_RCC_OSCSRC_MOSC (0 << SYSCON_RCC_OSCSRC_SHIFT) /* Main oscillator */
-# define SYSCON_RCC_OSCSRC_IOSC (1 << SYSCON_RCC_OSCSRC_SHIFT) /* Precision internal oscillator (reset) */
-# define SYSCON_RCC_OSCSRC_IOSC4 (2 << SYSCON_RCC_OSCSRC_SHIFT) /* Precision internal oscillator / 4 */
+# define SYSCON_RCC_OSCSRC_PIOSC (1 << SYSCON_RCC_OSCSRC_SHIFT) /* Precision internal oscillator (reset) */
+# define SYSCON_RCC_OSCSRC_PIOSC4 (2 << SYSCON_RCC_OSCSRC_SHIFT) /* Precision internal oscillator / 4 */
# define SYSCON_RCC_OSCSRC_LFIOSC (3 << SYSCON_RCC_OSCSRC_SHIFT) /* Low-frequency internal oscillator */
#define SYSCON_RCC_XTAL_SHIFT 6 /* Bits 10-6: Crystal Value */
#define SYSCON_RCC_XTAL_MASK (31 << SYSCON_RCC_XTAL_SHIFT)
@@ -425,23 +425,23 @@
# define SYSCON_RCC_XTAL4096KHZ (7 << SYSCON_RCC_XTAL_SHIFT) /* 4.096 MHz (NO PLL) */
# define SYSCON_RCC_XTAL4915p2KHZ (8 << SYSCON_RCC_XTAL_SHIFT) /* 4.9152 MHz (NO PLL) */
# define SYSCON_RCC_XTAL5000KHZ (9 << SYSCON_RCC_XTAL_SHIFT) /* 5 MHz (USB) */
-# define SYSCON_RCC_XTAL5120KHZ (10 << SYSCON_RCC_XTAL_SHIFT) /* 5.12 MHz */
-# define SYSCON_RCC_XTAL6000KHZ (11 << SYSCON_RCC_XTAL_SHIFT) /* 6 MHz (USB) */
-# define SYSCON_RCC_XTAL6144KHZ (12 << SYSCON_RCC_XTAL_SHIFT) /* 6.144 MHz */
-# define SYSCON_RCC_XTAL7372p8KHZ (13 << SYSCON_RCC_XTAL_SHIFT) /* 7.3728 MHz */
-# define SYSCON_RCC_XTAL8000KHZ (14 << SYSCON_RCC_XTAL_SHIFT) /* 8 MHz (USB) */
-# define SYSCON_RCC_XTAL8192KHZ (15 << SYSCON_RCC_XTAL_SHIFT) /* 8.192 MHz */
-# define SYSCON_RCC_XTAL10000KHZ (16 << SYSCON_RCC_XTAL_SHIFT) /* 10.0 MHz (USB) */
-# define SYSCON_RCC_XTAL12000KHZ (17 << SYSCON_RCC_XTAL_SHIFT) /* 12.0 MHz (USB) */
-# define SYSCON_RCC_XTAL12288KHZ (18 << SYSCON_RCC_XTAL_SHIFT) /* 12.288 MHz */
-# define SYSCON_RCC_XTAL13560KHZ (19 << SYSCON_RCC_XTAL_SHIFT) /* 13.56 MHz */
-# define SYSCON_RCC_XTAL14318p18KHZ (20 << SYSCON_RCC_XTAL_SHIFT) /* 14.31818 MHz */
-# define SYSCON_RCC_XTAL16000KHZ (21 << SYSCON_RCC_XTAL_SHIFT) /* 16.0 MHz (USB) */
-# define SYSCON_RCC_XTAL16384KHZ (22 << SYSCON_RCC_XTAL_SHIFT) /* 16.384 MHz */
-# define SYSCON_RCC_XTAL18000KHZ (23 << SYSCON_RCC_XTAL_SHIFT) /* 18.0 MHz (USB) */
-# define SYSCON_RCC_XTAL20000KHZ (24 << SYSCON_RCC_XTAL_SHIFT) /* 20.0 MHz (USB) */
-# define SYSCON_RCC_XTAL24000KHZ (25 << SYSCON_RCC_XTAL_SHIFT) /* 24.0 MHz (USB) */
-# define SYSCON_RCC_XTAL25000KHZ (26 << SYSCON_RCC_XTAL_SHIFT) /* 25.0 MHz (USB) */
+# define SYSCON_RCC_XTAL5120KHZ (10 << SYSCON_RCC_XTAL_SHIFT) /* 5.12 MHz */
+# define SYSCON_RCC_XTAL6000KHZ (11 << SYSCON_RCC_XTAL_SHIFT) /* 6 MHz (USB) */
+# define SYSCON_RCC_XTAL6144KHZ (12 << SYSCON_RCC_XTAL_SHIFT) /* 6.144 MHz */
+# define SYSCON_RCC_XTAL7372p8KHZ (13 << SYSCON_RCC_XTAL_SHIFT) /* 7.3728 MHz */
+# define SYSCON_RCC_XTAL8000KHZ (14 << SYSCON_RCC_XTAL_SHIFT) /* 8 MHz (USB) */
+# define SYSCON_RCC_XTAL8192KHZ (15 << SYSCON_RCC_XTAL_SHIFT) /* 8.192 MHz */
+# define SYSCON_RCC_XTAL10000KHZ (16 << SYSCON_RCC_XTAL_SHIFT) /* 10.0 MHz (USB) */
+# define SYSCON_RCC_XTAL12000KHZ (17 << SYSCON_RCC_XTAL_SHIFT) /* 12.0 MHz (USB) */
+# define SYSCON_RCC_XTAL12288KHZ (18 << SYSCON_RCC_XTAL_SHIFT) /* 12.288 MHz */
+# define SYSCON_RCC_XTAL13560KHZ (19 << SYSCON_RCC_XTAL_SHIFT) /* 13.56 MHz */
+# define SYSCON_RCC_XTAL14318p18KHZ (20 << SYSCON_RCC_XTAL_SHIFT) /* 14.31818 MHz */
+# define SYSCON_RCC_XTAL16000KHZ (21 << SYSCON_RCC_XTAL_SHIFT) /* 16.0 MHz (USB) */
+# define SYSCON_RCC_XTAL16384KHZ (22 << SYSCON_RCC_XTAL_SHIFT) /* 16.384 MHz */
+# define SYSCON_RCC_XTAL18000KHZ (23 << SYSCON_RCC_XTAL_SHIFT) /* 18.0 MHz (USB) */
+# define SYSCON_RCC_XTAL20000KHZ (24 << SYSCON_RCC_XTAL_SHIFT) /* 20.0 MHz (USB) */
+# define SYSCON_RCC_XTAL24000KHZ (25 << SYSCON_RCC_XTAL_SHIFT) /* 24.0 MHz (USB) */
+# define SYSCON_RCC_XTAL25000KHZ (26 << SYSCON_RCC_XTAL_SHIFT) /* 25.0 MHz (USB) */
#define SYSCON_RCC_BYPASS (1 << 11) /* Bit 11: PLL Bypass */
#define SYSCON_RCC_PWRDN (1 << 13) /* Bit 13: PLL Power Down */
#define SYSCON_RCC_USESYSDIV (1 << 22) /* Bit 22: Enable System Clock Divider */
diff --git a/nuttx/include/nuttx/kmalloc.h b/nuttx/include/nuttx/kmalloc.h
index de0246370..d6a1bd0b4 100644
--- a/nuttx/include/nuttx/kmalloc.h
+++ b/nuttx/include/nuttx/kmalloc.h
@@ -60,7 +60,8 @@
#undef KMALLOC_EXTERN
#if defined(__cplusplus)
# define KMALLOC_EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
# define KMALLOC_EXTERN extern
#endif
@@ -76,10 +77,13 @@ extern "C" {
#ifndef CONFIG_NUTTX_KERNEL
+struct mm_heap_s;
+extern struct mm_heap_s g_mmheap;
+
# define kmm_initialize(h,s) mm_initialize(h,s)
# define kmm_addregion(h,s) mm_addregion(h,s)
-# define kmm_trysemaphore() mm_trysemaphore()
-# define kmm_givesemaphore() mm_givesemaphore()
+# define kmm_trysemaphore() mm_trysemaphore(&g_mmheap)
+# define kmm_givesemaphore() mm_givesemaphore(&g_mmheap)
# define kmalloc(s) malloc(s)
# define kzalloc(s) zalloc(s)
diff --git a/nuttx/include/nuttx/mm.h b/nuttx/include/nuttx/mm.h
index cabab2619..feb45a931 100644
--- a/nuttx/include/nuttx/mm.h
+++ b/nuttx/include/nuttx/mm.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/mm.h
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -61,20 +61,22 @@
#ifdef __cplusplus
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
/* Functions contained in mm_initialize.c ***********************************/
-EXTERN void mm_initialize(FAR void *heap_start, size_t heap_size);
-EXTERN void mm_addregion(FAR void *heapstart, size_t heapsize);
+void mm_initialize(FAR void *heap_start, size_t heap_size);
+void mm_addregion(FAR void *heapstart, size_t heapsize);
/* Functions contained in mm_sem.c ******************************************/
-EXTERN int mm_trysemaphore(void);
-EXTERN void mm_givesemaphore(void);
+struct mm_heap_s;
+int mm_trysemaphore(FAR struct mm_heap_s *heap);
+void mm_givesemaphore(FAR struct mm_heap_s *heap);
#undef EXTERN
#ifdef __cplusplus
diff --git a/nuttx/mm/Makefile.test b/nuttx/mm/Makefile.test
index 2ae9dcb88..8a9e0d886 100644
--- a/nuttx/mm/Makefile.test
+++ b/nuttx/mm/Makefile.test
@@ -35,34 +35,33 @@
-include $(TOPDIR)/Make.defs
-SRCS = mm_test.c mm_initialize.c mm_sem.c mm_addfreechunk.c mm_size2ndx.c mm_shrinkchunk.c \
- mm_malloc.c mm_zalloc.c mm_calloc.c mm_realloc.c \
- mm_memalign.c mm_free.c mm_mallinfo.c
-OBJS = $(SRCS:.c=.o1)
+SRCS = mm_test.c mm_initialize.c mm_sem.c mm_addfreechunk.c mm_size2ndx.c
+SRCS += mm_shrinkchunk.c mm_malloc.c mm_zalloc.c mm_calloc.c mm_realloc.c
+SRCS += mm_memalign.c mm_free.c mm_mallinfo.c
+OBJS = $(SRCS:.c=.o1)
-LIBS = -lpthread -lc
+LIBS = -lpthread -lc
-CC = gcc
-LD = gcc
+CC = gcc
+LD = gcc
-DEFINES = -DMM_TEST=1
-WARNIGNS = -Wall -Wstrict-prototypes -Wshadow
-CFLAGS = -g $(DEFINES)
-LDFLAGS =
+DEFINES = -DMM_TEST=1
+WARNIGNS = -Wall -Wstrict-prototypes -Wshadow
+CFLAGS = -g $(DEFINES)
+LDFLAGS =
-BIN = ..$(DELIM)mm_test
+BIN = mm_test
-all: $(BIN)
+all: $(BIN)
$(OBJS): %.o1: %.c
@echo "Compiling $<"
- $(Q) $(CC) -c $(CFLAGS) $< -o $@
+ @$(CC) -c $(CFLAGS) $< -o $@
-$(BIN): $(OBJS)
+$(BIN): $(OBJS)
@echo "Linking {$(OBJS)} to produce $@"
- $(Q) $(LD) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
+ @$(LD) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
clean:
- $(call DELFILE, $(BIN))
- $(call DELFILE, *.o1)
- $(call CLEAN)
+ rm -f $(BIN)
+ rm -f *.o1
diff --git a/nuttx/mm/mm_addfreechunk.c b/nuttx/mm/mm_addfreechunk.c
index fdda3ed8d..61c11baaf 100644
--- a/nuttx/mm/mm_addfreechunk.c
+++ b/nuttx/mm/mm_addfreechunk.c
@@ -1,7 +1,7 @@
/****************************************************************************
* mm/mm_addfreechunk.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -61,7 +61,7 @@
*
****************************************************************************/
-void mm_addfreechunk(FAR struct mm_freenode_s *node)
+void mm_addfreechunk(FAR struct mm_heap_s *heap, FAR struct mm_freenode_s *node)
{
FAR struct mm_freenode_s *next;
FAR struct mm_freenode_s *prev;
@@ -72,7 +72,7 @@ void mm_addfreechunk(FAR struct mm_freenode_s *node)
/* Now put the new node int the next */
- for (prev = &g_nodelist[ndx], next = g_nodelist[ndx].flink;
+ for (prev = &heap->mm_nodelist[ndx], next = heap->mm_nodelist[ndx].flink;
next && next->size && next->size < node->size;
prev = next, next = next->flink);
diff --git a/nuttx/mm/mm_environment.h b/nuttx/mm/mm_environment.h
index d28fbf1d7..0f9967bcb 100644
--- a/nuttx/mm/mm_environment.h
+++ b/nuttx/mm/mm_environment.h
@@ -40,7 +40,7 @@
* Included Files
****************************************************************************/
-/* The platform configuratioin file will not be included when the memory
+/* The platform configuration file will not be included when the memory
* manager is built for the host-based test harness.
*/
@@ -50,13 +50,17 @@
# include <sys/types.h>
# include <stdlib.h>
# include <string.h>
-# include <debug.h>
+# include <semaphore.h>
# include <errno.h>
# include <assert.h>
# include <nuttx/mm.h>
+# include <debug.h>
#else
# include <sys/types.h>
+
+# include <stdio.h>
# include <string.h>
+# include <semaphore.h>
# include <assert.h>
#endif
@@ -79,7 +83,7 @@
# define CONFIG_CAN_PASS_STRUCTS 1 /* Normally in config.h */
# undef CONFIG_SMALL_MEMORY /* Normally in config.h */
-extern void mm_addregion(FAR void *heapstart, size_t heapsize);
+void mm_addregion(FAR void *heapstart, size_t heapsize);
/* Use the real system errno */
@@ -103,6 +107,10 @@ extern void mm_addregion(FAR void *heapstart, size_t heapsize);
# undef DEBUGASSERT
# define DEBUGASSERT(e) assert(e)
+/* Misc. NuttX-isms */
+
+#define OK 0
+
/* Debug macros are always on */
# define CONFIG_DEBUG 1
diff --git a/nuttx/mm/mm_free.c b/nuttx/mm/mm_free.c
index b34b8a459..7f7d92b16 100644
--- a/nuttx/mm/mm_free.c
+++ b/nuttx/mm/mm_free.c
@@ -1,7 +1,7 @@
/****************************************************************************
* mm/mm_free.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -51,19 +51,15 @@
****************************************************************************/
/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: free
+ * Name: _mm_free
*
* Description:
- * Returns a chunk of memory into the list of free nodes, merging with
+ * Returns a chunk of memory to the list of free nodes, merging with
* adjacent free chunks if possible.
*
****************************************************************************/
-void free(FAR void *mem)
+static inline void _mm_free(FAR struct mm_heap_s *heap, FAR void *mem)
{
FAR struct mm_freenode_s *node;
FAR struct mm_freenode_s *prev;
@@ -82,7 +78,7 @@ void free(FAR void *mem)
* nodelist.
*/
- mm_takesemaphore();
+ mm_takesemaphore(heap);
/* Map the memory chunk into a free node */
@@ -148,6 +144,26 @@ void free(FAR void *mem)
/* Add the merged node to the nodelist */
- mm_addfreechunk(node);
- mm_givesemaphore();
+ mm_addfreechunk(heap, node);
+ mm_givesemaphore(heap);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: free
+ *
+ * Description:
+ * Returns a chunk of memory to the list of free nodes, merging with
+ * adjacent free chunks if possible.
+ *
+ ****************************************************************************/
+
+#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
+void free(FAR void *mem)
+{
+ _mm_free(&g_mmheap, mem);
}
+#endif
diff --git a/nuttx/mm/mm_initialize.c b/nuttx/mm/mm_initialize.c
index a7f64cfaf..d536774ee 100644
--- a/nuttx/mm/mm_initialize.c
+++ b/nuttx/mm/mm_initialize.c
@@ -1,7 +1,7 @@
/****************************************************************************
* mm/mm_initialize.c
*
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -48,37 +48,110 @@
* Public Variables
****************************************************************************/
-/* This is the size of the heap provided to mm */
+#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
+/* This is the user heap */
-size_t g_heapsize;
+struct mm_heap_s g_mmheap;
-/* This is the first and last nodes of the heap */
+#endif
-FAR struct mm_allocnode_s *g_heapstart[CONFIG_MM_REGIONS];
-FAR struct mm_allocnode_s *g_heapend[CONFIG_MM_REGIONS];
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: _mm_addregion
+ *
+ * Description:
+ * This function adds a region of contiguous memory to the selected heap.
+ *
+ * Parameters:
+ * heap - The selected heap
+ * heapstart - Start of the heap region
+ * heapsize - Size of the heap region
+ *
+ * Return Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static inline void _mm_addregion(FAR struct mm_heap_s *heap,
+ FAR void *heapstart, size_t heapsize)
+{
+ FAR struct mm_freenode_s *node;
+ uintptr_t heapbase;
+ uintptr_t heapend;
#if CONFIG_MM_REGIONS > 1
-int g_nregions;
+ int IDX = heap->mm_nregions;
+#else
+# define IDX 0
#endif
-/* All free nodes are maintained in a doubly linked list. This array
- * provides some hooks into the list at various points to speed searches for
- * free nodes.
- */
+ /* If the MCU handles wide addresses but the memory manager is configured
+ * for a small heap, then verify that the caller is not doing something
+ * crazy.
+ */
-FAR struct mm_freenode_s g_nodelist[MM_NNODES];
+#if defined(CONFIG_MM_SMALL) && !defined(CONFIG_SMALL_MEMORY)
+ DEBUGASSERT(heapsize <= MMSIZE_MAX+1);
+#endif
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
+ /* Adjust the provide heap start and size so that they are both aligned
+ * with the MM_MIN_CHUNK size.
+ */
+
+ heapbase = MM_ALIGN_UP((uintptr_t)heapstart);
+ heapend = MM_ALIGN_DOWN((uintptr_t)heapstart + (uintptr_t)heapsize);
+ heapsize = heapend - heapbase;
+
+ mlldbg("Region %d: base=%p size=%u\n", IDX+1, heapstart, heapsize);
+
+ /* Add the size of this region to the total size of the heap */
+
+ heap->mm_heapsize += heapsize;
+
+ /* Create two "allocated" guard nodes at the beginning and end of
+ * the heap. These only serve to keep us from allocating outside
+ * of the heap.
+ *
+ * And create one free node between the guard nodes that contains
+ * all available memory.
+ */
+
+ heap->mm_heapstart[IDX] = (FAR struct mm_allocnode_s *)heapbase;
+ heap->mm_heapstart[IDX]->size = SIZEOF_MM_ALLOCNODE;
+ heap->mm_heapstart[IDX]->preceding = MM_ALLOC_BIT;
+
+ node = (FAR struct mm_freenode_s *)(heapbase + SIZEOF_MM_ALLOCNODE);
+ node->size = heapsize - 2*SIZEOF_MM_ALLOCNODE;
+ node->preceding = SIZEOF_MM_ALLOCNODE;
+
+ heap->mm_heapend[IDX] = (FAR struct mm_allocnode_s *)(heapend - SIZEOF_MM_ALLOCNODE);
+ heap->mm_heapend[IDX]->size = SIZEOF_MM_ALLOCNODE;
+ heap->mm_heapend[IDX]->preceding = node->size | MM_ALLOC_BIT;
+
+#undef IDX
+
+#if CONFIG_MM_REGIONS > 1
+ heap->mm_nregions++;
+#endif
+
+ /* Add the single, large free node to the nodelist */
+
+ mm_addfreechunk(heap, node);
+}
/****************************************************************************
- * Name: mm_initialize
+ * Name: _mm_initialize
*
* Description:
- * This is an internal OS function called only at power-up boot time.
+ * Initialize the selected heap data structures, providing the initial
+ * heap region.
*
* Parameters:
+ * heap - The selected heap
* heapstart - Start of the initial heap region
* heapsize - Size of the initial heap region
*
@@ -89,7 +162,8 @@ FAR struct mm_freenode_s g_nodelist[MM_NNODES];
*
****************************************************************************/
-void mm_initialize(FAR void *heapstart, size_t heapsize)
+static inline void _mm_initialize(FAR struct mm_heap_s *heap,
+ FAR void *heapstart, size_t heapsize)
{
int i;
@@ -107,41 +181,46 @@ void mm_initialize(FAR void *heapstart, size_t heapsize)
/* Set up global variables */
- g_heapsize = 0;
+ heap->mm_heapsize = 0;
#if CONFIG_MM_REGIONS > 1
- g_nregions = 0;
+ heap->mm_nregions = 0;
#endif
/* Initialize the node array */
- memset(g_nodelist, 0, sizeof(struct mm_freenode_s) * MM_NNODES);
+ memset(heap->mm_nodelist, 0, sizeof(struct mm_freenode_s) * MM_NNODES);
for (i = 1; i < MM_NNODES; i++)
{
- g_nodelist[i-1].flink = &g_nodelist[i];
- g_nodelist[i].blink = &g_nodelist[i-1];
+ heap->mm_nodelist[i-1].flink = &heap->mm_nodelist[i];
+ heap->mm_nodelist[i].blink = &heap->mm_nodelist[i-1];
}
/* Initialize the malloc semaphore to one (to support one-at-
* a-time access to private data sets).
*/
- mm_seminitialize();
+ mm_seminitialize(heap);
/* Add the initial region of memory to the heap */
- mm_addregion(heapstart, heapsize);
+ _mm_addregion(heap, heapstart, heapsize);
}
/****************************************************************************
- * Name: mm_addregion
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mm_initialize
*
* Description:
- * This function gives a region of contiguous memory to the memory manager
+ * This this function is called during initialization to initialize the
+ * user heap.
*
* Parameters:
- * heapstart - Start of the heap region
- * heapsize - Size of the heap region
+ * heapstart - Start of the initial heap region
+ * heapsize - Size of the initial heap region
*
* Return Value:
* None
@@ -150,67 +229,37 @@ void mm_initialize(FAR void *heapstart, size_t heapsize)
*
****************************************************************************/
-void mm_addregion(FAR void *heapstart, size_t heapsize)
-{
- FAR struct mm_freenode_s *node;
- uintptr_t heapbase;
- uintptr_t heapend;
-#if CONFIG_MM_REGIONS > 1
- int IDX = g_nregions;
-#else
-# define IDX 0
-#endif
+#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
- /* If the MCU handles wide addresses but the memory manager is configured
- * for a small heap, then verify that the caller is not doing something
- * crazy.
- */
+void mm_initialize(FAR void *heapstart, size_t heapsize)
+{
+ _mm_initialize(&g_mmheap, heapstart, heapsize);
+}
-#if defined(CONFIG_MM_SMALL) && !defined(CONFIG_SMALL_MEMORY)
- DEBUGASSERT(heapsize <= MMSIZE_MAX+1);
#endif
- /* Adjust the provide heap start and size so that they are both aligned
- * with the MM_MIN_CHUNK size.
- */
-
- heapbase = MM_ALIGN_UP((uintptr_t)heapstart);
- heapend = MM_ALIGN_DOWN((uintptr_t)heapstart + (uintptr_t)heapsize);
- heapsize = heapend - heapbase;
-
- mlldbg("Region %d: base=%p size=%u\n", IDX+1, heapstart, heapsize);
-
- /* Add the size of this region to the total size of the heap */
-
- g_heapsize += heapsize;
-
- /* Create two "allocated" guard nodes at the beginning and end of
- * the heap. These only serve to keep us from allocating outside
- * of the heap.
- *
- * And create one free node between the guard nodes that contains
- * all available memory.
- */
-
- g_heapstart[IDX] = (FAR struct mm_allocnode_s *)heapbase;
- g_heapstart[IDX]->size = SIZEOF_MM_ALLOCNODE;
- g_heapstart[IDX]->preceding = MM_ALLOC_BIT;
-
- node = (FAR struct mm_freenode_s *)(heapbase + SIZEOF_MM_ALLOCNODE);
- node->size = heapsize - 2*SIZEOF_MM_ALLOCNODE;
- node->preceding = SIZEOF_MM_ALLOCNODE;
+/****************************************************************************
+ * Name: mm_addregion
+ *
+ * Description:
+ * This function adds a region of contiguous memory to the user heap.
+ *
+ * Parameters:
+ * heapstart - Start of the heap region
+ * heapsize - Size of the heap region
+ *
+ * Return Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
- g_heapend[IDX] = (FAR struct mm_allocnode_s *)(heapend - SIZEOF_MM_ALLOCNODE);
- g_heapend[IDX]->size = SIZEOF_MM_ALLOCNODE;
- g_heapend[IDX]->preceding = node->size | MM_ALLOC_BIT;
+#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
-#undef IDX
+void mm_addregion(FAR void *heapstart, size_t heapsize)
+{
+ _mm_addregion(&g_mmheap, heapstart, heapsize);
+}
-#if CONFIG_MM_REGIONS > 1
- g_nregions++;
#endif
-
- /* Add the single, large free node to the nodelist */
-
- mm_addfreechunk(node);
-}
diff --git a/nuttx/mm/mm_internal.h b/nuttx/mm/mm_internal.h
index 21cf253d7..9f1616978 100644
--- a/nuttx/mm/mm_internal.h
+++ b/nuttx/mm/mm_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
* mm/mm_internal.h
*
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -113,7 +113,7 @@
* Public Types
****************************************************************************/
-/* Determine the size of the chunk size/offset type */
+/* Determines the size of the chunk size/offset type */
#ifdef CONFIG_MM_SMALL
typedef uint16_t mmsize_t;
@@ -170,6 +170,39 @@ struct mm_freenode_s
#define CHECK_FREENODE_SIZE \
DEBUGASSERT(sizeof(struct mm_freenode_s) == SIZEOF_MM_FREENODE)
+/* This describes one heap (possibly with multiple regions) */
+
+struct mm_heap_s
+{
+ /* Mutually exclusive access to this data set is enforced with
+ * the following un-named semaphore.
+ */
+
+ sem_t mm_semaphore;
+ pid_t mm_holder;
+ int mm_counts_held;
+
+ /* This is the size of the heap provided to mm */
+
+ size_t mm_heapsize;
+
+ /* This is the first and last nodes of the heap */
+
+ FAR struct mm_allocnode_s *mm_heapstart[CONFIG_MM_REGIONS];
+ FAR struct mm_allocnode_s *mm_heapend[CONFIG_MM_REGIONS];
+
+#if CONFIG_MM_REGIONS > 1
+ int mm_nregions;
+#endif
+
+ /* All free nodes are maintained in a doubly linked list. This
+ * array provides some hooks into the list at various points to
+ * speed searches for free nodes.
+ */
+
+ struct mm_freenode_s mm_nodelist[MM_NNODES];
+};
+
/* Normally defined in stdlib.h */
#ifdef MM_TEST
@@ -187,57 +220,58 @@ struct mallinfo
#endif
/****************************************************************************
- * Global Variables
+ * Public Variables
****************************************************************************/
-/* This is the size of the heap provided to mm */
-
-extern size_t g_heapsize;
-
-/* This is the first and last nodes of the heap */
-
-extern FAR struct mm_allocnode_s *g_heapstart[CONFIG_MM_REGIONS];
-extern FAR struct mm_allocnode_s *g_heapend[CONFIG_MM_REGIONS];
-
-#if CONFIG_MM_REGIONS > 1
-extern int g_nregions;
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
#else
-# define g_nregions 1
+#define EXTERN extern
#endif
-/* All free nodes are maintained in a doubly linked list. This
- * array provides some hooks into the list at various points to
- * speed searches for free nodes.
- */
+#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
+/* This is the user heap */
+
+EXTERN struct mm_heap_s g_mmheap;
-extern FAR struct mm_freenode_s g_nodelist[MM_NNODES];
+#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef MM_TEST
-FAR void *mm_malloc(size_t);
-void mm_free(void*);
-FAR void *mm_realloc(void*, size_t);
-FAR void *mm_memalign(size_t, size_t);
-FAR void *mm_zalloc(size_t);
-FAR void *mm_calloc(size_t, size_t);
+FAR void *mm_malloc(size_t);
+void mm_free(void*);
+FAR void *mm_realloc(void*, size_t);
+FAR void *mm_memalign(size_t, size_t);
+FAR void *mm_zalloc(size_t);
+FAR void *mm_calloc(size_t, size_t);
#ifdef CONFIG_CAN_PASS_STRUCTS
struct mallinfo mallinfo(void);
#else
-int mallinfo(struct mallinfo *info);
+int mallinfo(struct mallinfo *info);
#endif
#endif
-void mm_shrinkchunk(FAR struct mm_allocnode_s *node, size_t size);
-void mm_addfreechunk(FAR struct mm_freenode_s *node);
-int mm_size2ndx(size_t size);
-void mm_seminitialize(void);
-void mm_takesemaphore(void);
-void mm_givesemaphore(void);
+void mm_shrinkchunk(FAR struct mm_heap_s *heap,
+ FAR struct mm_allocnode_s *node, size_t size);
+void mm_addfreechunk(FAR struct mm_heap_s *heap,
+ FAR struct mm_freenode_s *node);
+int mm_size2ndx(size_t size);
+void mm_seminitialize(FAR struct mm_heap_s *heap);
+void mm_takesemaphore(FAR struct mm_heap_s *heap);
+void mm_givesemaphore(FAR struct mm_heap_s *heap);
#ifdef MM_TEST
-int mm_getsemaphore(void);
+int mm_getsemaphore(FAR struct mm_heap_s *heap);
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
#endif
#endif /* __MM_MM_INTERNAL_H */
diff --git a/nuttx/mm/mm_mallinfo.c b/nuttx/mm/mm_mallinfo.c
index 30c1028fd..37432a157 100644
--- a/nuttx/mm/mm_mallinfo.c
+++ b/nuttx/mm/mm_mallinfo.c
@@ -1,7 +1,7 @@
/****************************************************************************
* mm/mm_mallinfo.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -55,22 +55,15 @@
****************************************************************************/
/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: mallinfo
+ * Name: _mm_mallinfo
*
* Description:
- * mallinfo returns a copy of updated current mallinfo.
+ * mallinfo returns a copy of updated current heap information.
*
****************************************************************************/
-#ifdef CONFIG_CAN_PASS_STRUCTS
-struct mallinfo mallinfo(void)
-#else
-int mallinfo(struct mallinfo *info)
-#endif
+static inline int _mm_mallinfo(FAR struct mm_heap_s *heap,
+ FAR struct mallinfo *info)
{
struct mm_allocnode_s *node;
size_t mxordblk = 0;
@@ -83,29 +76,22 @@ int mallinfo(struct mallinfo *info)
# define region 0
#endif
-#ifdef CONFIG_CAN_PASS_STRUCTS
- static struct mallinfo info;
-#else
- if (!info)
- {
- return ERROR;
- }
-#endif
+ DEBUGASSERT(info);
/* Visit each region */
#if CONFIG_MM_REGIONS > 1
- for (region = 0; region < g_nregions; region++)
+ for (region = 0; region < heap->mm_nregions; region++)
#endif
{
/* Visit each node in the region
* Retake the semaphore for each region to reduce latencies
*/
- mm_takesemaphore();
+ mm_takesemaphore(heap);
- for (node = g_heapstart[region];
- node < g_heapend[region];
+ for (node = heap->mm_heapstart[region];
+ node < heap->mm_heapend[region];
node = (struct mm_allocnode_s *)((char*)node + node->size))
{
mvdbg("region=%d node=%p size=%p preceding=%p\n", region, node, node->size, node->preceding);
@@ -124,29 +110,54 @@ int mallinfo(struct mallinfo *info)
}
}
- mm_givesemaphore();
+ mm_givesemaphore(heap);
- mvdbg("region=%d node=%p g_heapend=%p\n", region, node, g_heapend[region]);
- DEBUGASSERT(node == g_heapend[region]);
+ mvdbg("region=%d node=%p heapend=%p\n", region, node, heap->mm_heapend[region]);
+ DEBUGASSERT(node == heap->mm_heapend[region]);
uordblks += SIZEOF_MM_ALLOCNODE; /* account for the tail node */
}
#undef region
- DEBUGASSERT(uordblks + fordblks == g_heapsize);
+ DEBUGASSERT(uordblks + fordblks == heap->mm_heapsize);
-#ifdef CONFIG_CAN_PASS_STRUCTS
- info.arena = g_heapsize;
- info.ordblks = ordblks;
- info.mxordblk = mxordblk;
- info.uordblks = uordblks;
- info.fordblks = fordblks;
- return info;
-#else
- info->arena = g_heapsize;
+ info->arena = heap->mm_heapsize;
info->ordblks = ordblks;
info->mxordblk = mxordblk;
info->uordblks = uordblks;
info->fordblks = fordblks;
return OK;
-#endif
}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: kmallinfo and mallinfo
+ *
+ * Description:
+ * mallinfo returns a copy of updated current heap information for either
+ * the user heap (mallinfo) or the kernel heap (kmallinfo).
+ *
+ ****************************************************************************/
+
+#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
+# ifdef CONFIG_CAN_PASS_STRUCTS
+
+struct mallinfo mallinfo(void)
+{
+ struct mallinfo info;
+
+ _mm_mallinfo(&g_mmheap, &info);
+ return info;
+}
+
+# else
+
+int mallinfo(struct mallinfo *info)
+{
+ return _mm_mallinfo(&g_mmheap, info);
+}
+
+#endif
+#endif /* !CONFIG_NUTTX_KERNEL || !__KERNEL__ */
diff --git a/nuttx/mm/mm_malloc.c b/nuttx/mm/mm_malloc.c
index 4f138957f..331f8eefd 100644
--- a/nuttx/mm/mm_malloc.c
+++ b/nuttx/mm/mm_malloc.c
@@ -71,11 +71,7 @@
****************************************************************************/
/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: malloc
+ * Name: _mm_malloc
*
* Description:
* Find the smallest chunk that satisfies the request. Take the memory from
@@ -85,7 +81,7 @@
*
****************************************************************************/
-FAR void *malloc(size_t size)
+static inline FAR void *_mm_malloc(FAR struct mm_heap_s *heap, size_t size)
{
FAR struct mm_freenode_s *node;
void *ret = NULL;
@@ -106,7 +102,7 @@ FAR void *malloc(size_t size)
/* We need to hold the MM semaphore while we muck with the nodelist. */
- mm_takesemaphore();
+ mm_takesemaphore(heap);
/* Get the location in the node list to start the search. Special case
* really big allocations
@@ -125,10 +121,10 @@ FAR void *malloc(size_t size)
/* Search for a large enough chunk in the list of nodes. This list is
* ordered by size, but will have occasional zero sized nodes as we visit
- * other g_nodelist[] entries.
+ * other mm_nodelist[] entries.
*/
- for (node = g_nodelist[ndx].flink;
+ for (node = heap->mm_nodelist[ndx].flink;
node && node->size < size;
node = node->flink);
@@ -186,7 +182,7 @@ FAR void *malloc(size_t size)
/* Add the remainder back into the nodelist */
- mm_addfreechunk(remainder);
+ mm_addfreechunk(heap, remainder);
}
/* Handle the case of an exact size match */
@@ -195,7 +191,7 @@ FAR void *malloc(size_t size)
ret = (void*)((char*)node + SIZEOF_MM_ALLOCNODE);
}
- mm_givesemaphore();
+ mm_givesemaphore(heap);
/* If CONFIG_DEBUG_MM is defined, then output the result of the allocation
* to the SYSLOG.
@@ -214,3 +210,26 @@ FAR void *malloc(size_t size)
return ret;
}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: malloc
+ *
+ * Description:
+ * Find the smallest chunk that satisfies the request. Take the memory from
+ * that chunk, save the remaining, smaller chunk (if any).
+ *
+ * 8-byte alignment of the allocated data is assured.
+ *
+ ****************************************************************************/
+
+#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
+FAR void *malloc(size_t size)
+{
+ return _mm_malloc(&g_mmheap, size);
+}
+#endif
+
diff --git a/nuttx/mm/mm_memalign.c b/nuttx/mm/mm_memalign.c
index 87547c96b..d06964534 100644
--- a/nuttx/mm/mm_memalign.c
+++ b/nuttx/mm/mm_memalign.c
@@ -1,7 +1,7 @@
/****************************************************************************
* mm/mm_memalign.c
*
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -47,11 +47,11 @@
****************************************************************************/
/****************************************************************************
- * Global Functions
+ * Private Functions
****************************************************************************/
/****************************************************************************
- * Name: memalign
+ * Name: _mm_memalign
*
* Description:
* memalign requests more than enough space from malloc, finds a region
@@ -63,7 +63,8 @@
*
****************************************************************************/
-FAR void *memalign(size_t alignment, size_t size)
+static inline FAR void *_mm_memalign(FAR struct mm_heap_s *heap,
+ size_t alignment, size_t size)
{
FAR struct mm_allocnode_s *node;
size_t rawchunk;
@@ -107,7 +108,7 @@ FAR void *memalign(size_t alignment, size_t size)
* nodelist.
*/
- mm_takesemaphore();
+ mm_takesemaphore(heap);
/* Get the node associated with the allocation and the next node after
* the allocation.
@@ -182,7 +183,7 @@ FAR void *memalign(size_t alignment, size_t size)
/* Add the original, newly freed node to the free nodelist */
- mm_addfreechunk((FAR struct mm_freenode_s *)node);
+ mm_addfreechunk(heap, (FAR struct mm_freenode_s *)node);
/* Replace the original node with the newlay realloaced,
* aligned node
@@ -200,9 +201,35 @@ FAR void *memalign(size_t alignment, size_t size)
* malloc-compatible sizes that we have.
*/
- mm_shrinkchunk(node, size + SIZEOF_MM_ALLOCNODE);
+ mm_shrinkchunk(heap, node, size + SIZEOF_MM_ALLOCNODE);
}
- mm_givesemaphore();
+ mm_givesemaphore(heap);
return (FAR void*)alignedchunk;
}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: _mm_memalign
+ *
+ * Description:
+ * memalign requests more than enough space from malloc, finds a region
+ * within that chunk that meets the alignment request and then frees any
+ * leading or trailing space.
+ *
+ * The alignment argument must be a power of two (not checked). 8-byte
+ * alignment is guaranteed by normal malloc calls.
+ *
+ ****************************************************************************/
+
+#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
+
+FAR void *memalign(size_t alignment, size_t size)
+{
+ return _mm_memalign(&g_mmheap, alignment, size);
+}
+
+#endif
diff --git a/nuttx/mm/mm_realloc.c b/nuttx/mm/mm_realloc.c
index b44938995..5364a97a8 100644
--- a/nuttx/mm/mm_realloc.c
+++ b/nuttx/mm/mm_realloc.c
@@ -1,7 +1,7 @@
/****************************************************************************
* mm/mm_realloc.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -47,11 +47,11 @@
****************************************************************************/
/****************************************************************************
- * Global Functions
+ * Private Functions
****************************************************************************/
/****************************************************************************
- * Name: realloc
+ * Name: _mm_realloc
*
* Description:
* If the reallocation is for less space, then:
@@ -73,7 +73,8 @@
*
****************************************************************************/
-FAR void *realloc(FAR void *oldmem, size_t size)
+static inline FAR void *_mm_realloc(FAR struct mm_heap_s *heap,
+ FAR void *oldmem, size_t size)
{
FAR struct mm_allocnode_s *oldnode;
FAR struct mm_freenode_s *prev;
@@ -110,7 +111,7 @@ FAR void *realloc(FAR void *oldmem, size_t size)
/* We need to hold the MM semaphore while we muck with the nodelist. */
- mm_takesemaphore();
+ mm_takesemaphore(heap);
/* Check if this is a request to reduce the size of the allocation. */
@@ -123,12 +124,12 @@ FAR void *realloc(FAR void *oldmem, size_t size)
if (size < oldsize)
{
- mm_shrinkchunk(oldnode, size);
+ mm_shrinkchunk(heap, oldnode, size);
}
/* Then return the original address */
- mm_givesemaphore();
+ mm_givesemaphore(heap);
return oldmem;
}
@@ -248,7 +249,7 @@ FAR void *realloc(FAR void *oldmem, size_t size)
/* Return the previous free node to the nodelist (with the new size) */
- mm_addfreechunk(prev);
+ mm_addfreechunk(heap, prev);
/* Now we want to return newnode */
@@ -317,7 +318,7 @@ FAR void *realloc(FAR void *oldmem, size_t size)
/* Add the new free node to the nodelist (with the new size) */
- mm_addfreechunk(newnode);
+ mm_addfreechunk(heap, newnode);
}
else
{
@@ -327,7 +328,7 @@ FAR void *realloc(FAR void *oldmem, size_t size)
}
}
- mm_givesemaphore();
+ mm_givesemaphore(heap);
return newmem;
}
@@ -339,7 +340,7 @@ FAR void *realloc(FAR void *oldmem, size_t size)
* leave the original memory in place.
*/
- mm_givesemaphore();
+ mm_givesemaphore(heap);
newmem = (FAR void*)malloc(size);
if (newmem)
{
@@ -350,3 +351,40 @@ FAR void *realloc(FAR void *oldmem, size_t size)
return newmem;
}
}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: realloc
+ *
+ * Description:
+ * If the reallocation is for less space, then:
+ *
+ * (1) the current allocation is reduced in size
+ * (2) the remainder at the end of the allocation is returned to the
+ * free list.
+ *
+ * If the request is for more space and the current allocation can be
+ * extended, it will be extended by:
+ *
+ * (1) Taking the additional space from the following free chunk, or
+ * (2) Taking the additional space from the preceding free chunk.
+ * (3) Or both
+ *
+ * If the request is for more space but the current chunk cannot be
+ * extended, then malloc a new buffer, copy the data into the new buffer,
+ * and free the old buffer.
+ *
+ ****************************************************************************/
+
+#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
+
+FAR void *realloc(FAR void *oldmem, size_t size)
+{
+ return _mm_realloc(&g_mmheap, oldmem, size);
+}
+
+#endif
+
diff --git a/nuttx/mm/mm_sem.c b/nuttx/mm/mm_sem.c
index 19fff780b..61e4fc2f0 100644
--- a/nuttx/mm/mm_sem.c
+++ b/nuttx/mm/mm_sem.c
@@ -1,7 +1,7 @@
/****************************************************************************
* mm/mm_sem.c
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,6 @@
#include "mm_environment.h"
#include <unistd.h>
-#include <semaphore.h>
#include <errno.h>
#include <assert.h>
@@ -72,13 +71,6 @@
* Private Data
****************************************************************************/
-/* Mutually exclusive access to this data set is enforced with
- * the following (un-named) semaphore. */
-
-static sem_t g_mm_semaphore;
-static pid_t g_holder;
-static int g_counts_held;
-
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -91,16 +83,16 @@ static int g_counts_held;
*
****************************************************************************/
-void mm_seminitialize(void)
+void mm_seminitialize(FAR struct mm_heap_s *heap)
{
/* Initialize the MM semaphore to one (to support one-at-a-time access to
* private data sets.
*/
- (void)sem_init(&g_mm_semaphore, 0, 1);
+ (void)sem_init(&heap->mm_semaphore, 0, 1);
- g_holder = -1;
- g_counts_held = 0;
+ heap->mm_holder = -1;
+ heap->mm_counts_held = 0;
}
/****************************************************************************
@@ -115,32 +107,32 @@ void mm_seminitialize(void)
****************************************************************************/
#ifndef MM_TEST
-int mm_trysemaphore(void)
+int mm_trysemaphore(FAR struct mm_heap_s *heap)
{
pid_t my_pid = getpid();
/* Do I already have the semaphore? */
- if (g_holder == my_pid)
+ if (heap->mm_holder == my_pid)
{
/* Yes, just increment the number of references that I have */
- g_counts_held++;
+ heap->mm_counts_held++;
return OK;
}
else
{
/* Try to take the semaphore (perhaps waiting) */
- if (sem_trywait(&g_mm_semaphore) != 0)
+ if (sem_trywait(&heap->mm_semaphore) != 0)
{
return ERROR;
}
/* We have it. Claim the stak and return */
- g_holder = my_pid;
- g_counts_held = 1;
+ heap->mm_holder = my_pid;
+ heap->mm_counts_held = 1;
return OK;
}
}
@@ -155,24 +147,24 @@ int mm_trysemaphore(void)
*
****************************************************************************/
-void mm_takesemaphore(void)
+void mm_takesemaphore(FAR struct mm_heap_s *heap)
{
pid_t my_pid = getpid();
/* Do I already have the semaphore? */
- if (g_holder == my_pid)
+ if (heap->mm_holder == my_pid)
{
/* Yes, just increment the number of references that I have */
- g_counts_held++;
+ heap->mm_counts_held++;
}
else
{
/* Take the semaphore (perhaps waiting) */
msemdbg("PID=%d taking\n", my_pid);
- while (sem_wait(&g_mm_semaphore) != 0)
+ while (sem_wait(&heap->mm_semaphore) != 0)
{
/* The only case that an error should occur here is if
* the wait was awakened by a signal.
@@ -183,11 +175,11 @@ void mm_takesemaphore(void)
/* We have it. Claim the stake and return */
- g_holder = my_pid;
- g_counts_held = 1;
+ heap->mm_holder = my_pid;
+ heap->mm_counts_held = 1;
}
- msemdbg("Holder=%d count=%d\n", g_holder, g_counts_held);
+ msemdbg("Holder=%d count=%d\n", heap->mm_holder, heap->mm_counts_held);
}
/****************************************************************************
@@ -198,7 +190,7 @@ void mm_takesemaphore(void)
*
****************************************************************************/
-void mm_givesemaphore(void)
+void mm_givesemaphore(FAR struct mm_heap_s *heap)
{
#ifdef CONFIG_DEBUG
pid_t my_pid = getpid();
@@ -206,25 +198,25 @@ void mm_givesemaphore(void)
/* I better be holding at least one reference to the semaphore */
- DEBUGASSERT(g_holder == my_pid);
+ DEBUGASSERT(heap->mm_holder == my_pid);
/* Do I hold multiple references to the semphore */
- if (g_counts_held > 1)
+ if (heap->mm_counts_held > 1)
{
/* Yes, just release one count and return */
- g_counts_held--;
- msemdbg("Holder=%d count=%d\n", g_holder, g_counts_held);
+ heap->mm_counts_held--;
+ msemdbg("Holder=%d count=%d\n", heap->mm_holder, heap->mm_counts_held);
}
else
{
/* Nope, this is the last reference I have */
msemdbg("PID=%d giving\n", my_pid);
- g_holder = -1;
- g_counts_held = 0;
- ASSERT(sem_post(&g_mm_semaphore) == 0);
+ heap->mm_holder = -1;
+ heap->mm_counts_held = 0;
+ ASSERT(sem_post(&heap->mm_semaphore) == 0);
}
}
@@ -237,10 +229,10 @@ void mm_givesemaphore(void)
****************************************************************************/
#ifdef MM_TEST
-int mm_getsemaphore(void)
+int mm_getsemaphore(FAR struct mm_heap_s *heap)
{
int sval;
- sem_getvalue(&g_mm_semaphore, &sval);
+ sem_getvalue(&heap->mm_semaphore, &sval);
return sval;
}
#endif
diff --git a/nuttx/mm/mm_shrinkchunk.c b/nuttx/mm/mm_shrinkchunk.c
index e538e43ed..c20aaf0fb 100644
--- a/nuttx/mm/mm_shrinkchunk.c
+++ b/nuttx/mm/mm_shrinkchunk.c
@@ -1,7 +1,7 @@
/****************************************************************************
* mm/mm_shrinkchunk.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 1013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -63,7 +63,8 @@
*
****************************************************************************/
-void mm_shrinkchunk(FAR struct mm_allocnode_s *node, size_t size)
+void mm_shrinkchunk(FAR struct mm_heap_s *heap,
+ FAR struct mm_allocnode_s *node, size_t size)
{
FAR struct mm_freenode_s *next;
@@ -108,7 +109,7 @@ void mm_shrinkchunk(FAR struct mm_allocnode_s *node, size_t size)
/* Add the new node to the freenodelist */
- mm_addfreechunk(newnode);
+ mm_addfreechunk(heap, newnode);
}
/* The next chunk is allocated. Try to free the end portion at the end
@@ -134,6 +135,6 @@ void mm_shrinkchunk(FAR struct mm_allocnode_s *node, size_t size)
/* Add the new node to the freenodelist */
- mm_addfreechunk(newnode);
+ mm_addfreechunk(heap, newnode);
}
}
diff --git a/nuttx/mm/mm_test.c b/nuttx/mm/mm_test.c
index b25a24095..483fd165c 100644
--- a/nuttx/mm/mm_test.c
+++ b/nuttx/mm/mm_test.c
@@ -1,7 +1,7 @@
/************************************************************************
* mm/mm_test.c
*
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <semaphore.h>
/************************************************************************
* Pre-processor Definitions
@@ -133,7 +134,7 @@ static int mm_findinfreelist(struct mm_freenode_s *node)
{
struct mm_freenode_s *list;
- for(list = &g_nodelist[0];
+ for(list = &g_mmheap.mm_nodelist[0];
list;
list = list->flink)
{
@@ -165,13 +166,13 @@ static void mm_showchunkinfo(void)
/* Visit each region */
#if CONFIG_MM_REGIONS > 1
- for (region = 0; region < g_nregions; region++)
+ for (region = 0; region < g_mmheap.mm_nregions; region++)
#endif
{
/* Visit each node in each region */
- for (node = g_heapstart[region];
- node < g_heapend[region];
+ for (node = g_mmheap.mm_heapstart[region];
+ node < g_mmheap.mm_heapend[region];
node = (struct mm_allocnode_s *)((char*)node + node->size))
{
printf(" %p 0x%08x 0x%08x %s",
@@ -206,7 +207,7 @@ static void mm_showfreelist(void)
int i = 0;
printf(" FREE NODE LIST:\n");
- for(prev = NULL, node = &g_nodelist[0];
+ for(prev = NULL, node = &g_mmheap.mm_nodelist[0];
node;
prev = node, node = node->flink)
{
@@ -258,7 +259,7 @@ static void mm_showmallinfo(void)
printf(" Total non-inuse space = %ld\n",
alloc_info.fordblks);
- sval = mm_getsemaphore();
+ sval = mm_getsemaphore(&g_mmheap);
if (sval != 1)
{
fprintf(stderr, "After mallinfo, semaphore count=%d, should be 1\n", sval);
@@ -322,7 +323,7 @@ static void do_mallocs(void **mem, const int *size, const int *rand,
memset(mem[j], 0xAA, size[j]);
}
- sval = mm_getsemaphore();
+ sval = mm_getsemaphore(&g_mmheap);
if (sval != 1)
{
fprintf(stderr, " After malloc semaphore count=%d, should be 1\n", sval);
@@ -371,7 +372,7 @@ static void do_reallocs(void **mem, const int *oldsize,
memset(mem[j], 0x55, newsize[j]);
}
- sval = mm_getsemaphore();
+ sval = mm_getsemaphore(&g_mmheap);
if (sval != 1)
{
fprintf(stderr, " After realloc semaphore count=%d, should be 1\n", sval);
@@ -419,7 +420,7 @@ static void do_memaligns(void **mem, const int *size, const int *align,
memset(mem[j], 0x33, size[j]);
}
- sval = mm_getsemaphore();
+ sval = mm_getsemaphore(&g_mmheap);
if (sval != 1)
{
fprintf(stderr, " After memalign semaphore count=%d, should be 1\n", sval);
@@ -448,7 +449,7 @@ static void do_frees(void **mem, const int *size, const int *rand, int n)
mm_free(mem[j]);
mem[j] = NULL;
- sval = mm_getsemaphore();
+ sval = mm_getsemaphore(&g_mmheap);
if (sval != 1)
{
fprintf(stderr, " After free semaphore count=%d, should be 1\n", sval);