Move rammaps to use mm_map list
Signed-off-by: Jukka Laitinen <jukkax@ssrc.tii.ae>
This commit is contained in:
parent
a5ed8014e8
commit
b8f23fc3f7
@ -135,7 +135,7 @@ static int file_mmap_(FAR struct file *filep, FAR void *start,
|
||||
* do much better in the KERNEL build using the MMU.
|
||||
*/
|
||||
|
||||
return rammap(filep, length, offset, kernel, mapped);
|
||||
return rammap(filep, &entry, kernel);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ static int file_mmap_(FAR struct file *filep, FAR void *start,
|
||||
* do much better in the KERNEL build using the MMU.
|
||||
*/
|
||||
|
||||
return rammap(filep, length, offset, kernel, mapped);
|
||||
return rammap(filep, &entry, kernel);
|
||||
#else
|
||||
ferr("ERROR: mmap not supported \n");
|
||||
return -ENOSYS;
|
||||
|
@ -44,122 +44,6 @@
|
||||
|
||||
static int file_munmap_(FAR void *start, size_t length, bool kernel)
|
||||
{
|
||||
#ifdef CONFIG_FS_RAMMAP
|
||||
FAR struct fs_rammap_s *prev;
|
||||
FAR struct fs_rammap_s *curr;
|
||||
FAR void *newaddr;
|
||||
unsigned int offset;
|
||||
int ret;
|
||||
|
||||
/* Find a region containing this start and length in the list of regions */
|
||||
|
||||
ret = nxmutex_lock(&g_rammaps.lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Search the list of regions */
|
||||
|
||||
for (prev = NULL, curr = g_rammaps.head; curr;
|
||||
prev = curr, curr = curr->flink)
|
||||
{
|
||||
/* Does this region include any part of the specified range? */
|
||||
|
||||
if ((uintptr_t)start < (uintptr_t)curr->addr + curr->length &&
|
||||
(uintptr_t)start + length >= (uintptr_t)curr->addr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we find the region */
|
||||
|
||||
if (!curr)
|
||||
{
|
||||
ferr("ERROR: Region not found\n");
|
||||
ret = -EINVAL;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* Get the offset from the beginning of the region and the actual number
|
||||
* of bytes to "unmap". All mappings must extend to the end of the region.
|
||||
* There is no support for free a block of memory but leaving a block of
|
||||
* memory at the end. This is a consequence of using kumm_realloc() to
|
||||
* simulate the unmapping.
|
||||
*/
|
||||
|
||||
offset = start - curr->addr;
|
||||
if (offset + length < curr->length)
|
||||
{
|
||||
ferr("ERROR: Cannot umap without unmapping to the end\n");
|
||||
ret = -ENOSYS;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* Okay.. the region is beging umapped to the end. Make sure the length
|
||||
* indicates that.
|
||||
*/
|
||||
|
||||
length = curr->length - offset;
|
||||
|
||||
/* Are we unmapping the entire region (offset == 0)? */
|
||||
|
||||
if (length >= curr->length)
|
||||
{
|
||||
/* Yes.. remove the mapping from the list */
|
||||
|
||||
if (prev)
|
||||
{
|
||||
prev->flink = curr->flink;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_rammaps.head = curr->flink;
|
||||
}
|
||||
|
||||
/* Then free the region */
|
||||
|
||||
if (kernel)
|
||||
{
|
||||
kmm_free(curr);
|
||||
}
|
||||
else
|
||||
{
|
||||
kumm_free(curr);
|
||||
}
|
||||
}
|
||||
|
||||
/* No.. We have been asked to "unmap' only a portion of the memory
|
||||
* (offset > 0).
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
if (kernel)
|
||||
{
|
||||
newaddr = kmm_realloc(curr->addr,
|
||||
sizeof(struct fs_rammap_s) + length);
|
||||
}
|
||||
else
|
||||
{
|
||||
newaddr = kumm_realloc(curr->addr,
|
||||
sizeof(struct fs_rammap_s) + length);
|
||||
}
|
||||
|
||||
DEBUGASSERT(newaddr == (FAR void *)(curr->addr));
|
||||
UNUSED(newaddr); /* May not be used */
|
||||
curr->length = length;
|
||||
}
|
||||
|
||||
nxmutex_unlock(&g_rammaps.lock);
|
||||
return OK;
|
||||
|
||||
errout_with_lock:
|
||||
nxmutex_unlock(&g_rammaps.lock);
|
||||
return ret;
|
||||
#else
|
||||
|
||||
FAR struct tcb_s *tcb = nxsched_self();
|
||||
FAR struct task_group_s *group = tcb->group;
|
||||
FAR struct mm_map_entry_s *entry = NULL;
|
||||
@ -185,7 +69,6 @@ errout_with_lock:
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif /* CONFIG_FS_RAMMAP */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -23,9 +23,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@ -35,7 +33,6 @@
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include "inode/inode.h"
|
||||
#include "fs_rammap.h"
|
||||
|
||||
#ifdef CONFIG_FS_RAMMAP
|
||||
@ -44,12 +41,83 @@
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the list of all mapped files */
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
struct fs_allmaps_s g_rammaps =
|
||||
static int unmap_rammap(FAR struct task_group_s *group,
|
||||
FAR struct mm_map_entry_s *entry,
|
||||
FAR void *start,
|
||||
size_t length)
|
||||
{
|
||||
NXMUTEX_INITIALIZER
|
||||
};
|
||||
FAR void *newaddr;
|
||||
unsigned int offset;
|
||||
bool kernel = entry->priv.i != 0 ? true : false;
|
||||
int ret;
|
||||
|
||||
/* Get the offset from the beginning of the region and the actual number
|
||||
* of bytes to "unmap". All mappings must extend to the end of the region.
|
||||
* There is no support for freeing a block of memory but leaving a block of
|
||||
* memory at the end. This is a consequence of using kumm_realloc() to
|
||||
* simulate the unmapping.
|
||||
*/
|
||||
|
||||
offset = start - entry->vaddr;
|
||||
if (offset + length < entry->length)
|
||||
{
|
||||
ferr("ERROR: Cannot umap without unmapping to the end\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* Okay.. the region is being unmapped to the end. Make sure the length
|
||||
* indicates that.
|
||||
*/
|
||||
|
||||
length = entry->length - offset;
|
||||
|
||||
/* Are we unmapping the entire region (offset == 0)? */
|
||||
|
||||
if (length >= entry->length)
|
||||
{
|
||||
/* Free the region */
|
||||
|
||||
if (kernel)
|
||||
{
|
||||
kmm_free(entry->vaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
kumm_free(entry->vaddr);
|
||||
}
|
||||
|
||||
/* Then remove the mapping from the list */
|
||||
|
||||
ret = mm_map_remove(get_group_mm(group), entry);
|
||||
}
|
||||
|
||||
/* No.. We have been asked to "unmap' only a portion of the memory
|
||||
* (offset > 0).
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
if (kernel)
|
||||
{
|
||||
newaddr = kmm_realloc(entry->vaddr, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
newaddr = kumm_realloc(entry->vaddr, length);
|
||||
}
|
||||
|
||||
DEBUGASSERT(newaddr == entry->vaddr);
|
||||
UNUSED(newaddr); /* May not be used */
|
||||
entry->length = length;
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -81,15 +149,14 @@ struct fs_allmaps_s g_rammaps =
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rammap(FAR struct file *filep, size_t length,
|
||||
off_t offset, bool kernel, FAR void **mapped)
|
||||
int rammap(FAR struct file *filep, FAR struct mm_map_entry_s *entry,
|
||||
bool kernel)
|
||||
{
|
||||
FAR struct fs_rammap_s *map;
|
||||
FAR uint8_t *alloc;
|
||||
FAR uint8_t *rdbuffer;
|
||||
ssize_t nread;
|
||||
off_t fpos;
|
||||
int ret;
|
||||
size_t length = entry->length;
|
||||
|
||||
/* There is a major design flaw that I have not yet thought of fix for:
|
||||
* The goal is to have a single region of memory that represents a single
|
||||
@ -106,40 +173,29 @@ int rammap(FAR struct file *filep, size_t length,
|
||||
|
||||
/* Allocate a region of memory of the specified size */
|
||||
|
||||
alloc = kernel ?
|
||||
kmm_malloc(sizeof(struct fs_rammap_s) + length) :
|
||||
kumm_malloc(sizeof(struct fs_rammap_s) + length);
|
||||
if (!alloc)
|
||||
rdbuffer = kernel ? kmm_malloc(length) : kumm_malloc(length);
|
||||
if (!rdbuffer)
|
||||
{
|
||||
ferr("ERROR: Region allocation failed, length: %d\n", (int)length);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Initialize the region */
|
||||
|
||||
map = (FAR struct fs_rammap_s *)alloc;
|
||||
memset(map, 0, sizeof(struct fs_rammap_s));
|
||||
map->addr = alloc + sizeof(struct fs_rammap_s);
|
||||
map->length = length;
|
||||
map->offset = offset;
|
||||
|
||||
/* Seek to the specified file offset */
|
||||
|
||||
fpos = file_seek(filep, offset, SEEK_SET);
|
||||
fpos = file_seek(filep, entry->offset, SEEK_SET);
|
||||
if (fpos < 0)
|
||||
{
|
||||
/* Seek failed... errno has already been set, but EINVAL is probably
|
||||
* the correct response.
|
||||
*/
|
||||
|
||||
ferr("ERROR: Seek to position %d failed\n", (int)offset);
|
||||
ferr("ERROR: Seek to position %d failed\n", (int)entry->offset);
|
||||
ret = fpos;
|
||||
goto errout_with_region;
|
||||
}
|
||||
|
||||
/* Read the file data into the memory region */
|
||||
|
||||
rdbuffer = map->addr;
|
||||
while (length > 0)
|
||||
{
|
||||
nread = file_read(filep, rdbuffer, length);
|
||||
@ -154,7 +210,7 @@ int rammap(FAR struct file *filep, size_t length,
|
||||
/* All other read errors are bad. */
|
||||
|
||||
ferr("ERROR: Read failed: offset=%d ret=%d\n",
|
||||
(int)offset, (int)nread);
|
||||
(int)entry->offset, (int)nread);
|
||||
|
||||
ret = nread;
|
||||
goto errout_with_region;
|
||||
@ -180,27 +236,26 @@ int rammap(FAR struct file *filep, size_t length,
|
||||
|
||||
/* Add the buffer to the list of regions */
|
||||
|
||||
ret = nxmutex_lock(&g_rammaps.lock);
|
||||
entry->vaddr = rdbuffer;
|
||||
entry->priv.i = kernel ? 1 : 0;
|
||||
entry->munmap = unmap_rammap;
|
||||
|
||||
ret = mm_map_add(entry);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_region;
|
||||
}
|
||||
|
||||
map->flink = g_rammaps.head;
|
||||
g_rammaps.head = map;
|
||||
|
||||
nxmutex_unlock(&g_rammaps.lock);
|
||||
*mapped = map->addr;
|
||||
return OK;
|
||||
|
||||
errout_with_region:
|
||||
if (kernel)
|
||||
{
|
||||
kmm_free(alloc);
|
||||
kmm_free(rdbuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
kumm_free(alloc);
|
||||
kumm_free(rdbuffer);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -18,25 +18,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __FS_MMAP_FS_RAMMAP_H
|
||||
#define __FS_MMAP_FS_RAMMAP_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <nuttx/mutex.h>
|
||||
|
||||
#ifdef CONFIG_FS_RAMMAP
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure describes one file that has been copied to memory and
|
||||
/* This driver manages files that have been copied to memory and
|
||||
* managed as a share-able "memory mapped" file. This functionality is
|
||||
* intended to provide a substitute for memory mapped files for architectures
|
||||
* that do not have MMUs and, hence, cannot support on demand paging of
|
||||
@ -53,30 +35,28 @@
|
||||
* - There are not access privileges.
|
||||
*/
|
||||
|
||||
struct fs_rammap_s
|
||||
{
|
||||
struct fs_rammap_s *flink; /* Implements a singly linked list */
|
||||
FAR void *addr; /* Start of allocated memory */
|
||||
size_t length; /* Length of region */
|
||||
off_t offset; /* File offset */
|
||||
};
|
||||
#ifndef __FS_MMAP_FS_RAMMAP_H
|
||||
#define __FS_MMAP_FS_RAMMAP_H
|
||||
|
||||
/* This structure defines all "mapped" files */
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
struct fs_allmaps_s
|
||||
{
|
||||
mutex_t lock; /* Provides exclusive access the list */
|
||||
struct fs_rammap_s *head; /* List of mapped files */
|
||||
};
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <nuttx/mm/map.h>
|
||||
|
||||
#ifdef CONFIG_FS_RAMMAP
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the list of all mapped files */
|
||||
|
||||
extern struct fs_allmaps_s g_rammaps;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
@ -107,8 +87,8 @@ extern struct fs_allmaps_s g_rammaps;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rammap(FAR struct file *filep, size_t length,
|
||||
off_t offset, bool kernel, FAR void **mapped);
|
||||
int rammap(FAR struct file *filep, FAR struct mm_map_entry_s *entry,
|
||||
bool kernel);
|
||||
|
||||
#endif /* CONFIG_FS_RAMMAP */
|
||||
#endif /* __FS_MMAP_FS_RAMMAP_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user