forked from nuttx/nuttx-update
Add support for multiple heaps
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5720 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
45ce321f51
commit
017e07d35d
21 changed files with 438 additions and 1140 deletions
|
@ -4272,7 +4272,7 @@
|
|||
was closed by the remote peer). That excludes the listen socket which
|
||||
was never connected. This does introduce a new problem, however. If
|
||||
the socket was not closed, but lost the connection through an abnormal
|
||||
event, then poll/select will hang. That needs to be revisited.\
|
||||
event, then poll/select will hang. That needs to be revisited.
|
||||
(2013-03-07)
|
||||
* fs/fs_selected.c: Was not checking if the timeout parameter was NULL
|
||||
but would, instead, setup a bogus timeout based on whatever it found at
|
||||
|
@ -4284,4 +4284,6 @@
|
|||
* 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.
|
||||
|
||||
(2013-03-07).
|
||||
* mm/ and include/nuttx/mm.h: Implement support for multiple heaps.
|
||||
(2013-03-07).
|
||||
|
|
|
@ -77,9 +77,6 @@ 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(&g_mmheap)
|
||||
|
@ -94,7 +91,7 @@ extern struct mm_heap_s g_mmheap;
|
|||
|
||||
void kmm_initialize(FAR void *heap_start, size_t heap_size);
|
||||
void kmm_addregion(FAR void *heapstart, size_t heapsize);
|
||||
int kmm_trysemaphore(void);
|
||||
int kmm_trysemaphore(void);
|
||||
void kmm_givesemaphore(void);
|
||||
|
||||
FAR void *kmalloc(size_t);
|
||||
|
|
|
@ -41,25 +41,178 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-Processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* If the MCU has a small (16-bit) address capability, then we will use
|
||||
* a smaller chunk header that contains 16-bit size/offset information.
|
||||
* We will also use the smaller header on MCUs with wider addresses if
|
||||
* CONFIG_MM_SMALL is selected. This configuration is common with MCUs
|
||||
* that have a large FLASH space, but only a tiny internal SRAM.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMALL_MEMORY
|
||||
/* If the MCU has a small addressing capability, then for the smaller
|
||||
* chunk header.
|
||||
*/
|
||||
|
||||
# undef CONFIG_MM_SMALL
|
||||
# define CONFIG_MM_SMALL 1
|
||||
#endif
|
||||
|
||||
/* Chunk Header Definitions *************************************************/
|
||||
/* These definitions define the characteristics of allocator
|
||||
*
|
||||
* MM_MIN_SHIFT is used to define MM_MIN_CHUNK.
|
||||
* MM_MIN_CHUNK - is the smallest physical chunk that can
|
||||
* be allocated. It must be at least a large as
|
||||
* sizeof(struct mm_freenode_s). Larger values may
|
||||
* improve performance slightly, but will waste memory
|
||||
* due to quantization losses.
|
||||
*
|
||||
* MM_MAX_SHIFT is used to define MM_MAX_CHUNK
|
||||
* MM_MAX_CHUNK is the largest, contiguous chunk of memory
|
||||
* that can be allocated. It can range from 16-bytes to
|
||||
* 4Gb. Larger values of MM_MAX_SHIFT can cause larger
|
||||
* data structure sizes and, perhaps, minor performance
|
||||
* losses.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# define MM_MIN_SHIFT 4 /* 16 bytes */
|
||||
# define MM_MAX_SHIFT 15 /* 32 Kb */
|
||||
#else
|
||||
# define MM_MIN_SHIFT 4 /* 16 bytes */
|
||||
# define MM_MAX_SHIFT 22 /* 4 Mb */
|
||||
#endif
|
||||
|
||||
/* All other definitions derive from these two */
|
||||
|
||||
#define MM_MIN_CHUNK (1 << MM_MIN_SHIFT)
|
||||
#define MM_MAX_CHUNK (1 << MM_MAX_SHIFT)
|
||||
#define MM_NNODES (MM_MAX_SHIFT - MM_MIN_SHIFT + 1)
|
||||
|
||||
#define MM_GRAN_MASK (MM_MIN_CHUNK-1)
|
||||
#define MM_ALIGN_UP(a) (((a) + MM_GRAN_MASK) & ~MM_GRAN_MASK)
|
||||
#define MM_ALIGN_DOWN(a) ((a) & ~MM_GRAN_MASK)
|
||||
|
||||
/* An allocated chunk is distinguished from a free chunk by bit 31 (or 15)
|
||||
* of the 'preceding' chunk size. If set, then this is an allocated chunk.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# define MM_ALLOC_BIT 0x8000
|
||||
#else
|
||||
# define MM_ALLOC_BIT 0x80000000
|
||||
#endif
|
||||
#define MM_IS_ALLOCATED(n) \
|
||||
((int)((struct mm_allocnode_s*)(n)->preceding) < 0))
|
||||
|
||||
/****************************************************************************
|
||||
* Global Data
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Determines the size of the chunk size/offset type */
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
typedef uint16_t mmsize_t;
|
||||
# define MMSIZE_MAX 0xffff
|
||||
#else
|
||||
typedef size_t mmsize_t;
|
||||
# define MMSIZE_MAX SIZE_MAX
|
||||
#endif
|
||||
|
||||
/* This describes an allocated chunk. An allocated chunk is
|
||||
* distinguished from a free chunk by bit 15/31 of the 'preceding' chunk
|
||||
* size. If set, then this is an allocated chunk.
|
||||
*/
|
||||
|
||||
struct mm_allocnode_s
|
||||
{
|
||||
mmsize_t size; /* Size of this chunk */
|
||||
mmsize_t preceding; /* Size of the preceding chunk */
|
||||
};
|
||||
|
||||
/* What is the size of the allocnode? */
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# define SIZEOF_MM_ALLOCNODE 4
|
||||
#else
|
||||
# define SIZEOF_MM_ALLOCNODE 8
|
||||
#endif
|
||||
|
||||
#define CHECK_ALLOCNODE_SIZE \
|
||||
DEBUGASSERT(sizeof(struct mm_allocnode_s) == SIZEOF_MM_ALLOCNODE)
|
||||
|
||||
/* This describes a free chunk */
|
||||
|
||||
struct mm_freenode_s
|
||||
{
|
||||
mmsize_t size; /* Size of this chunk */
|
||||
mmsize_t preceding; /* Size of the preceding chunk */
|
||||
FAR struct mm_freenode_s *flink; /* Supports a doubly linked list */
|
||||
FAR struct mm_freenode_s *blink;
|
||||
};
|
||||
|
||||
/* What is the size of the freenode? */
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# ifdef CONFIG_SMALL_MEMORY
|
||||
# define SIZEOF_MM_FREENODE 8
|
||||
# else
|
||||
# define SIZEOF_MM_FREENODE 12
|
||||
# endif
|
||||
#else
|
||||
# define SIZEOF_MM_FREENODE 16
|
||||
#endif
|
||||
|
||||
#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];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Global Function Prototypes
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Global Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
|
@ -67,6 +220,17 @@ extern "C"
|
|||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
|
||||
/* This is the user heap */
|
||||
|
||||
EXTERN struct mm_heap_s g_mmheap;
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Functions contained in mm_initialize.c ***********************************/
|
||||
|
||||
void mm_initialize(FAR void *heap_start, size_t heap_size);
|
||||
|
@ -74,10 +238,69 @@ void mm_addregion(FAR void *heapstart, size_t heapsize);
|
|||
|
||||
/* Functions contained in mm_sem.c ******************************************/
|
||||
|
||||
struct mm_heap_s;
|
||||
int mm_trysemaphore(FAR struct mm_heap_s *heap);
|
||||
void mm_seminitialize(FAR struct mm_heap_s *heap);
|
||||
void mm_takesemaphore(FAR struct mm_heap_s *heap);
|
||||
int mm_trysemaphore(FAR struct mm_heap_s *heap);
|
||||
void mm_givesemaphore(FAR struct mm_heap_s *heap);
|
||||
|
||||
/* Functions contained in mm_malloc.c ***************************************/
|
||||
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size);
|
||||
#endif
|
||||
|
||||
/* Functions contained in mm_free.c *****************************************/
|
||||
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
void mm_free(FAR struct mm_heap_s *heap, FAR void *mem);
|
||||
#endif
|
||||
|
||||
/* Functions contained in mm_realloc.c **************************************/
|
||||
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
|
||||
size_t size);
|
||||
#endif
|
||||
|
||||
/* Functions contained in mm_calloc.c ***************************************/
|
||||
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
FAR void *mm_calloc(FAR struct mm_heap_s *heap, size_t n, size_t elem_size);
|
||||
#endif
|
||||
|
||||
/* Functions contained in mm_zalloc.c ***************************************/
|
||||
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
FAR void *mm_zalloc(FAR struct mm_heap_s *heap, size_t size);
|
||||
#endif
|
||||
|
||||
/* Functions contained in mm_memalign.c *************************************/
|
||||
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
|
||||
size_t size);
|
||||
#endif
|
||||
|
||||
/* Functions contained in mm_mallinfo.c *************************************/
|
||||
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info);
|
||||
#endif
|
||||
|
||||
/* Functions contained in mm_shrinkchunk.c **********************************/
|
||||
|
||||
void mm_shrinkchunk(FAR struct mm_heap_s *heap,
|
||||
FAR struct mm_allocnode_s *node, size_t size);
|
||||
|
||||
/* Functions contained in mm_addfreechunk.c *********************************/
|
||||
|
||||
void mm_addfreechunk(FAR struct mm_heap_s *heap,
|
||||
FAR struct mm_freenode_s *node);
|
||||
|
||||
/* Functions contained in mm_size2ndx.c.c ***********************************/
|
||||
|
||||
int mm_size2ndx(size_t size);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -107,47 +107,48 @@ struct mallinfo
|
|||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C" {
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/* Random number generation */
|
||||
|
||||
EXTERN void srand(unsigned int seed);
|
||||
EXTERN int rand(void);
|
||||
void srand(unsigned int seed);
|
||||
int rand(void);
|
||||
|
||||
/* Environment variable support */
|
||||
|
||||
#ifndef CONFIG_DISABLE_ENIVRON
|
||||
EXTERN FAR char **get_environ_ptr( void );
|
||||
EXTERN FAR char *getenv(FAR const char *name);
|
||||
EXTERN int putenv(FAR const char *string);
|
||||
EXTERN int clearenv(void);
|
||||
EXTERN int setenv(const char *name, const char *value, int overwrite);
|
||||
EXTERN int unsetenv(const char *name);
|
||||
FAR char **get_environ_ptr( void );
|
||||
FAR char *getenv(FAR const char *name);
|
||||
int putenv(FAR const char *string);
|
||||
int clearenv(void);
|
||||
int setenv(const char *name, const char *value, int overwrite);
|
||||
int unsetenv(const char *name);
|
||||
#endif
|
||||
|
||||
/* Process exit functions */
|
||||
|
||||
EXTERN void exit(int status) noreturn_function;
|
||||
EXTERN void abort(void) noreturn_function;
|
||||
void exit(int status) noreturn_function;
|
||||
void abort(void) noreturn_function;
|
||||
#ifdef CONFIG_SCHED_ATEXIT
|
||||
EXTERN int atexit(CODE void (*func)(void));
|
||||
int atexit(CODE void (*func)(void));
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_ONEXIT
|
||||
EXTERN int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg);
|
||||
int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg);
|
||||
#endif
|
||||
|
||||
/* String to binary conversions */
|
||||
|
||||
EXTERN long strtol(const char *, char **, int);
|
||||
EXTERN unsigned long strtoul(const char *, char **, int);
|
||||
long strtol(const char *, char **, int);
|
||||
unsigned long strtoul(const char *, char **, int);
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
EXTERN long long strtoll(const char *, char **, int);
|
||||
EXTERN unsigned long long strtoull(const char *, char **, int);
|
||||
long long strtoll(const char *, char **, int);
|
||||
unsigned long long strtoull(const char *, char **, int);
|
||||
#endif
|
||||
EXTERN double_t strtod(const char *, char **);
|
||||
double_t strtod(const char *, char **);
|
||||
|
||||
#define atoi(nptr) strtol((nptr), NULL, 10)
|
||||
#define atol(nptr) strtol((nptr), NULL, 10)
|
||||
|
@ -158,30 +159,30 @@ EXTERN double_t strtod(const char *, char **);
|
|||
|
||||
/* Memory Management */
|
||||
|
||||
EXTERN FAR void *malloc(size_t);
|
||||
EXTERN void free(FAR void*);
|
||||
EXTERN FAR void *realloc(FAR void*, size_t);
|
||||
EXTERN FAR void *memalign(size_t, size_t);
|
||||
EXTERN FAR void *zalloc(size_t);
|
||||
EXTERN FAR void *calloc(size_t, size_t);
|
||||
FAR void *malloc(size_t);
|
||||
void free(FAR void*);
|
||||
FAR void *realloc(FAR void*, size_t);
|
||||
FAR void *memalign(size_t, size_t);
|
||||
FAR void *zalloc(size_t);
|
||||
FAR void *calloc(size_t, size_t);
|
||||
|
||||
/* Misc */
|
||||
|
||||
EXTERN int abs(int j);
|
||||
EXTERN long int labs(long int j);
|
||||
int abs(int j);
|
||||
long int labs(long int j);
|
||||
#ifdef CONFIG_HAVE_LONG_LONG
|
||||
EXTERN long long int llabs(long long int j);
|
||||
long long int llabs(long long int j);
|
||||
#endif
|
||||
|
||||
/* Sorting */
|
||||
|
||||
EXTERN void qsort(void *base, size_t nmemb, size_t size,
|
||||
int(*compar)(const void *, const void *));
|
||||
void qsort(void *base, size_t nmemb, size_t size,
|
||||
int(*compar)(const void *, const void *));
|
||||
|
||||
#ifdef CONFIG_CAN_PASS_STRUCTS
|
||||
EXTERN struct mallinfo mallinfo(void);
|
||||
struct mallinfo mallinfo(void);
|
||||
#else
|
||||
EXTERN int mallinfo(struct mallinfo *info);
|
||||
int mallinfo(struct mallinfo *info);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
|
|
21
mm/Kconfig
21
mm/Kconfig
|
@ -3,6 +3,18 @@
|
|||
# see misc/tools/kconfig-language.txt.
|
||||
#
|
||||
|
||||
config MM_MULTIHEAP
|
||||
bool "Build support for multiple heaps"
|
||||
default n
|
||||
---help---
|
||||
Build interfaces to support multiple heaps. This should not be
|
||||
confused with memory regions. One heap may be composed of multiple,
|
||||
non-contiguous memory regions. The fact that the heap is composed
|
||||
of such multiple regions is invisible to the end-user (other than
|
||||
the heap comes pre-fragemented). Multiple heaps, on the other hand,
|
||||
supports a separate set of allocators that operate on a separate set
|
||||
of memory regions.
|
||||
|
||||
config MM_SMALL
|
||||
bool "Small memory model"
|
||||
default n
|
||||
|
@ -16,6 +28,8 @@ config MM_SMALL
|
|||
CONFIG_MM_SMALL can be defined so that those MCUs will also benefit
|
||||
from the smaller, 16-bit-based allocation overhead.
|
||||
|
||||
NOTE: If MM_MULTIHEAP is selected, then this applies to all heaps.
|
||||
|
||||
config MM_REGIONS
|
||||
int "Number of memory regions"
|
||||
default 1
|
||||
|
@ -25,18 +39,21 @@ config MM_REGIONS
|
|||
that the memory manager must handle and enables the API
|
||||
mm_addregion(start, end);
|
||||
|
||||
NOTE: If MM_MULTIHEAP is selected, then this maximum number of regions
|
||||
applies to all heaps.
|
||||
|
||||
config ARCH_HAVE_HEAP2
|
||||
bool
|
||||
|
||||
config HEAP2_BASE
|
||||
hex "Start address of second heap region"
|
||||
hex "Start address of second user heap region"
|
||||
default 0x00000000
|
||||
depends on ARCH_HAVE_HEAP2
|
||||
---help---
|
||||
The base address of the second heap region.
|
||||
|
||||
config HEAP2_SIZE
|
||||
int "Size of the second heap region"
|
||||
int "Size of the second user heap region"
|
||||
default 0
|
||||
depends on ARCH_HAVE_HEAP2
|
||||
---help---
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
############################################################################
|
||||
# mm/Makefile.test
|
||||
#
|
||||
# Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
-include $(TOPDIR)/Make.defs
|
||||
|
||||
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
|
||||
|
||||
CC = gcc
|
||||
LD = gcc
|
||||
|
||||
DEFINES = -DMM_TEST=1
|
||||
WARNIGNS = -Wall -Wstrict-prototypes -Wshadow
|
||||
CFLAGS = -g $(DEFINES)
|
||||
LDFLAGS =
|
||||
|
||||
BIN = mm_test
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
$(OBJS): %.o1: %.c
|
||||
@echo "Compiling $<"
|
||||
@$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
@echo "Linking {$(OBJS)} to produce $@"
|
||||
@$(LD) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(BIN)
|
||||
rm -f *.o1
|
|
@ -37,8 +37,9 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include "mm_internal.h"
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
|
@ -37,8 +37,11 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include "mm_internal.h"
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -48,6 +51,28 @@
|
|||
* Global Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mm_calloc
|
||||
*
|
||||
* Descripton:
|
||||
* calloc calculates the size of the allocation and calls zalloc
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
FAR void *mm_calloc(FAR struct mm_heap_s *heap, size_t n, size_t elem_size)
|
||||
{
|
||||
FAR void *ret = NULL;
|
||||
|
||||
if (n > 0 && elem_size > 0)
|
||||
{
|
||||
ret = mm_zalloc(heap, n * elem_size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: calloc
|
||||
*
|
||||
|
@ -56,8 +81,12 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
|
||||
FAR void *calloc(size_t n, size_t elem_size)
|
||||
{
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
return mm_calloc(&g_mmheap, n, elem_size);
|
||||
#else
|
||||
FAR void *ret = NULL;
|
||||
|
||||
if (n > 0 && elem_size > 0)
|
||||
|
@ -66,4 +95,6 @@ FAR void *calloc(size_t n, size_t elem_size)
|
|||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
/****************************************************************************
|
||||
* mm/mm_environment.h
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __MM_MM_ENVIRONMENT_H
|
||||
#define __MM_MM_ENVIRONMENT_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
/* The platform configuration file will not be included when the memory
|
||||
* manager is built for the host-based test harness.
|
||||
*/
|
||||
|
||||
#ifndef MM_TEST
|
||||
# include <nuttx/config.h>
|
||||
# include <nuttx/compiler.h>
|
||||
# include <sys/types.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.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
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Special definitions used when the memory mnager is built for the host-
|
||||
* based test harness.
|
||||
*/
|
||||
|
||||
#ifdef MM_TEST
|
||||
|
||||
/* Fake NuttX dependencies */
|
||||
|
||||
# define FAR /* Normally in compiler.h */
|
||||
# define CONFIG_CPP_HAVE_VARARGS 1 /* Normally in compiler.h */
|
||||
# define CONFIG_MM_REGIONS 2 /* Normally in config.h */
|
||||
# undef CONFIG_MM_SMALL /* Normally in config.h */
|
||||
# define CONFIG_CAN_PASS_STRUCTS 1 /* Normally in config.h */
|
||||
# undef CONFIG_SMALL_MEMORY /* Normally in config.h */
|
||||
|
||||
void mm_addregion(FAR void *heapstart, size_t heapsize);
|
||||
|
||||
/* Use the real system errno */
|
||||
|
||||
# define mm_errno errno
|
||||
|
||||
/* When built for the test harness, we change the names of the exported
|
||||
* functions so that they do not collide with the host libc names.
|
||||
*/
|
||||
|
||||
# define malloc mm_malloc
|
||||
# define memalign mm_memalign
|
||||
# define realloc mm_realloc
|
||||
# define zalloc mm_zalloc
|
||||
# define calloc mm_calloc
|
||||
# define free mm_free
|
||||
|
||||
/* Use normal libc assertion functions */
|
||||
|
||||
# undef ASSERT
|
||||
# define ASSERT(e) assert(e)
|
||||
# undef DEBUGASSERT
|
||||
# define DEBUGASSERT(e) assert(e)
|
||||
|
||||
/* Misc. NuttX-isms */
|
||||
|
||||
#define OK 0
|
||||
|
||||
/* Debug macros are always on */
|
||||
|
||||
# define CONFIG_DEBUG 1
|
||||
|
||||
# undef mdbg
|
||||
# define mdbg(format, arg...) printf(format, ##arg)
|
||||
# undef mvdg
|
||||
# define mvdbg(format, arg...) printf(format, ##arg)
|
||||
# undef mlldbg
|
||||
# define mlldbg(format, arg...) printf(format, ##arg)
|
||||
# undef mllvdg
|
||||
# define mllvdbg(format, arg...) printf(format, ##arg)
|
||||
|
||||
#else
|
||||
# define mm_errno get_errno()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#endif /* __MM_MM_ENVIRONMENT_H */
|
18
mm/mm_free.c
18
mm/mm_free.c
|
@ -37,10 +37,13 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include "mm_internal.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -51,7 +54,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: _mm_free
|
||||
* Name: mm_free
|
||||
*
|
||||
* Description:
|
||||
* Returns a chunk of memory to the list of free nodes, merging with
|
||||
|
@ -59,7 +62,10 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void _mm_free(FAR struct mm_heap_s *heap, FAR void *mem)
|
||||
#ifndef CONFIG_MM_MULTIHEAP
|
||||
static inline
|
||||
#endif
|
||||
void mm_free(FAR struct mm_heap_s *heap, FAR void *mem)
|
||||
{
|
||||
FAR struct mm_freenode_s *node;
|
||||
FAR struct mm_freenode_s *prev;
|
||||
|
@ -164,6 +170,6 @@ static inline void _mm_free(FAR struct mm_heap_s *heap, FAR void *mem)
|
|||
#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
|
||||
void free(FAR void *mem)
|
||||
{
|
||||
_mm_free(&g_mmheap, mem);
|
||||
mm_free(&g_mmheap, mem);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -37,8 +37,13 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include "mm_internal.h"
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
277
mm/mm_internal.h
277
mm/mm_internal.h
|
@ -1,277 +0,0 @@
|
|||
/****************************************************************************
|
||||
* mm/mm_internal.h
|
||||
*
|
||||
* 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
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __MM_MM_INTERNAL_H
|
||||
#define __MM_MM_INTERNAL_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* If the MCU has a small (16-bit) address capability, then we will use
|
||||
* a smaller chunk header that contains 16-bit size/offset information.
|
||||
* We will also use the smaller header on MCUs with wider addresses if
|
||||
* CONFIG_MM_SMALL is selected. This configuration is common with MCUs
|
||||
* that have a large FLASH space, but only a tiny internal SRAM.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMALL_MEMORY
|
||||
/* If the MCU has a small addressing capability, then for the smaller
|
||||
* chunk header.
|
||||
*/
|
||||
|
||||
# undef CONFIG_MM_SMALL
|
||||
# define CONFIG_MM_SMALL 1
|
||||
#endif
|
||||
|
||||
/* Chunk Header Definitions *************************************************/
|
||||
/* These definitions define the characteristics of allocator
|
||||
*
|
||||
* MM_MIN_SHIFT is used to define MM_MIN_CHUNK.
|
||||
* MM_MIN_CHUNK - is the smallest physical chunk that can
|
||||
* be allocated. It must be at least a large as
|
||||
* sizeof(struct mm_freenode_s). Larger values may
|
||||
* improve performance slightly, but will waste memory
|
||||
* due to quantization losses.
|
||||
*
|
||||
* MM_MAX_SHIFT is used to define MM_MAX_CHUNK
|
||||
* MM_MAX_CHUNK is the largest, contiguous chunk of memory
|
||||
* that can be allocated. It can range from 16-bytes to
|
||||
* 4Gb. Larger values of MM_MAX_SHIFT can cause larger
|
||||
* data structure sizes and, perhaps, minor performance
|
||||
* losses.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# define MM_MIN_SHIFT 4 /* 16 bytes */
|
||||
# define MM_MAX_SHIFT 15 /* 32 Kb */
|
||||
#else
|
||||
# define MM_MIN_SHIFT 4 /* 16 bytes */
|
||||
# define MM_MAX_SHIFT 22 /* 4 Mb */
|
||||
#endif
|
||||
|
||||
/* All other definitions derive from these two */
|
||||
|
||||
#define MM_MIN_CHUNK (1 << MM_MIN_SHIFT)
|
||||
#define MM_MAX_CHUNK (1 << MM_MAX_SHIFT)
|
||||
#define MM_NNODES (MM_MAX_SHIFT - MM_MIN_SHIFT + 1)
|
||||
|
||||
#define MM_GRAN_MASK (MM_MIN_CHUNK-1)
|
||||
#define MM_ALIGN_UP(a) (((a) + MM_GRAN_MASK) & ~MM_GRAN_MASK)
|
||||
#define MM_ALIGN_DOWN(a) ((a) & ~MM_GRAN_MASK)
|
||||
|
||||
/* An allocated chunk is distinguished from a free chunk by
|
||||
* bit 31 of the 'preceding' chunk size. If set, then this is
|
||||
* an allocated chunk.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# define MM_ALLOC_BIT 0x8000
|
||||
#else
|
||||
# define MM_ALLOC_BIT 0x80000000
|
||||
#endif
|
||||
#define MM_IS_ALLOCATED(n) \
|
||||
((int)((struct mm_allocnode_s*)(n)->preceding) < 0))
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Determines the size of the chunk size/offset type */
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
typedef uint16_t mmsize_t;
|
||||
# define MMSIZE_MAX 0xffff
|
||||
#else
|
||||
typedef size_t mmsize_t;
|
||||
# define MMSIZE_MAX SIZE_MAX
|
||||
#endif
|
||||
|
||||
/* This describes an allocated chunk. An allocated chunk is
|
||||
* distinguished from a free chunk by bit 15/31 of the 'preceding' chunk
|
||||
* size. If set, then this is an allocated chunk.
|
||||
*/
|
||||
|
||||
struct mm_allocnode_s
|
||||
{
|
||||
mmsize_t size; /* Size of this chunk */
|
||||
mmsize_t preceding; /* Size of the preceding chunk */
|
||||
};
|
||||
|
||||
/* What is the size of the allocnode? */
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# define SIZEOF_MM_ALLOCNODE 4
|
||||
#else
|
||||
# define SIZEOF_MM_ALLOCNODE 8
|
||||
#endif
|
||||
|
||||
#define CHECK_ALLOCNODE_SIZE \
|
||||
DEBUGASSERT(sizeof(struct mm_allocnode_s) == SIZEOF_MM_ALLOCNODE)
|
||||
|
||||
/* This describes a free chunk */
|
||||
|
||||
struct mm_freenode_s
|
||||
{
|
||||
mmsize_t size; /* Size of this chunk */
|
||||
mmsize_t preceding; /* Size of the preceding chunk */
|
||||
FAR struct mm_freenode_s *flink; /* Supports a doubly linked list */
|
||||
FAR struct mm_freenode_s *blink;
|
||||
};
|
||||
|
||||
/* What is the size of the freenode? */
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# ifdef CONFIG_SMALL_MEMORY
|
||||
# define SIZEOF_MM_FREENODE 8
|
||||
# else
|
||||
# define SIZEOF_MM_FREENODE 12
|
||||
# endif
|
||||
#else
|
||||
# define SIZEOF_MM_FREENODE 16
|
||||
#endif
|
||||
|
||||
#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
|
||||
struct mallinfo
|
||||
{
|
||||
int arena; /* This is the total size of memory allocated
|
||||
* for use by malloc in bytes. */
|
||||
int ordblks; /* This is the number of free (not in use) chunks */
|
||||
int mxordblk; /* Size of the largest free (not in use) chunk */
|
||||
int uordblks; /* This is the total size of memory occupied by
|
||||
* chunks handed out by malloc. */
|
||||
int fordblks; /* This is the total size of memory occupied
|
||||
* by free (not in use) chunks.*/
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Variables
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
|
||||
/* This is the user heap */
|
||||
|
||||
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);
|
||||
#ifdef CONFIG_CAN_PASS_STRUCTS
|
||||
struct mallinfo mallinfo(void);
|
||||
#else
|
||||
int mallinfo(struct mallinfo *info);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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(FAR struct mm_heap_s *heap);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MM_MM_INTERNAL_H */
|
|
@ -37,10 +37,13 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include "mm_internal.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -55,15 +58,17 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: _mm_mallinfo
|
||||
* Name: mm_mallinfo
|
||||
*
|
||||
* Description:
|
||||
* mallinfo returns a copy of updated current heap information.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int _mm_mallinfo(FAR struct mm_heap_s *heap,
|
||||
FAR struct mallinfo *info)
|
||||
#ifndef CONFIG_MM_MULTIHEAP
|
||||
static inline
|
||||
#endif
|
||||
int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info)
|
||||
{
|
||||
struct mm_allocnode_s *node;
|
||||
size_t mxordblk = 0;
|
||||
|
@ -148,7 +153,7 @@ struct mallinfo mallinfo(void)
|
|||
{
|
||||
struct mallinfo info;
|
||||
|
||||
_mm_mallinfo(&g_mmheap, &info);
|
||||
mm_mallinfo(&g_mmheap, &info);
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -156,7 +161,7 @@ struct mallinfo mallinfo(void)
|
|||
|
||||
int mallinfo(struct mallinfo *info)
|
||||
{
|
||||
return _mm_mallinfo(&g_mmheap, info);
|
||||
return mm_mallinfo(&g_mmheap, info);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,14 +37,12 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
/* Special definitions when we operate in the normal vs. the host-pc test
|
||||
* environement.
|
||||
*/
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include "mm_internal.h"
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -71,7 +69,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: _mm_malloc
|
||||
* Name: mm_malloc
|
||||
*
|
||||
* Description:
|
||||
* Find the smallest chunk that satisfies the request. Take the memory from
|
||||
|
@ -81,7 +79,10 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline FAR void *_mm_malloc(FAR struct mm_heap_s *heap, size_t size)
|
||||
#ifndef CONFIG_MM_MULTIHEAP
|
||||
static inline
|
||||
#endif
|
||||
FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size)
|
||||
{
|
||||
FAR struct mm_freenode_s *node;
|
||||
void *ret = NULL;
|
||||
|
@ -229,7 +230,7 @@ static inline FAR void *_mm_malloc(FAR struct mm_heap_s *heap, size_t size)
|
|||
#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
|
||||
FAR void *malloc(size_t size)
|
||||
{
|
||||
return _mm_malloc(&g_mmheap, size);
|
||||
return mm_malloc(&g_mmheap, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,10 +37,12 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include "mm_internal.h"
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -51,7 +53,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: _mm_memalign
|
||||
* Name: mm_memalign
|
||||
*
|
||||
* Description:
|
||||
* memalign requests more than enough space from malloc, finds a region
|
||||
|
@ -63,8 +65,11 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline FAR void *_mm_memalign(FAR struct mm_heap_s *heap,
|
||||
size_t alignment, size_t size)
|
||||
#ifndef CONFIG_MM_MULTIHEAP
|
||||
static inline
|
||||
#endif
|
||||
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;
|
||||
|
@ -213,7 +218,7 @@ static inline FAR void *_mm_memalign(FAR struct mm_heap_s *heap,
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: _mm_memalign
|
||||
* Name: memalign
|
||||
*
|
||||
* Description:
|
||||
* memalign requests more than enough space from malloc, finds a region
|
||||
|
@ -229,7 +234,7 @@ static inline FAR void *_mm_memalign(FAR struct mm_heap_s *heap,
|
|||
|
||||
FAR void *memalign(size_t alignment, size_t size)
|
||||
{
|
||||
return _mm_memalign(&g_mmheap, alignment, size);
|
||||
return mm_memalign(&g_mmheap, alignment, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,10 +37,14 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mm_environment.h"
|
||||
#include <stdio.h>
|
||||
#include "mm_internal.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -51,7 +55,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: _mm_realloc
|
||||
* Name: mm_realloc
|
||||
*
|
||||
* Description:
|
||||
* If the reallocation is for less space, then:
|
||||
|
@ -73,8 +77,11 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline FAR void *_mm_realloc(FAR struct mm_heap_s *heap,
|
||||
FAR void *oldmem, size_t size)
|
||||
#ifndef CONFIG_MM_MULTIHEAP
|
||||
static inline
|
||||
#endif
|
||||
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;
|
||||
|
@ -383,7 +390,7 @@ static inline FAR void *_mm_realloc(FAR struct mm_heap_s *heap,
|
|||
|
||||
FAR void *realloc(FAR void *oldmem, size_t size)
|
||||
{
|
||||
return _mm_realloc(&g_mmheap, oldmem, size);
|
||||
return mm_realloc(&g_mmheap, oldmem, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
25
mm/mm_sem.c
25
mm/mm_sem.c
|
@ -37,13 +37,13 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mm_internal.h"
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -106,7 +106,6 @@ void mm_seminitialize(FAR struct mm_heap_s *heap)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef MM_TEST
|
||||
int mm_trysemaphore(FAR struct mm_heap_s *heap)
|
||||
{
|
||||
pid_t my_pid = getpid();
|
||||
|
@ -136,7 +135,6 @@ int mm_trysemaphore(FAR struct mm_heap_s *heap)
|
|||
return OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mm_takesemaphore
|
||||
|
@ -170,7 +168,7 @@ void mm_takesemaphore(FAR struct mm_heap_s *heap)
|
|||
* the wait was awakened by a signal.
|
||||
*/
|
||||
|
||||
ASSERT(mm_errno == EINTR);
|
||||
ASSERT(errno == EINTR);
|
||||
}
|
||||
|
||||
/* We have it. Claim the stake and return */
|
||||
|
@ -220,20 +218,3 @@ void mm_givesemaphore(FAR struct mm_heap_s *heap)
|
|||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mm_getsemaphore
|
||||
*
|
||||
* Description:
|
||||
* Return the current value of the MM semaphore (for test purposes only)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef MM_TEST
|
||||
int mm_getsemaphore(FAR struct mm_heap_s *heap)
|
||||
{
|
||||
int sval;
|
||||
sem_getvalue(&heap->mm_semaphore, &sval);
|
||||
return sval;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,8 +37,11 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include "mm_internal.h"
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
|
@ -37,8 +37,9 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include "mm_internal.h"
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
536
mm/mm_test.c
536
mm/mm_test.c
|
@ -1,536 +0,0 @@
|
|||
/************************************************************************
|
||||
* mm/mm_test.c
|
||||
*
|
||||
* 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
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Included Files
|
||||
************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
/************************************************************************
|
||||
* Pre-processor Definitions
|
||||
************************************************************************/
|
||||
|
||||
/* Fake NuttX dependencies */
|
||||
|
||||
#define FAR
|
||||
#define CONFIG_MM_REGIONS 2
|
||||
#undef CONFIG_MM_SMALL
|
||||
#define CONFIG_CAN_PASS_STRUCTS 1
|
||||
#undef CONFIG_SMALL_MEMORY
|
||||
|
||||
#include "mm_internal.h"
|
||||
|
||||
/* Pre-processor Definitions */
|
||||
|
||||
#define TEST_HEAP1_SIZE 0x00080000
|
||||
#define TEST_HEAP2_SIZE 0x00080000
|
||||
#define NTEST_ALLOCS 32
|
||||
|
||||
/* #define STOP_ON_ERRORS do{}while(0) */
|
||||
#define STOP_ON_ERRORS exit(1)
|
||||
|
||||
/************************************************************************
|
||||
* Private Data
|
||||
************************************************************************/
|
||||
|
||||
/* Test allocations */
|
||||
|
||||
static const int alloc_sizes[NTEST_ALLOCS] =
|
||||
{
|
||||
1024, 12, 962, 5692, 10254, 111, 9932, 601,
|
||||
222, 2746, 3, 124321, 68, 776, 6750, 852,
|
||||
4732, 28, 901, 480, 5011, 1536, 2011, 81647,
|
||||
646, 1646, 69179, 194, 2590, 7, 969, 70
|
||||
};
|
||||
|
||||
static const int realloc_sizes[NTEST_ALLOCS] =
|
||||
{
|
||||
18, 3088, 963, 123, 511, 11666, 3723, 42,
|
||||
9374, 1990, 1412, 6, 592, 4088, 11, 5040,
|
||||
8663, 91255, 28, 4346, 9172, 168, 229, 4734,
|
||||
59139, 221, 7830, 30421, 1666, 4, 812, 416
|
||||
};
|
||||
|
||||
static const int random1[NTEST_ALLOCS] =
|
||||
{
|
||||
20, 11, 3, 31, 9, 29, 7, 17,
|
||||
21, 2, 26, 18, 14, 25, 0, 10,
|
||||
27, 19, 22, 28, 8, 30, 12, 15,
|
||||
4, 1, 24, 6, 16, 13, 5, 23
|
||||
};
|
||||
|
||||
static const int random2[NTEST_ALLOCS] =
|
||||
{
|
||||
2, 19, 12, 23, 30, 11, 27, 4,
|
||||
20, 7, 0, 16, 28, 15, 5, 24,
|
||||
10, 17, 25, 31, 8, 29, 3, 26,
|
||||
9, 18, 22, 13, 1, 21, 14, 6
|
||||
};
|
||||
|
||||
static const int random3[NTEST_ALLOCS] =
|
||||
{
|
||||
8, 17, 3, 18, 26, 23, 30, 11,
|
||||
12, 22, 4, 20, 25, 10, 27, 1,
|
||||
29, 14, 19, 21, 0, 31, 7, 24,
|
||||
9, 15, 2, 28, 16, 6, 13, 5
|
||||
};
|
||||
|
||||
static const int alignment[NTEST_ALLOCS/2] =
|
||||
{
|
||||
128, 2048, 131072, 8192, 32, 32768, 16384 , 262144,
|
||||
512, 4096, 65536, 8, 64, 1024, 16, 4
|
||||
};
|
||||
|
||||
static void *allocs[NTEST_ALLOCS];
|
||||
static struct mallinfo alloc_info;
|
||||
static unsigned int g_reportedheapsize = 0;
|
||||
static unsigned int g_actualheapsize = 0;
|
||||
|
||||
/************************************************************************
|
||||
* Private Functions
|
||||
************************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Name: mm_findinfreelist
|
||||
************************************************************************/
|
||||
|
||||
static int mm_findinfreelist(struct mm_freenode_s *node)
|
||||
{
|
||||
struct mm_freenode_s *list;
|
||||
|
||||
for(list = &g_mmheap.mm_nodelist[0];
|
||||
list;
|
||||
list = list->flink)
|
||||
{
|
||||
if (list == node)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: mm_showchunkinfo
|
||||
************************************************************************/
|
||||
|
||||
static void mm_showchunkinfo(void)
|
||||
{
|
||||
struct mm_allocnode_s *node;
|
||||
#if CONFIG_MM_REGIONS > 1
|
||||
int region;
|
||||
#else
|
||||
# define region 0
|
||||
#endif
|
||||
int found;
|
||||
|
||||
printf(" CHUNK LIST:\n");
|
||||
|
||||
/* Visit each region */
|
||||
|
||||
#if CONFIG_MM_REGIONS > 1
|
||||
for (region = 0; region < g_mmheap.mm_nregions; region++)
|
||||
#endif
|
||||
{
|
||||
/* Visit each node in each 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",
|
||||
node, node->size, node->preceding & ~MM_ALLOC_BIT,
|
||||
node->preceding & MM_ALLOC_BIT ? "Allocated" : "Free ");
|
||||
found = mm_findinfreelist((struct mm_freenode_s *)node);
|
||||
if (found && (node->preceding & MM_ALLOC_BIT) != 0)
|
||||
{
|
||||
printf(" Should NOT have been in free list\n");
|
||||
}
|
||||
else if (!found && (node->preceding & MM_ALLOC_BIT) == 0)
|
||||
{
|
||||
printf(" SHOULD have been in free listT\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" OK\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef region
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: mm_showfreelist
|
||||
************************************************************************/
|
||||
|
||||
static void mm_showfreelist(void)
|
||||
{
|
||||
struct mm_freenode_s *prev;
|
||||
struct mm_freenode_s *node;
|
||||
int i = 0;
|
||||
|
||||
printf(" FREE NODE LIST:\n");
|
||||
for(prev = NULL, node = &g_mmheap.mm_nodelist[0];
|
||||
node;
|
||||
prev = node, node = node->flink)
|
||||
{
|
||||
/* Dump "fake" nodes in a different way */
|
||||
|
||||
if (node->size == 0)
|
||||
{
|
||||
printf(" [NODE %2d] %08x %08x %08x\n",
|
||||
i, node->preceding, (int)node->flink, (int)node->blink);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" %08x %08x %08x %08x %08x\n",
|
||||
(int)node, node->size, node->preceding, (int)node->flink, (int)node->blink);
|
||||
}
|
||||
|
||||
/* Verify all backward links */
|
||||
|
||||
if (node->blink != prev)
|
||||
{
|
||||
fprintf(stderr, "Backward link is wrong: Is %p, should be %p\n",
|
||||
node->blink, prev);
|
||||
STOP_ON_ERRORS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: mm_showmallinfo
|
||||
************************************************************************/
|
||||
|
||||
static void mm_showmallinfo(void)
|
||||
{
|
||||
int sval;
|
||||
|
||||
mm_showchunkinfo();
|
||||
mm_showfreelist();
|
||||
alloc_info = mallinfo();
|
||||
printf(" mallinfo:\n");
|
||||
printf(" Total space allocated from system = %ld\n",
|
||||
alloc_info.arena);
|
||||
printf(" Number of non-inuse chunks = %ld\n",
|
||||
alloc_info.ordblks);
|
||||
printf(" Largest non-inuse chunk = %ld\n",
|
||||
alloc_info.mxordblk);
|
||||
printf(" Total allocated space = %ld\n",
|
||||
alloc_info.uordblks);
|
||||
printf(" Total non-inuse space = %ld\n",
|
||||
alloc_info.fordblks);
|
||||
|
||||
sval = mm_getsemaphore(&g_mmheap);
|
||||
if (sval != 1)
|
||||
{
|
||||
fprintf(stderr, "After mallinfo, semaphore count=%d, should be 1\n", sval);
|
||||
STOP_ON_ERRORS;
|
||||
}
|
||||
|
||||
if (!g_reportedheapsize)
|
||||
{
|
||||
g_reportedheapsize = alloc_info.uordblks + alloc_info.fordblks;
|
||||
if (g_reportedheapsize > g_actualheapsize + 16*CONFIG_MM_REGIONS ||
|
||||
g_reportedheapsize < g_actualheapsize -16*CONFIG_MM_REGIONS)
|
||||
{
|
||||
fprintf(stderr, "Total memory %d not close to uordlbks=%d + fordblks=%d = %d\n",
|
||||
g_actualheapsize, alloc_info.uordblks, alloc_info.fordblks, g_reportedheapsize);
|
||||
STOP_ON_ERRORS;
|
||||
}
|
||||
}
|
||||
else if (alloc_info.uordblks + alloc_info.fordblks != g_reportedheapsize)
|
||||
{
|
||||
fprintf(stderr, "Total memory %d != uordlbks=%d + fordblks=%d\n",
|
||||
g_reportedheapsize, alloc_info.uordblks, alloc_info.fordblks);
|
||||
STOP_ON_ERRORS;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: do_mallocs
|
||||
************************************************************************/
|
||||
|
||||
static void do_mallocs(void **mem, const int *size, const int *rand,
|
||||
int n)
|
||||
{
|
||||
int sval;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
j = rand[i];
|
||||
if (!mem[j])
|
||||
{
|
||||
printf("(%d)Allocating %d bytes\n", i, size[j]);
|
||||
mem[j] = mm_malloc(size[j]);
|
||||
printf("(%d)Memory allocated at %p\n", i, mem[j]);
|
||||
if (mem[j] == NULL)
|
||||
{
|
||||
int allocsize = MM_ALIGN_UP(size[j] + SIZEOF_MM_ALLOCNODE);
|
||||
fprintf(stderr, "(%d)malloc failed for allocsize=%d\n", i, allocsize);
|
||||
if (allocsize > alloc_info.mxordblk)
|
||||
{
|
||||
fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(mem[j], 0xAA, size[j]);
|
||||
}
|
||||
|
||||
sval = mm_getsemaphore(&g_mmheap);
|
||||
if (sval != 1)
|
||||
{
|
||||
fprintf(stderr, " After malloc semaphore count=%d, should be 1\n", sval);
|
||||
STOP_ON_ERRORS;
|
||||
}
|
||||
|
||||
mm_showmallinfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: do_reallocs
|
||||
************************************************************************/
|
||||
|
||||
static void do_reallocs(void **mem, const int *oldsize,
|
||||
const int *newsize, const int *rand, int n)
|
||||
{
|
||||
int sval;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
j = rand[i];
|
||||
printf("(%d)Re-allocating at %p from %d to %d bytes\n",
|
||||
i, mem[j], oldsize[j], newsize[j]);
|
||||
mem[j] = mm_realloc(mem[j], newsize[j]);
|
||||
printf("(%d)Memory re-allocated at %p\n", i, mem[j]);
|
||||
if (mem[j] == NULL)
|
||||
{
|
||||
int allocsize = MM_ALIGN_UP(newsize[j] + SIZEOF_MM_ALLOCNODE);
|
||||
fprintf(stderr, "(%d)realloc failed for allocsize=%d\n", i, allocsize);
|
||||
if (allocsize > alloc_info.mxordblk)
|
||||
{
|
||||
fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(mem[j], 0x55, newsize[j]);
|
||||
}
|
||||
|
||||
sval = mm_getsemaphore(&g_mmheap);
|
||||
if (sval != 1)
|
||||
{
|
||||
fprintf(stderr, " After realloc semaphore count=%d, should be 1\n", sval);
|
||||
STOP_ON_ERRORS;
|
||||
}
|
||||
|
||||
mm_showmallinfo();
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: do_memaligns
|
||||
************************************************************************/
|
||||
|
||||
static void do_memaligns(void **mem, const int *size, const int *align,
|
||||
const int *rand, int n)
|
||||
{
|
||||
int sval;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
j = rand[i];
|
||||
printf("(%d)Allocating %d bytes aligned to 0x%08x\n",
|
||||
i, size[j], align[i]);
|
||||
mem[j] = mm_memalign(align[i], size[j]);
|
||||
printf("(%d)Memory allocated at %p\n", i, mem[j]);
|
||||
if (mem[j] == NULL)
|
||||
{
|
||||
int allocsize = MM_ALIGN_UP(size[j] + SIZEOF_MM_ALLOCNODE) + 2*align[i];
|
||||
fprintf(stderr, "(%d)memalign failed for allocsize=%d\n", i, allocsize);
|
||||
if (allocsize > alloc_info.mxordblk)
|
||||
{
|
||||
fprintf(stderr, " Normal, largest free block is only %ld\n", alloc_info.mxordblk);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, " ERROR largest free block is %ld\n", alloc_info.mxordblk);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(mem[j], 0x33, size[j]);
|
||||
}
|
||||
|
||||
sval = mm_getsemaphore(&g_mmheap);
|
||||
if (sval != 1)
|
||||
{
|
||||
fprintf(stderr, " After memalign semaphore count=%d, should be 1\n", sval);
|
||||
STOP_ON_ERRORS;
|
||||
}
|
||||
|
||||
mm_showmallinfo();
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Name: do_frees
|
||||
************************************************************************/
|
||||
|
||||
static void do_frees(void **mem, const int *size, const int *rand, int n)
|
||||
{
|
||||
int sval;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
j = rand[i];
|
||||
printf("(%d)Releasing memory at %p (size=%d bytes)\n",
|
||||
i, mem[j], size[j]);
|
||||
mm_free(mem[j]);
|
||||
mem[j] = NULL;
|
||||
|
||||
sval = mm_getsemaphore(&g_mmheap);
|
||||
if (sval != 1)
|
||||
{
|
||||
fprintf(stderr, " After free semaphore count=%d, should be 1\n", sval);
|
||||
STOP_ON_ERRORS;
|
||||
}
|
||||
|
||||
mm_showmallinfo();
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Functions
|
||||
************************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
* Name: main
|
||||
************************************************************************/
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
void *heap1_base;
|
||||
void *heap2_base;
|
||||
int i, j;
|
||||
|
||||
/* Allocate a heap */
|
||||
|
||||
printf("Allocating test heap #1 of %ldKb\n", TEST_HEAP1_SIZE/1024);
|
||||
heap1_base = malloc(TEST_HEAP1_SIZE);
|
||||
printf("Allocated heap1_base=%p\n", heap1_base);
|
||||
if (heap1_base == 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to allocate test heap #1\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Allocating test heap #2 of %ldKb\n", TEST_HEAP2_SIZE/1024);
|
||||
heap2_base = malloc(TEST_HEAP2_SIZE);
|
||||
printf("Allocated heap2_base=%p\n", heap2_base);
|
||||
if (heap2_base == 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to allocate test heap #2\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Initialize the memory manager */
|
||||
|
||||
mm_initialize(heap1_base, TEST_HEAP1_SIZE);
|
||||
g_actualheapsize = TEST_HEAP1_SIZE;
|
||||
mm_showmallinfo();
|
||||
|
||||
mm_addregion(heap2_base, TEST_HEAP2_SIZE);
|
||||
g_reportedheapsize = 0;
|
||||
g_actualheapsize += TEST_HEAP2_SIZE;
|
||||
mm_showmallinfo();
|
||||
|
||||
/* Allocate some memory */
|
||||
|
||||
do_mallocs(allocs, alloc_sizes, random1, NTEST_ALLOCS);
|
||||
|
||||
/* Re-allocate the memory */
|
||||
|
||||
do_reallocs(allocs, alloc_sizes, realloc_sizes, random2, NTEST_ALLOCS);
|
||||
|
||||
/* Release the memory */
|
||||
|
||||
do_frees(allocs, realloc_sizes, random3, NTEST_ALLOCS);
|
||||
|
||||
/* Allocate aligned memory */
|
||||
|
||||
do_memaligns(allocs, alloc_sizes, alignment, random2, NTEST_ALLOCS/2);
|
||||
do_memaligns(allocs, alloc_sizes, alignment, &random2[NTEST_ALLOCS/2], NTEST_ALLOCS/2);
|
||||
|
||||
/* Release aligned memory */
|
||||
|
||||
do_frees(allocs, alloc_sizes, random1, NTEST_ALLOCS);
|
||||
|
||||
/* Clean up and exit */
|
||||
|
||||
free(heap1_base);
|
||||
free(heap2_base);
|
||||
|
||||
printf("TEST COMPLETE\n");
|
||||
return 0;
|
||||
}
|
|
@ -37,8 +37,12 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "mm_environment.h"
|
||||
#include "mm_internal.h"
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/mm.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -49,16 +53,17 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: zalloc
|
||||
* Name: mm_zalloc
|
||||
*
|
||||
* Description:
|
||||
* zalloc calls malloc, then zeroes out the allocated chunk.
|
||||
* mm_zalloc calls mm_malloc, then zeroes out the allocated chunk.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *zalloc(size_t size)
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
FAR void *mm_zalloc(FAR struct mm_heap_s *heap, size_t size)
|
||||
{
|
||||
FAR void *alloc = malloc(size);
|
||||
FAR void *alloc = mm_malloc(heap, size);
|
||||
if (alloc)
|
||||
{
|
||||
memset(alloc, 0, size);
|
||||
|
@ -66,3 +71,29 @@ FAR void *zalloc(size_t size)
|
|||
|
||||
return alloc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: zalloc
|
||||
*
|
||||
* Description:
|
||||
* zalloc calls malloc, then zeroes out the allocated chunk.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_NUTTX_KERNEL) || !defined(__KERNEL__)
|
||||
FAR void *zalloc(size_t size)
|
||||
{
|
||||
#ifdef CONFIG_MM_MULTIHEAP
|
||||
return mm_zalloc(&g_mmheap, size);
|
||||
#else
|
||||
FAR void *alloc = malloc(size);
|
||||
if (alloc)
|
||||
{
|
||||
memset(alloc, 0, size);
|
||||
}
|
||||
|
||||
return alloc;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue