From b75545f120098c59c81a733f24749045b818eced Mon Sep 17 00:00:00 2001 From: patacongo Date: Tue, 11 Sep 2012 21:39:39 +0000 Subject: [PATCH] Fixes for granule allocator git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5131 42af7a65-404d-4744-a932-0658087f49c3 --- include/nuttx/gran.h | 4 ++-- mm/Makefile | 2 +- mm/mm_gran.h | 20 ++++++++++++++++++++ mm/mm_granalloc.c | 9 ++++++++- mm/mm_granfree.c | 17 +++++++++++------ mm/mm_graninit.c | 39 ++++++++++++++++++++++++++++++++++++++- 6 files changed, 80 insertions(+), 11 deletions(-) diff --git a/include/nuttx/gran.h b/include/nuttx/gran.h index bb08f9b374..1176735cf1 100644 --- a/include/nuttx/gran.h +++ b/include/nuttx/gran.h @@ -106,8 +106,8 @@ extern "C" { ****************************************************************************/ #ifdef CONFIG_GRAN_SINGLE -EXTERN void gran_initialize(FAR void *heapstart, size_t heapsize, - uint8_t log2gran); +EXTERN int gran_initialize(FAR void *heapstart, size_t heapsize, + uint8_t log2gran); #else EXTERN GRAN_HANDLE gran_initialize(FAR void *heapstart, size_t heapsize, uint8_t log2gran); diff --git a/mm/Makefile b/mm/Makefile index ef168f0db1..0cd28b23d1 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -41,7 +41,7 @@ CSRCS = mm_initialize.c mm_sem.c mm_addfreechunk.c mm_size2ndx.c mm_shrinkchunk mm_memalign.c mm_free.c mm_mallinfo.c ifeq ($(CONFIG_GRAN),y) -CSRCS = mm_graninit.c mm_granalloc.c mm_granfree.c +CSRCS += mm_graninit.c mm_granalloc.c mm_granfree.c endif AOBJS = $(ASRCS:.S=$(OBJEXT)) diff --git a/mm/mm_gran.h b/mm/mm_gran.h index d8a334e298..4a76397c82 100644 --- a/mm/mm_gran.h +++ b/mm/mm_gran.h @@ -43,6 +43,7 @@ #include #include +#include #include @@ -87,6 +88,7 @@ struct gran_s { uint8_t log2gran; /* Log base 2 of the size of one granule */ uint16_t ngranules; /* The total number of (aligned) granules in the heap */ + sem_t exclsem; /* For exclusive access to the GAT */ uintptr_t heapstart; /* The aligned start of the granule heap */ uint32_t gat[1]; /* Start of the granule allocation table */ }; @@ -105,4 +107,22 @@ extern FAR struct gran_s *g_graninfo; * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: gran_semtake and gran_semgive + * + * Description: + * Managed semaphore for the granule allocator. gran_semgive is + * implemented as a macro. + * + * Input Parameters: + * priv - Pointer to the gran state + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gran_semtake(FAR struct gran_s *priv); +#define gran_semgive(p) sem_post(&(p)->exclsem); + #endif /* __MM_MM_GRAN_H */ diff --git a/mm/mm_granalloc.c b/mm/mm_granalloc.c index a8802a6c51..0e94d464b0 100644 --- a/mm/mm_granalloc.c +++ b/mm/mm_granalloc.c @@ -93,7 +93,7 @@ static inline void gran_mark_allocated(FAR struct gran_s *priv, uintptr_t alloc, ngranules -= avail; } - /* Handle the cae where where all of the granules come from one entry */ + /* Handle the case where where all of the granules come from one entry */ else { @@ -135,8 +135,13 @@ static inline FAR void *gran_common_alloc(FAR struct gran_s *priv, size_t size) int j; DEBUGASSERT(priv && size <= 32 * (1 << priv->log2gran)); + if (priv && size > 0) { + /* Get exclusive access to the GAT */ + + gran_semtake(priv); + /* How many contiguous granules we we need to find? */ tmpmask = (1 << priv->log2gran) - 1; @@ -186,6 +191,7 @@ static inline FAR void *gran_common_alloc(FAR struct gran_s *priv, size_t size) /* And return the allocation address */ + gran_semgive(priv); return (FAR void *)alloc; } @@ -207,6 +213,7 @@ static inline FAR void *gran_common_alloc(FAR struct gran_s *priv, size_t size) } } + gran_semgive(priv); return NULL; } diff --git a/mm/mm_granfree.c b/mm/mm_granfree.c index e359cded8c..96fdda87e0 100644 --- a/mm/mm_granfree.c +++ b/mm/mm_granfree.c @@ -79,6 +79,10 @@ static inline void gran_common_free(FAR struct gran_s *priv, DEBUGASSERT(priv && memory && size <= 32 * (1 << priv->log2gran)); + /* Get exclusive access to the GAT */ + + gran_semtake(priv); + /* Determine the granule number of the first granule in the allocation */ granno = ((uintptr_t)memory - priv->heapstart) >> priv->log2gran; @@ -102,21 +106,22 @@ static inline void gran_common_free(FAR struct gran_s *priv, { priv->gat[gatidx] &= ~(0xffffffff << gatbit); ngranules -= avail; + + /* Clear bits in the second GAT entry */ + + gatmask = 0xffffffff >> (32 - ngranules); + priv->gat[gatidx+1] &= ~(gatmask << gatbit); } - /* Handle the cae where where all of the granules came from one entry */ + /* Handle the case where where all of the granules came from one entry */ else { gatmask = 0xffffffff >> (32 - ngranules); priv->gat[gatidx] &= ~(gatmask << gatbit); - return; } - /* Clear bits in the second GAT entry */ - - gatmask = 0xffffffff >> (32 - ngranules); - priv->gat[gatidx+1] &= ~(gatmask << gatbit); + gran_semgive(priv); } /**************************************************************************** diff --git a/mm/mm_graninit.c b/mm/mm_graninit.c index 46b5f5ff14..bc2c6f2a1a 100644 --- a/mm/mm_graninit.c +++ b/mm/mm_graninit.c @@ -40,6 +40,8 @@ #include #include +#include +#include #include @@ -95,6 +97,8 @@ static inline FAR struct gran_s *gran_common_initialize(FAR void *heapstart, unsigned int alignedsize; unsigned int ngranules; + DEBUGASSERT(heapstart && heapsize > 0 && log2gran > 0 && log2gran < 32); + /* Determine the number of granules */ mask = (1 << log2gran) - 1; @@ -115,6 +119,7 @@ static inline FAR struct gran_s *gran_common_initialize(FAR void *heapstart, priv->log2gran = log2gran; priv->ngranules = ngranules; priv->heapstart = alignedstart; + sem_init(&priv->exclsem, 0, 1); } return priv; @@ -153,7 +158,7 @@ static inline FAR struct gran_s *gran_common_initialize(FAR void *heapstart, int gran_initialize(FAR void *heapstart, size_t heapsize, uint8_t log2gran) { g_graninfo = gran_common_initialize(heapstart, heapsize, log2gran); - if (!g_granifo) + if (!g_graninfo) { return -ENOMEM; } @@ -167,6 +172,38 @@ GRAN_HANDLE gran_initialize(FAR void *heapstart, size_t heapsize, uint8_t log2gr } #endif +/**************************************************************************** + * Name: gran_semtake and gran_semgive + * + * Description: + * Managed semaphore for the granule allocator. gran_semgive is + * implemented as a macro. + * + * Input Parameters: + * priv - Pointer to the gran state + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gran_semtake(FAR struct gran_s *priv) +{ + int ret; + + /* Continue waiting if we are awakened by a signal */ + + do + { + ret = sem_wait(&priv->exclsem); + if (ret < 0) + { + DEBUGASSERT(errno == EINTR); + } + } + while (ret < 0); +} + #endif /* CONFIG_GRAN */