diff --git a/Documentation/NuttXNxFlat.html b/Documentation/NuttXNxFlat.html index b08b65801632a78d8f635dd8daefc08e9616ae59..d6ada4e9b7f831b20b2a8aa225a2f4703291b6c8 100644 --- a/Documentation/NuttXNxFlat.html +++ b/Documentation/NuttXNxFlat.html @@ -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. diff --git a/Documentation/NuttxPortingGuide.html b/Documentation/NuttxPortingGuide.html index 70bdab5379e6676bd6857d2bf4e8e6bb2d22c026..8d237f8de5a2d7c5572fd39e5c8cb210420c7251 100644 --- a/Documentation/NuttxPortingGuide.html +++ b/Documentation/NuttxPortingGuide.html @@ -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> diff --git a/Documentation/NuttxUserGuide.html b/Documentation/NuttxUserGuide.html index 53bdad919d169b1ab6bd2015fb35119bcfc48aa7..8e97173114529a87da42f4101df068c4b8b53270 100644 --- a/Documentation/NuttxUserGuide.html +++ b/Documentation/NuttxUserGuide.html @@ -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> diff --git a/Documentation/README.html b/Documentation/README.html index 5c7a89c0426021826f114537905ce6118b466cb2..bb07b883a6424880772ffb655fb707f9e4e26b53 100755 --- a/Documentation/README.html +++ b/Documentation/README.html @@ -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/ diff --git a/README.txt b/README.txt index 240f626eef1089740de2d7e6a3824864405e9489..14d199d9be0d4bee71f5cb6b8313a1a7bc2fc3ab 100755 --- a/README.txt +++ b/README.txt @@ -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/ diff --git a/configs/README.txt b/configs/README.txt index 8f6438ba7ca10878be1c268ab69042e680f7c781..82d83eaf2c26463830d374cc09f90a621189f12b 100644 --- a/configs/README.txt +++ b/configs/README.txt @@ -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 diff --git a/fs/mmap/README.txt b/fs/mmap/README.txt new file mode 100755 index 0000000000000000000000000000000000000000..cf4c51e9e84e30a8a51f535cbd4f0ffc4e24f381 --- /dev/null +++ b/fs/mmap/README.txt @@ -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. diff --git a/fs/mmap/fs_mmap.c b/fs/mmap/fs_mmap.c index 3a69e5167fd22250ab4f795df6312826cec64dd4..5764b16f1ddde9a2a39bafd3cd71632f25ca63e4 100644 --- a/fs/mmap/fs_mmap.c +++ b/fs/mmap/fs_mmap.c @@ -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; } diff --git a/fs/mmap/fs_munmap.c b/fs/mmap/fs_munmap.c index df0f471ac8ecce59c4e50a4c46564efe4fe72947..a4b9dc6091d551a6af403e7a796aa2fbbf05b507 100644 --- a/fs/mmap/fs_munmap.c +++ b/fs/mmap/fs_munmap.c @@ -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. + */ + + 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 */ + + kfree(curr); + } + + /* No.. We have been asked to "unmap' only a portion of the memory + * (offset > 0). */ - if (length < curr->length) + else { - newaddr = realloc(curr->addr, length); - DEBUGASSERT(newaddr == curr->addr); + newaddr = krealloc(curr->addr, sizeof(struct fs_rammap_s) + length); + DEBUGASSERT(newaddr == (FAR void*)(curr->addr)); + curr->length = length; } - sem_post(g_rammaps.exclsem); + sem_post(&g_rammaps.exclsem); return OK; errout_with_semaphore: - sem_post(g_rammaps.exclsem); + sem_post(&g_rammaps.exclsem); errno = err; return ERROR; } diff --git a/fs/mmap/fs_rammap.c b/fs/mmap/fs_rammap.c index 4136882af22364ab0725f7407303ea582241eb2a..0eaf313b5970fde5f0c434902d55b5d69cc333ee 100644 --- a/fs/mmap/fs_rammap.c +++ b/fs/mmap/fs_rammap.c @@ -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 */ diff --git a/fs/mmap/fs_rammap.h b/fs/mmap/fs_rammap.h index db19f215cea491b07a4643299ed755f92ad4adf9..9076d73432958503171624516236f3b8634571cf 100644 --- a/fs/mmap/fs_rammap.h +++ b/fs/mmap/fs_rammap.h @@ -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 */ diff --git a/include/sys/mman.h b/include/sys/mman.h index 81bed9ca252329ed2146281f462dde420d9ffff0..6d220bef107b753cdad276eb2ec8968399c605ea 100644 --- a/include/sys/mman.h +++ b/include/sys/mman.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)