More RAM mapping logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3577 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-05-08 00:20:44 +00:00
parent 248af62f80
commit 365a11a5ec
3 changed files with 204 additions and 5 deletions

View File

@ -105,10 +105,73 @@
*
****************************************************************************/
int munmap(FART void *start, size_t length)
int munmap(FAR void *start, size_t length)
{
#warning "Missing logic"
return MAP_FAILED;
FAR struct fs_rammap_s *prev;
FAR struct fs_rammap_s *curr;
FAR void *newaddr;
int ret;
int err;
/* Find a region containing this start and length in the list of regions */
#warning "Missing semaphore initialization"
ret = sem_wait(g_rammaps.exclsem);
if (ret < 0)
{
return ERROR;
}
/* Seach the list of regions */
for (prev = NULL, curr = g_rammaps.head; 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)
{
fdbg("Region not found\n");
err = EINVAL;
goto errout_with_semaphore;
}
/* There is not yet any support for freeing memory at the beginning of the
* region or for increasing the size of the mapped region.
*/
if (start != curr->addr || length > curr->length)
{
fdbg("Unmapping at offset/Extending not supported\n");
err = ENOSYS;
goto errout_with_semaphore;
}
/* Otherwise, we can simply realloc the region. Since we are reducing
* the size of the region, this should not change the start addres.
*/
if (length < curr->length)
{
newaddr = realloc(curr->addr, length);
DEBUGASSERT(newaddr == curr->addr);
}
sem_post(g_rammaps.exclsem);
return OK;
errout_with_semaphore:
sem_post(g_rammaps.exclsem);
errno = err;
return ERROR;
}
#endif /* CONFIG_FS_RAMMAP */

View File

@ -40,6 +40,8 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <debug.h>
@ -78,8 +80,123 @@
int rammap(int fd, size_t length, off_t offset, FAR void **addr)
{
#warning "Missing logic"
return -ENOSYS;
FAR struct fs_rammap_s *rammap;
FAR uint8_t *alloc;
FAR uint8_t *rdbuffer;
ssize_t nread;
off_t fpos;
int err;
int ret;
/* 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
* file and can be shared by many threads. That is, given a filename a
* thread should be able to open the file, get a file descriptor, and
* call mmap() to get a memory region. Different file descriptors opened
* with the same file path should get the same memory region when mapped.
*
* The design flaw is that I don't have sufficient knowledge to know that
* these different file descriptors map to the same file. So, for the time
* being, a new memory region is created each time that rammap() is called.
* Not very useful!
*/
/* Allocate a region of memory of the specified size */
alloc = (FAR uint8_t *)kmalloc(sizeof(struct fs_rammap_s) + length);
if (!alloc)
{
fdbg("Region allocation failed, length: %d\n", (int)length);
err = ENOMEM;
goto errout;
}
/* Initialize the region */
rammap = (FAR struct fs_rammap_s *)alloc;
memset(rammap, 0, sizeof(struct fs_rammap_s));
rammap->addr = alloc + sizeof(struct fs_rammap_s);
rammap->length = length;
rammap->offset = offset;
/* Seek to the specified file offset */
fpos = lseek(fd, offset, SEEK_SET);
if (fpos == (off_t)-1)
{
/* Seek failed... errno has already been set, but EINVAL is probably
* the correct response.
*/
fdbg("Seek to position %d failed\n", (int)offset);
err = ENOMEM;
goto errout_with_region;
}
/* Read the file data into the memory region */
rdbuffer = rammap->addr;
while (length > 0)
{
nread = read(fd, rdbuffer, length);
if (nread < 0)
{
/* Handle the special case where the read was interrupted by a
* signal.
*/
if (nread != EINTR)
{
/* All other read errors are bad. errno is already set.
* (but maybe should be forced to EINVAL?)
*/
fdbg("Read failed: %d\n", (int)offset);
goto errout_with_errno;
}
/* Check for end of file. */
if (nread == 0)
{
break;
}
/* Increment number of bytes read */
rdbuffer += nread;
length -= nread;
}
}
/* Zero any memory beyond the amount read from the file */
memset(rdbuffer, 0, length);
/* Add the buffer to the list of regions */
#warning "Missing semaphore initialization"
ret = sem_wait(g_rammaps.exclsem);
if (ret < 0)
{
goto errout_with_errno;
}
rammap->flink = g_rammaps.head;
g_rammaps.head = rammap;
sem_post(g_rammaps.exclsem);
return rammap->addr;
errout_with_region:
kfree(alloc);
errout:
errno = err;
return MAP_FAILED;
errout_with_errno:
kfree(alloc)
returm MAP_FAILED;
}
#endif /* CONFIG_FS_RAMMAP */

View File

@ -44,6 +44,9 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <semaphore.h>
#ifdef CONFIG_FS_RAMMAP
/****************************************************************************
@ -68,12 +71,28 @@
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 */
};
/* This structure defines all "mapped" files */
struct fs_allmaps_s
{
sem_t exclsem; /* Provides exclusive access the list */
struct fs_rammap_s *maps; /* List of mapped files */
};
/****************************************************************************
* Public Variables
****************************************************************************/
/* This is the list of all mapped files */
extern struct fs_allmaps_s g_rammaps;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/