Skip to content

Commit

Permalink
mm/gran: Allow run-time execution of gran_reserve
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pussuw authored and pkarashchenko committed Nov 22, 2022
1 parent 5c1b518 commit 458ff38
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 25 deletions.
5 changes: 3 additions & 2 deletions include/nuttx/mm/gran.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 4 additions & 3 deletions mm/mm_gran/mm_gran.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
44 changes: 28 additions & 16 deletions mm/mm_gran/mm_granmark.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 */
18 changes: 15 additions & 3 deletions mm/mm_gran/mm_granreserve.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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 */
3 changes: 2 additions & 1 deletion mm/mm_gran/mm_pgalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/****************************************************************************
Expand Down

0 comments on commit 458ff38

Please sign in to comment.