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);
 }
 
 /****************************************************************************

Reply via email to