mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 08:38:38 +08:00
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:
parent
365a11a5ec
commit
36a7f0be04
12 changed files with 404 additions and 118 deletions
|
@ -10,7 +10,7 @@
|
|||
<td>
|
||||
<h1><big><font color="#3c34ec"><i>NXFLAT</i></font></big></h1>
|
||||
<h2><font color="#dc143c">>>> Under Construction <<<</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.
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 "mqName." 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><time.h><code>.
|
||||
The particular clock, <code>clock_id</code>, is defined in <code><time.h></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 "mapped" 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 "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).
|
||||
</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>
|
||||
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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
78
fs/mmap/README.txt
Executable 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.
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue