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
This commit is contained in:
patacongo 2013-03-08 18:29:56 +00:00
parent 8a774a1712
commit 45ce321f51
18 changed files with 576 additions and 314 deletions

View File

@ -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.

67
TODO
View File

@ -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

View File

@ -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 */

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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,98 +48,25 @@
* 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 */
FAR struct mm_allocnode_s *g_heapstart[CONFIG_MM_REGIONS];
FAR struct mm_allocnode_s *g_heapend[CONFIG_MM_REGIONS];
#if CONFIG_MM_REGIONS > 1
int g_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.
*/
FAR struct mm_freenode_s g_nodelist[MM_NNODES];
/****************************************************************************
* Public Functions
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mm_initialize
* Name: _mm_addregion
*
* Description:
* This is an internal OS function called only at power-up boot time.
*
* Parameters:
* heapstart - Start of the initial heap region
* heapsize - Size of the initial heap region
*
* Return Value:
* None
*
* Assumptions:
*
****************************************************************************/
void mm_initialize(FAR void *heapstart, size_t heapsize)
{
int i;
mlldbg("Heap: start=%p size=%u\n", heapstart, heapsize);
/* The following two lines have cause problems for some older ZiLog
* compilers in the past (but not the more recent). Life is easier if we
* just the suppress them altogther for those tools.
*/
#ifndef __ZILOG__
CHECK_ALLOCNODE_SIZE;
CHECK_FREENODE_SIZE;
#endif
/* Set up global variables */
g_heapsize = 0;
#if CONFIG_MM_REGIONS > 1
g_nregions = 0;
#endif
/* Initialize the node array */
memset(g_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];
}
/* Initialize the malloc semaphore to one (to support one-at-
* a-time access to private data sets).
*/
mm_seminitialize();
/* Add the initial region of memory to the heap */
mm_addregion(heapstart, heapsize);
}
/****************************************************************************
* Name: mm_addregion
*
* Description:
* This function gives a region of contiguous memory to the memory manager
* 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
*
@ -150,13 +77,14 @@ void mm_initialize(FAR void *heapstart, size_t heapsize)
*
****************************************************************************/
void mm_addregion(FAR void *heapstart, size_t heapsize)
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 IDX = g_nregions;
int IDX = heap->mm_nregions;
#else
# define IDX 0
#endif
@ -182,7 +110,7 @@ void mm_addregion(FAR void *heapstart, size_t heapsize)
/* Add the size of this region to the total size of the heap */
g_heapsize += heapsize;
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
@ -192,25 +120,146 @@ void mm_addregion(FAR void *heapstart, size_t heapsize)
* 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;
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;
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;
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
g_nregions++;
heap->mm_nregions++;
#endif
/* Add the single, large free node to the nodelist */
mm_addfreechunk(node);
mm_addfreechunk(heap, node);
}
/****************************************************************************
* Name: _mm_initialize
*
* Description:
* 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
*
* Return Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void _mm_initialize(FAR struct mm_heap_s *heap,
FAR void *heapstart, size_t heapsize)
{
int i;
mlldbg("Heap: start=%p size=%u\n", heapstart, heapsize);
/* The following two lines have cause problems for some older ZiLog
* compilers in the past (but not the more recent). Life is easier if we
* just the suppress them altogther for those tools.
*/
#ifndef __ZILOG__
CHECK_ALLOCNODE_SIZE;
CHECK_FREENODE_SIZE;
#endif
/* Set up global variables */
heap->mm_heapsize = 0;
#if CONFIG_MM_REGIONS > 1
heap->mm_nregions = 0;
#endif
/* Initialize the node array */
memset(heap->mm_nodelist, 0, sizeof(struct mm_freenode_s) * MM_NNODES);
for (i = 1; i < MM_NNODES; i++)
{
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(heap);
/* Add the initial region of memory to the heap */
_mm_addregion(heap, heapstart, heapsize);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mm_initialize
*
* Description:
* This this function is called during initialization to initialize the
* user heap.
*
* Parameters:
* heapstart - Start of the initial heap region
* heapsize - Size of the initial heap region
*
* Return Value:
* None
*
* Assumptions:
*
****************************************************************************/
#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
void mm_initialize(FAR void *heapstart, size_t heapsize)
{
_mm_initialize(&g_mmheap, heapstart, heapsize);
}
#endif
/****************************************************************************
* 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:
*
****************************************************************************/
#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
void mm_addregion(FAR void *heapstart, size_t heapsize)
{
_mm_addregion(&g_mmheap, heapstart, heapsize);
}
#endif

View File

@ -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 FAR struct mm_freenode_s g_nodelist[MM_NNODES];
EXTERN struct mm_heap_s g_mmheap;
#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 */

View File

@ -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__ */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);