diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-05-08 00:20:44 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-05-08 00:20:44 +0000 |
commit | 0a30a23cf0bb5a2abf1f02c5f120641e75067fae (patch) | |
tree | ec08393efc9f0fd5ea4e76202b280575500fde42 | |
parent | 77f5bc2c9f37c3e15e1ea07f0954d61c65210e6a (diff) | |
download | nuttx-0a30a23cf0bb5a2abf1f02c5f120641e75067fae.tar.gz nuttx-0a30a23cf0bb5a2abf1f02c5f120641e75067fae.tar.bz2 nuttx-0a30a23cf0bb5a2abf1f02c5f120641e75067fae.zip |
More RAM mapping logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3577 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r-- | nuttx/fs/mmap/fs_munmap.c | 69 | ||||
-rw-r--r-- | nuttx/fs/mmap/fs_rammap.c | 121 | ||||
-rw-r--r-- | nuttx/fs/mmap/fs_rammap.h | 19 |
3 files changed, 204 insertions, 5 deletions
diff --git a/nuttx/fs/mmap/fs_munmap.c b/nuttx/fs/mmap/fs_munmap.c index e42450458..df0f471ac 100644 --- a/nuttx/fs/mmap/fs_munmap.c +++ b/nuttx/fs/mmap/fs_munmap.c @@ -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 */ diff --git a/nuttx/fs/mmap/fs_rammap.c b/nuttx/fs/mmap/fs_rammap.c index 91f753cd0..4136882af 100644 --- a/nuttx/fs/mmap/fs_rammap.c +++ b/nuttx/fs/mmap/fs_rammap.c @@ -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 */ diff --git a/nuttx/fs/mmap/fs_rammap.h b/nuttx/fs/mmap/fs_rammap.h index c8eba76b6..db19f215c 100644 --- a/nuttx/fs/mmap/fs_rammap.h +++ b/nuttx/fs/mmap/fs_rammap.h @@ -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 ****************************************************************************/ |