diff --git a/include/nuttx/mm/gran.h b/include/nuttx/mm/gran.h index d515a1c3ca0..30940efb842 100644 --- a/include/nuttx/mm/gran.h +++ b/include/nuttx/mm/gran.h @@ -170,11 +170,12 @@ void gran_release(GRAN_HANDLE handle); * size - The size of the region to be reserved * * Returned Value: - * None + * On success, a non-NULL pointer to the allocated memory is returned; + * NULL is returned on failure. * ****************************************************************************/ -void gran_reserve(GRAN_HANDLE handle, uintptr_t start, size_t size); +FAR void *gran_reserve(GRAN_HANDLE handle, uintptr_t start, size_t size); /**************************************************************************** * Name: gran_alloc diff --git a/mm/mm_gran/mm_gran.h b/mm/mm_gran/mm_gran.h index b9fe04bebac..3ef67916d31 100644 --- a/mm/mm_gran/mm_gran.h +++ b/mm/mm_gran/mm_gran.h @@ -109,11 +109,12 @@ void gran_leave_critical(FAR struct gran_s *priv); * ngranules - The number of granules allocated * * Returned Value: - * None + * On success, a non-NULL pointer to the allocated memory is returned; + * NULL is returned on failure. * ****************************************************************************/ -void gran_mark_allocated(FAR struct gran_s *priv, uintptr_t alloc, - unsigned int ngranules); +FAR void *gran_mark_allocated(FAR struct gran_s *priv, uintptr_t alloc, + unsigned int ngranules); #endif /* __MM_MM_GRAN_MM_GRAN_H */ diff --git a/mm/mm_gran/mm_granmark.c b/mm/mm_gran/mm_granmark.c index 05d60f9ae05..634778b414f 100644 --- a/mm/mm_gran/mm_granmark.c +++ b/mm/mm_gran/mm_granmark.c @@ -48,12 +48,13 @@ * ngranules - The number of granules allocated * * Returned Value: - * None + * On success, a non-NULL pointer to the allocated memory is returned; + * NULL is returned on failure. * ****************************************************************************/ -void gran_mark_allocated(FAR struct gran_s *priv, uintptr_t alloc, - unsigned int ngranules) +FAR void *gran_mark_allocated(FAR struct gran_s *priv, uintptr_t alloc, + unsigned int ngranules) { unsigned int granno; unsigned int gatidx; @@ -75,35 +76,46 @@ void gran_mark_allocated(FAR struct gran_s *priv, uintptr_t alloc, avail = 32 - gatbit; if (ngranules > avail) { - /* Mark bits in the first GAT entry */ + uint32_t gatmask2; - gatmask = 0xffffffff << gatbit; - DEBUGASSERT((priv->gat[gatidx] & gatmask) == 0); + gatmask = 0xffffffff << gatbit; + ngranules -= avail; + gatmask2 = 0xffffffff >> (32 - ngranules); + + /* Check that the area is free, from both mask words */ + + if (((priv->gat[gatidx] & gatmask) != 0) || + ((priv->gat[gatidx + 1] & gatmask2) != 0)) + { + return NULL; + } + + /* Mark bits in the first and second GAT entry */ priv->gat[gatidx] |= gatmask; - ngranules -= avail; - - /* Mark bits in the second GAT entry */ - - gatmask = 0xffffffff >> (32 - ngranules); - DEBUGASSERT((priv->gat[gatidx + 1] & gatmask) == 0); - - priv->gat[gatidx + 1] |= gatmask; + priv->gat[gatidx + 1] |= gatmask2; } /* Handle the case where where all of the granules come from one entry */ else { - /* Mark bits in a single GAT entry */ - gatmask = 0xffffffff >> (32 - ngranules); gatmask <<= gatbit; - DEBUGASSERT((priv->gat[gatidx] & gatmask) == 0); + + /* Check that the area is free */ + + if ((priv->gat[gatidx] & gatmask) != 0) + { + return NULL; + } + + /* Mark bits in a single GAT entry */ priv->gat[gatidx] |= gatmask; - return; } + + return (FAR void *)alloc; } #endif /* CONFIG_GRAN */ diff --git a/mm/mm_gran/mm_granreserve.c b/mm/mm_gran/mm_granreserve.c index cbb3dad3e31..4930b02d086 100644 --- a/mm/mm_gran/mm_granreserve.c +++ b/mm/mm_gran/mm_granreserve.c @@ -54,13 +54,15 @@ * size - The size of the region to be reserved * * Returned Value: - * None + * On success, a non-NULL pointer to the allocated memory is returned; + * NULL is returned on failure. * ****************************************************************************/ -void gran_reserve(GRAN_HANDLE handle, uintptr_t start, size_t size) +FAR void *gran_reserve(GRAN_HANDLE handle, uintptr_t start, size_t size) { FAR struct gran_s *priv = (FAR struct gran_s *)handle; + FAR void *ret = NULL; DEBUGASSERT(priv != NULL); @@ -81,10 +83,20 @@ void gran_reserve(GRAN_HANDLE handle, uintptr_t start, size_t size) ngranules = ((end - start) >> priv->log2gran) + 1; + /* Must lock the granule allocator */ + + if (gran_enter_critical(priv) < 0) + { + return NULL; + } + /* And reserve the granules */ - gran_mark_allocated(priv, start, ngranules); + ret = gran_mark_allocated(priv, start, ngranules); + gran_leave_critical(priv); } + + return ret; } #endif /* CONFIG_GRAN */ diff --git a/mm/mm_gran/mm_pgalloc.c b/mm/mm_gran/mm_pgalloc.c index 915e2419e4a..369b057de97 100644 --- a/mm/mm_gran/mm_pgalloc.c +++ b/mm/mm_gran/mm_pgalloc.c @@ -123,7 +123,8 @@ void mm_pginitialize(FAR void *heap_start, size_t heap_size) void mm_pgreserve(uintptr_t start, size_t size) { - gran_reserve(g_pgalloc, start, size); + FAR void * ret = gran_reserve(g_pgalloc, start, size); + DEBUGASSERT(ret != NULL); } /****************************************************************************