This is an automated email from the ASF dual-hosted git repository. pkarashchenko pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 458ff380e5fd7578db5faf74c82d4dccceb8a8c4 Author: Ville Juven <ville.ju...@unikie.com> AuthorDate: Thu Nov 17 13:39:17 2022 +0200 mm/gran: Allow run-time execution of gran_reserve User can ask for specific granules to be allocated. This is useful for one thing only: when mmap() is called for a specific vaddr. The parameter itself is non-sensical, this is just to satisfy the POSIX standard. --- include/nuttx/mm/gran.h | 5 +++-- mm/mm_gran/mm_gran.h | 7 ++++--- mm/mm_gran/mm_granmark.c | 44 ++++++++++++++++++++++++++++---------------- mm/mm_gran/mm_granreserve.c | 18 +++++++++++++++--- mm/mm_gran/mm_pgalloc.c | 3 ++- 5 files changed, 52 insertions(+), 25 deletions(-) diff --git a/include/nuttx/mm/gran.h b/include/nuttx/mm/gran.h index d515a1c3ca..30940efb84 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 b9fe04beba..3ef67916d3 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 05d60f9ae0..634778b414 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); - - priv->gat[gatidx] |= gatmask; + gatmask = 0xffffffff << gatbit; ngranules -= avail; + gatmask2 = 0xffffffff >> (32 - ngranules); + + /* Check that the area is free, from both mask words */ - /* Mark bits in the second GAT entry */ + if (((priv->gat[gatidx] & gatmask) != 0) || + ((priv->gat[gatidx + 1] & gatmask2) != 0)) + { + return NULL; + } - gatmask = 0xffffffff >> (32 - ngranules); - DEBUGASSERT((priv->gat[gatidx + 1] & gatmask) == 0); + /* Mark bits in the first and second GAT entry */ - priv->gat[gatidx + 1] |= gatmask; + priv->gat[gatidx] |= 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 cbb3dad3e3..4930b02d08 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 915e2419e4..369b057de9 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); } /****************************************************************************