Complets ram mapping logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3578 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-05-08 14:42:42 +00:00
parent 365a11a5ec
commit 36a7f0be04
12 changed files with 404 additions and 118 deletions

View file

@ -10,7 +10,7 @@
<td>
<h1><big><font color="#3c34ec"><i>NXFLAT</i></font></big></h1>
<h2><font color="#dc143c">&gt;&gt;&gt; Under Construction &lt;&lt;&lt;</font></h2>
<p>Last Updated: March 20, 2011</p>
<p>Last Updated: May 8, 2011</p>
</td>
</tr>
</table>
@ -193,10 +193,12 @@
<a name="limitations"><h2>1.3 Limitations</h2></a>
<ul>
<li><b>ROMFS Only</b>.
The initial NXFLAT release will work only with executable modules residing on a ROMFS
file system.
<li><b>ROMFS (or RAM maps) Only</b>.
The initial NXFLAT release will work only with wither (1) executable modules residing on a ROMFS
file system, or (2) executables provided on other file systems provided that <code>CONFIG_FS_RAMMAP</code>
is defined.
That is because the loader depends on the capability to <code>mmap()</code> the code segment.
See the <a href="NuttxUserGuide.html#mmapxip">NuttX User Guide</a> for further information.
NUTTX does not provide any general kind of file mapping capability.
In fact, <i>true </i>file mapping is only possible with RTOSs and MCUs that provide an MMU<sup>1</sup>
and only ROMFS supports that kind of XIP execution from FLASH.

View file

@ -12,7 +12,7 @@
<h1><big><font color="#3c34ec">
<i>NuttX RTOS Porting Guide</i>
</font></big></h1>
<p>Last Updated: May 6, 2011</p>
<p>Last Updated: May 8, 2011</p>
</td>
</tr>
</table>
@ -3480,6 +3480,11 @@ build
<li>
<code>CONFIG_FS_ROMFS</code>: Enable ROMFS file system support
</li>
<li>
<code>CONFIG_FS_RAMMAP</code>: For file systems that do not support
XIP, this option will enable a limited form of memory mapping that is
implemented by copying whole files into memory.
</li>
</ul>
<h2>Device Drivers</h2>

View file

@ -13,7 +13,7 @@
<h1><big><font color="#3c34ec"><i>NuttX Operating System<p>User's Manual</i></font></big></h1>
<p><small>by</small></p>
<p>Gregory Nutt<p>
<p>Last Updated: December 13, 2009</p>
<p>Last Updated: May 8, 2011</p>
</td>
</tr>
</table>
@ -747,10 +747,10 @@ interface of the same name.
priority of the calling task is set.
</li>
<li>
<I>policy</I>. Scheduling policy requested (either SCHED_FIFO or SCHED_RR).
<I>policy</I>. Scheduling policy requested (either <code>SCHED_FIFO</code> or <code>SCHED_RR</code>).
</li>
<li>
<code>param<code>. A structure whose member sched_priority is the
<code>param</code>. A structure whose member sched_priority is the
integer priority. The range of valid priority numbers is from
SCHED_PRIORITY_MIN through SCHED_PRIORITY_MAX.
</li>
@ -1213,7 +1213,7 @@ of the same name.
<p>
<b>Description:</b> This function removes the message queue named
by &quot;mqName.&quot; If one or more tasks have the message queue
open when mq_unlink() is called, removal of the message queue
open when <code>mq_unlink()</code> is called, removal of the message queue
is postponed until all references to the message queue have been
closed.
<p>
@ -1341,7 +1341,7 @@ interface of the same name.
</p>
<p>
If the message queue is full, and the timeout has already expired by the time
of the call, <code>mq_timedsend()<code> returns immediately.
of the call, <code>mq_timedsend()</code> returns immediately.
</p>
<p>
<b>Input Parameters:</b>
@ -1483,8 +1483,8 @@ interface of the same name.
priority that has waited the longest will be unblocked.
</p>
<p>
<code>mq_timedreceive()</code> behaves just like <code>mq_receive()<code>, except
that if the queue is empty and the <code>O_NONBLOCK<c/ode> flag is not enabled
<code>mq_timedreceive()</code> behaves just like <code>mq_receive()</code>, except
that if the queue is empty and the <code>O_NONBLOCK</code> flag is not enabled
for the message queue description, then <code>abstime</code> points to a structure
which specifies a ceiling on the time for which the call will block.
This ceiling is an absolute timeout in seconds and nanoseconds since the Epoch
@ -2681,7 +2681,7 @@ VxWorks provides the following comparable interface:
the location referenced by <code>timerid</code>, a timer ID of type timer_t used to identify
the timer in timer requests.
This timer ID is unique until the timer is deleted.
The particular clock, <code>clock_id<code>, is defined in <code>&lt;time.h&gt;<code>.
The particular clock, <code>clock_id</code>, is defined in <code>&lt;time.h&gt;</code>.
The timer whose ID is returned will be in a disarmed state upon return from
<code>timer_create()</code>.
</p>
@ -4425,7 +4425,7 @@ interface of the same name.
<p>
The policy parameter may have the value <code>SCHED_FIFO</code> or <code>SCHED_RR</code>
(<code>SCHED_OTHER</code> and <code>SCHED_SPORADIC</code>, in particular, are not supported).
The <code>SCHED_FIFO</code> and <code>SCHED_RR<code> policies will have a single
The <code>SCHED_FIFO</code> and <code>SCHED_RR</code> policies will have a single
scheduling parameter, <code>sched_priority</code>.
</p>
<p>
@ -4502,8 +4502,8 @@ interface of the same name.
<li>
<code>policy</code>.
The new scheduling policy of the thread.
Either <code>SCHED_FIFO</code> or <code>SCHED_RR<code>.
<code>SCHED_OTHER<code> and <code>SCHED_SPORADIC<code> are not supported.
Either <code>SCHED_FIFO</code> or <code>SCHED_RR</code>.
<code>SCHED_OTHER</code> and <code>SCHED_SPORADIC</code> are not supported.
</li>
<li>
<code>param</code>.
@ -5141,7 +5141,7 @@ interface of the same name.
<b>Input Parameters:</b>
<p>
<ul>
<li><code>param<code>.</li>
<li><code>mutex</code>.</li>
</ul>
<p>
<b>Returned Values:</b>
@ -6233,7 +6233,7 @@ interface of the same name.
</p>
<ul>
<li><code>CONFIG_NET_TCPBACKLOG</code>
Incoming connections pend in a backlog until <code>accept()</cod> is called.
Incoming connections pend in a backlog until <code>accept()</code> is called.
The size of the backlog is selected when <code>listen()</code> is called.</li>
</ul>
<p>
@ -6505,7 +6505,7 @@ void *memmove(void *dest, const void *src, size_t count);
<li><code>pathname</code>.
The full path to the FIFO instance to attach to or to create (if not already created).
</li>
<li><code>mode<code>.
<li><code>mode</code>.
Ignored for now
</li>
</ul>
@ -6599,26 +6599,132 @@ struct fat_format_s
<h3><a name="mmapxip">2.11.9 <code>mmap()</code> and eXecute In Place (XIP)</a></h3>
<p>
NuttX operates in a flat open address space.
Therefore, it generally does not require <code>mmap()</code> functionality.
There is one one exception:
<code>mmap()</code> is the API that is used to support direct access to random
access media under the following very restrictive conditions:
<ol>
<li>
The file-system supports the <code>FIOC_MMAP</code> ioctl command.
Any file system that maps files contiguously on the media should support this
<code>ioctl</code> command.
By comparison, most file system scatter files over the media in non-contiguous
sectors. As of this writing, ROMFS is the only file system that meets this requirement.
</li>
<li>
The underlying block driver supports the <code>BIOC_XIPBASE</code> <code>ioctl</code> command
that maps the underlying media to a randomly accessible address.
At present, only the RAM/ROM disk driver does this.
</li>
</ol>
NuttX operates in a flat open address space and is focused on MCUs that do
support Memory Management Units (MMUs). Therefore, NuttX generally does not
require <code>mmap()</code> functionality and the MCUs generally cannot support true
memory-mapped files.
</p>
<p>
However, memory mapping of files is the mechanism used by NXFLAT, the NuttX
tiny binary format, to get files into memory in order to execute them.
<code>mmap()</code> support is therefore required to support NXFLAT.
There are two conditions where <code>mmap()</code> can be supported:
</p>
<ol type="1">
<li>
<p>
<code>mmap()</code> can be used to support <i>eXecute In Place</i> (XIP) on random access media
under the following very restrictive conditions:
</p>
<ol type="a">
<li>
<p>
The file-system supports the <code>FIOC_MMAP</code> ioctl command.
Any file system that maps files contiguously on the media should support this
<code>ioctl</code> command.
By comparison, most file system scatter files over the media in non-contiguous
sectors. As of this writing, ROMFS is the only file system that meets this requirement.
</p>
</li>
<li>
<p>
The underlying block driver supports the <code>BIOC_XIPBASE</code> <code>ioctl</code> command
that maps the underlying media to a randomly accessible address.
At present, only the RAM/ROM disk driver does this.
</p>
</li>
</ol>
<p>
Some limitations of this approach are as follows:
<p>
<ol type="a">
<li>
<p>
Since no real mapping occurs, all of the file contents are &quot;mapped&quot; into memory.
</p>
</li>
<li>
<p>
All mapped files are read-only.
</p>
</li>
<li>
<p>
There are no access privileges.
</p>
</li>
</ol>
</li>
<li>
<p>
If <code>CONFIG_FS_RAMMAP</code> is defined in the configuration, then <code>mmap()</code> will
support simulation of memory mapped files by copying files whole into RAM.
These copied files have some of the properties of standard memory mapped files.
There are many, many exceptions exceptions, however.
Some of these include:
</p>
<ol type="a">
<li>
<p>
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 <code>mmap()</code> to get a memory region. Different file descriptors opened
with the same file path should get the same memory region when mapped.
</p>
<p>
The limitation in the current design is that there is insufficient
knowledge to know that these different file descriptors correspond to
the same file. So, for the time being, a new memory region is created
each time that <code>rammmap()</code> is called. Not very useful!
</p>
</li>
<li>
<p>
The entire mapped portion of the file must be present in memory.
Since it is assumed the the MCU does not have an MMU, on-demanding
paging in of file blocks cannot be supported. Since the while mapped
portion of the file must be present in memory, there are limitations
in the size of files that may be memory mapped (especially on MCUs
with no significant RAM resources).
</p>
</li>
<li>
<p>
All mapped files are read-only. You can write to the in-memory image,
but the file contents will not change.
</p>
</li>
<li>
<p>
There are no access privileges.
</p>
</li>
<li>
<p>
Since there are no processes in NuttX, all <code>mmap()</code> and <code>munmap()</code>
operations have immediate, global effects. Under Linux, for example,
<code>munmap()</code> would eliminate only the mapping with a process; the mappings
to the same file in other processes would not be effected.
</p>
</li>
<li>
<p>
Like true mapped file, the region will persist after closing the file
descriptor. However, at present, these ram copied file regions are
<i>not</i> automatically &quot;unmapped&quot; (i.e., freed) when a thread is terminated.
This is primarily because it is not possible to know how many users
of the mapped region there are and, therefore, when would be the
appropriate time to free the region (other than when munmap is called).
</p>
<p>
NOTE: Note, if the design limitation of a) were solved, then it would be
easy to solve exception d) as well.
</p>
</li>
</ol>
</li>
</ol>
<h3><a name="mmap">2.11.9.1 <code>mmap</code></a></h3>
<p>
@ -6952,7 +7058,7 @@ Those socket APIs are discussed in the following paragraphs.</p>
To accept connections, a socket is first created with <code>socket()</code>, a
willingness to accept incoming connections and a queue limit for incoming
connections are specified with <code>listen()</code>, and then the connections are
accepted with <code>accept()</code>. The <code>listen()</coe> call applies only to sockets of
accepted with <code>accept()</code>. The <code>listen()</code> call applies only to sockets of
type <code>SOCK_STREAM</code> or <code>SOCK_SEQPACKET</code>.
</p>
<p>
@ -7280,11 +7386,11 @@ Those socket APIs are discussed in the following paragraphs.</p>
<b>Input Parameters:</b>
</p>
<ul>
<li><code>sockfd</code>: Socket descriptor of socket
<li><code>level</code>: Protocol level to set the option
<li><code>option</code>: identifies the option to set
<li><code>value</code>: Points to the argument value
<li><code>value_len</code>: The length of the argument value
<li><code>sockfd</code>: Socket descriptor of socket</li>
<li><code>level</code>: Protocol level to set the option</li>
<li><code>option</code>: identifies the option to set</li>
<li><code>value</code>: Points to the argument value</li>
<li><code>value_len</code>: The length of the argument value</li>
</ul>
<p>
<b>Returned Values:</b>
@ -7337,17 +7443,17 @@ Those socket APIs are discussed in the following paragraphs.</p>
SOL_SOCKET.
</p>
<p>
See <code>sys/socket.h</code>for a complete list of values for the <code>option</code> argument.
See <code>sys/socket.h</code> for a complete list of values for the <code>option</code> argument.
</p>
<p>
<b>Input Parameters:</b>
</p>
<ul>
<li><code>sockfd Socket descriptor of socket
<li><code>level Protocol level to set the option
<li><code>option identifies the option to get
<li><code>value Points to the argument value
<li><code>value_len The length of the argument value
<li><code>sockfd</code>: Socket descriptor of socket
<li><code>level</code>: Protocol level to set the option
<li><code>option</code>: Identifies the option to get
<li><code>value</code>: Points to the argument value
<li><code>value_len</code>: The length of the argument value
</ul>
<p>
<b>Returned Values:</b>
@ -7364,7 +7470,7 @@ Those socket APIs are discussed in the following paragraphs.</p>
The <code>option</code> is not supported by the protocol.</li>
<li><code>NOTSOCK</code>.
The <code>sockfd</code> argument does not refer to a socket.</li>
<li><code>NOBUFS
<li><code>NOBUFS</code>.
Insufficient resources are available in the system to complete the call.</li>
</ul>

View file

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX README Files</i></font></big></h1>
<p>Last Updated: April 15, 2010</p>
<p>Last Updated: May 7, 2010</p>
</td>
</tr>
</table>
@ -167,6 +167,8 @@
| |- drivers/
| | `- <a href="http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/nuttx/drivers/README.txt?view=log"><b><i>README.txt</i></b></a>
| |- fs/
| | |- mmap/
| | | `- <a href="http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/nuttx/fs/mmap/README.txt?view=log"><b><i>README.txt</i></b></a>
| | `- nxffs/
| | `- <a href="http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/nuttx/fs/nxffs/README.txt?view=log"><b><i>README.txt</i></b></a>
| |- graphics/

View file

@ -416,6 +416,8 @@ Below is a guide to the available README files in the NuttX source tree:
| |- pashello/README.txt
| `- README.txt
|- fs/
| |- mmap/
| | `- README.txt
| `- nxffs/
| `- README.txt
|- graphics/

View file

@ -540,6 +540,9 @@ defconfig -- This is a configuration file similar to the Linux
and making it available for re-use (and possible over-wear).
Default: 8192.
CONFIG_FS_ROMFS - Enable ROMFS filesystem support
CONFIG_FS_RAMMAP - For file systems that do not support XIP, this
option will enable a limited form of memory mapping that is
implemented by copying whole files into memory.
SPI driver
CONFIG_SPI_OWNBUS - Set if there is only one active device

78
fs/mmap/README.txt Executable file
View file

@ -0,0 +1,78 @@
fs/mmap README File
===================
NuttX operates in a flat open address space and is focused on MCUs that do
support Memory Management Units (MMUs). Therefore, NuttX generally does not
require mmap() functionality and the MCUs generally cannot support true
memory-mapped files.
However, memory mapping of files is the mechanism used by NXFLAT, the NuttX
tiny binary format, to get files into memory in order to execute them.
mmap() support is therefore required to support NXFLAT. There are two
conditions where mmap() can be supported:
1. mmap can be used to support eXecute In Place (XIP) on random access media
under the following very restrictive conditions:
a. The filesystem supports the FIOC_MMAP ioctl command. Any file
system that maps files contiguously on the media should support
this ioctl. (vs. file system that scatter files over the media
in non-contiguous sectors). As of this writing, ROMFS is the
only file system that meets this requirement.
b. The underlying block driver supports the BIOC_XIPBASE ioctl
command that maps the underlying media to a randomly accessible
address. At present, only the RAM/ROM disk driver does this.
Some limitations of this approach are as follows:
a. Since no real mapping occurs, all of the file contents are "mapped"
into memory.
b. All mapped files are read-only.
c. There are no access privileges.
2. If CONFIG_FS_RAMMAP is defined in the configuration, then mmap() will
support simulation of memory mapped files by copying files whole
into RAM. These copied files have some of the properties of
standard memory mapped files. There are many, many exceptions
exceptions, however. Some of these include:
a. 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 limitation in the current design is that there is insufficient
knowledge to know that these different file descriptors correspond to
the same file. So, for the time being, a new memory region is created
each time that rammap() is called. Not very useful!
b. The entire mapped portion of the file must be present in memory.
Since it is assumed the the MCU does not have an MMU, on-demanding
paging in of file blocks cannot be supported. Since the while mapped
portion of the file must be present in memory, there are limitations
in the size of files that may be memory mapped (especially on MCUs
with no significant RAM resources).
c. All mapped files are read-only. You can write to the in-memory image,
but the file contents will not change.
d. There are no access privileges.
e. Since there are no processes in NuttX, all mmap() and munmap()
operations have immediate, global effects. Under Linux, for example,
munmap() would eliminate only the mapping with a process; the mappings
to the same file in other processes would not be effected.
f. Like true mapped file, the region will persist after closing the file
descriptor. However, at present, these ram copied file regions are
*not* automatically "unmapped" (i.e., freed) when a thread is terminated.
This is primarily because it is not possible to know how many users
of the mapped region there are and, therefore, when would be the
appropriate time to free the region (other than when munmap is called).
NOTE: Note, if the design limitation of a) were solved, then it would be
easy to solve exception d) as well.

View file

@ -47,6 +47,7 @@
#include <debug.h>
#include "fs_internal.h"
#include "fs_rammap.h"
/****************************************************************************
* Global Functions
@ -135,16 +136,15 @@ FAR void *mmap(FAR void *start, size_t length, int prot, int flags,
(flags & (MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_DENYWRITE)) != 0)
{
fdbg("Unsupported options, prot=%x flags=%04x\n", prot, flags);
ret = ENOSYS;
goto errout_with_ret;
errno = ENOSYS;
return MAP_FAILED;
}
if (length == 0 ||
(flags & MAP_SHARED) == 0)
if (length == 0 || (flags & MAP_SHARED) == 0)
{
fdbg("Invalid options, lengt=%d flags=%04x\n", length, flags);
ret = EINVAL;
goto errout_with_ret;
errno = EINVAL;
return MAP_FAILED;
}
#endif
@ -161,24 +161,14 @@ FAR void *mmap(FAR void *start, size_t length, int prot, int flags,
if (ret < 0)
{
#ifdef CONFIG_FS_RAMMAP
ret = rammap(fd, length, offset, &addr);
if (ret < 0)
return rammap(fd, length, offset);
#else
fdbg("ioctl(FIOC_MMAP) failed: %d\n", errno);
return MAP_FAILED;
#endif
{
fdbg("ioctl(FIOC_MMAP) failed: %d\n", errno);
goto errout;
}
}
/* Return the offset address */
return (void*)(((uint8_t*)addr) + offset);
#ifdef CONFIG_DEBUG
errout_with_ret:
errno = ret;
#endif
errout:
return MAP_FAILED;
}

View file

@ -44,9 +44,13 @@
#include <stdint.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include "fs_internal.h"
#include "fs_rammap.h"
#ifdef CONFIG_FS_RAMMAP
@ -60,8 +64,8 @@
* Description:
*
* munmap() system call deletes mappings for the specified address range.
* The region is also automatically unmapped when the process is terminated.
* On the other hand, closing the file descriptor does not unmap the region.
* All memory starting with 'start' and continuing for a length of 'length'
* bytes are removed.
*
* NuttX operates in a flat open address space. Therefore, it generally
* does not require mmap() and, hence, munmap functionality. There are
@ -96,8 +100,7 @@
* simplified munmap() implementation, the *must* be the start
* address of the memory region (the same address returned by
* mmap()).
* length The length region to be umapped. Ignored. The entire underlying
* media is always freed.
* length The length region to be umapped.
*
* Returned Value:
* On success, munmap() returns 0, on failure -1, and errno is set
@ -110,13 +113,14 @@ int munmap(FAR void *start, size_t length)
FAR struct fs_rammap_s *prev;
FAR struct fs_rammap_s *curr;
FAR void *newaddr;
unsigned int offset;
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);
rammap_initialize();
ret = sem_wait(&g_rammaps.exclsem);
if (ret < 0)
{
return ERROR;
@ -124,7 +128,7 @@ int munmap(FAR void *start, size_t length)
/* Seach the list of regions */
for (prev = NULL, curr = g_rammaps.head; prev = curr, curr = curr->flink)
for (prev = NULL, curr = g_rammaps.head; curr; prev = curr, curr = curr->flink)
{
/* Does this region include any part of the specified range? */
@ -144,32 +148,63 @@ int munmap(FAR void *start, size_t length)
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.
/* 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 realloc() to
* simulate the unmapping.
*/
if (start != curr->addr || length > curr->length)
offset = start - curr->addr;
if (offset + length < curr->length)
{
fdbg("Unmapping at offset/Extending not supported\n");
fdbg("Cannot umap without unmapping to the end\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.
/* Okay.. the region is beging umapped to the end. Make sure the length
* indicates that.
*/
if (length < curr->length)
length = curr->length - offset;
/* Are we unmapping the entire region (offset == 0)? */
if (length >= curr->length)
{
newaddr = realloc(curr->addr, length);
DEBUGASSERT(newaddr == curr->addr);
/* Yes.. remove the mapping from the list */
if (prev)
{
prev->flink = curr->flink;
}
else
{
g_rammaps.head = curr->flink;
}
/* Then free the region */
kfree(curr);
}
sem_post(g_rammaps.exclsem);
/* No.. We have been asked to "unmap' only a portion of the memory
* (offset > 0).
*/
else
{
newaddr = krealloc(curr->addr, sizeof(struct fs_rammap_s) + length);
DEBUGASSERT(newaddr == (FAR void*)(curr->addr));
curr->length = length;
}
sem_post(&g_rammaps.exclsem);
return OK;
errout_with_semaphore:
sem_post(g_rammaps.exclsem);
sem_post(&g_rammaps.exclsem);
errno = err;
return ERROR;
}

View file

@ -40,19 +40,55 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include "fs_internal.h"
#include "fs_rammap.h"
#ifdef CONFIG_FS_RAMMAP
/****************************************************************************
* Global Data
****************************************************************************/
/* This is the list of all mapped files */
struct fs_allmaps_s g_rammaps;
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: rammap_initialize
*
* Description:
* Verified that this capability has been initialized.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void rammap_initialize(void)
{
if (!g_rammaps.initialized)
{
sem_init(&g_rammaps.exclsem, 0, 1);
g_rammaps.initialized = true;
}
}
/****************************************************************************
* Name: rammmap
*
@ -78,9 +114,9 @@
*
****************************************************************************/
int rammap(int fd, size_t length, off_t offset, FAR void **addr)
FAR void *rammap(int fd, size_t length, off_t offset)
{
FAR struct fs_rammap_s *rammap;
FAR struct fs_rammap_s *map;
FAR uint8_t *alloc;
FAR uint8_t *rdbuffer;
ssize_t nread;
@ -113,11 +149,11 @@ int rammap(int fd, size_t length, off_t offset, FAR void **addr)
/* 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;
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 */
@ -135,7 +171,7 @@ int rammap(int fd, size_t length, off_t offset, FAR void **addr)
/* Read the file data into the memory region */
rdbuffer = rammap->addr;
rdbuffer = map->addr;
while (length > 0)
{
nread = read(fd, rdbuffer, length);
@ -175,18 +211,18 @@ int rammap(int fd, size_t length, off_t offset, FAR void **addr)
/* Add the buffer to the list of regions */
#warning "Missing semaphore initialization"
ret = sem_wait(g_rammaps.exclsem);
rammap_initialize();
ret = sem_wait(&g_rammaps.exclsem);
if (ret < 0)
{
goto errout_with_errno;
}
rammap->flink = g_rammaps.head;
g_rammaps.head = rammap;
map->flink = g_rammaps.head;
g_rammaps.head = map;
sem_post(g_rammaps.exclsem);
return rammap->addr;
sem_post(&g_rammaps.exclsem);
return map->addr;
errout_with_region:
kfree(alloc);
@ -195,8 +231,8 @@ errout:
return MAP_FAILED;
errout_with_errno:
kfree(alloc)
returm MAP_FAILED;
kfree(alloc);
return MAP_FAILED;
}
#endif /* CONFIG_FS_RAMMAP */

View file

@ -64,25 +64,31 @@
* blocks of a file.
*
* This copied file has many of the properties of a standard memory mapped
* file except for all of the file must be present in memory. This limits
* the size of files that may be memory mapped (especially on MCUs with
* no significant RAM resources).
* file except:
*
* - All of the file must be present in memory. This limits the size of
* files that may be memory mapped (especially on MCUs with no significant
* RAM resources).
* - All mapped files are read-only. You can write to the in-memory image,
* but the file contents will not change.
* - 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 */
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 */
bool initialized; /* True: This structure has been initialized */
sem_t exclsem; /* Provides exclusive access the list */
struct fs_rammap_s *head; /* List of mapped files */
};
/****************************************************************************
@ -97,6 +103,22 @@ extern struct fs_allmaps_s g_rammaps;
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: rammap_initialize
*
* Description:
* Verified that this capability has been initialized.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
extern void rammap_initialize(void);
/****************************************************************************
* Name: rammmap
*
@ -122,7 +144,7 @@ extern struct fs_allmaps_s g_rammaps;
*
****************************************************************************/
extern int rammap(int fd, size_t length, off_t offset, FAR void **addr);
extern FAR void *rammap(int fd, size_t length, off_t offset);
#endif /* CONFIG_FS_RAMMAP */
#endif /* __FS_MMAP_RAMMAP_H */

View file

@ -1,7 +1,7 @@
/****************************************************************************
* include/sys/mman.h
*
* Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved.
* Copyright (C) 2008, 2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@ -98,7 +98,12 @@ extern "C" {
EXTERN FAR void *mmap(FAR void *start, size_t length, int prot, int flags,
int fd, off_t offset);
#define munmap(start, length)
#ifdef CONFIG_FS_RAMMAP
EXTERN int munmap(FAR void *start, size_t length);
#else
# define munmap(start, length)
#endif
#undef EXTERN
#if defined(__cplusplus)