[PATCH 6/6] posix/mmap: update for MAP_FIXED

Gedare Bloom gedare at rtems.org
Fri Mar 31 20:47:04 UTC 2017


Updates #2859.
---
 cpukit/posix/src/mmap.c | 42 ++++++++++++++++++++++++------------------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/cpukit/posix/src/mmap.c b/cpukit/posix/src/mmap.c
index b1d1653..9c70328 100644
--- a/cpukit/posix/src/mmap.c
+++ b/cpukit/posix/src/mmap.c
@@ -124,6 +124,7 @@ void *mmap(
   mmap_mapping   *mapping;
   ssize_t         r;
   rtems_libio_t  *iop;
+  bool            map_fixed;
   
   /*
    * Clear errno.
@@ -202,13 +203,15 @@ void *mmap(
   if ( !mmap_mappings_lock_obtain( ) )
     return MAP_FAILED;
 
-  if (( flags & MAP_FIXED ) == MAP_FIXED ) {
+  map_fixed = (flags & MAP_FIXED) == MAP_FIXED;
+  if ( map_fixed ) {
     rtems_chain_node* node = rtems_chain_first (&mmap_mappings);
     while ( !rtems_chain_is_tail( &mmap_mappings, node )) {
       /*
        * If the map is fixed see if this address is already mapped. At this
        * point in time if there is an overlap in the mappings we return an
-       * error.
+       * error. POSIX allows us to also return successfully by unmapping
+       * the overlapping prior mappings.
        */
       mapping = (mmap_mapping*) node;
       if ( ( addr >= mapping->addr ) &&
@@ -234,7 +237,7 @@ void *mmap(
   mapping->flags = flags;
   mapping->iop = iop;
   
-  if (( flags & MAP_FIXED ) != MAP_FIXED ) {
+  if ( !map_fixed ) {
     mapping->addr = malloc( len );
     if ( !mapping->addr ) {
       mmap_mappings_lock_release( );
@@ -242,26 +245,34 @@ void *mmap(
       errno = ENOMEM;
       return MAP_FAILED;
     }
+  } else {
+    mapping->addr = addr;
+  }
 
-    /*
-     * Do not seek on character devices, pipes, sockets, or memory objects.
-     */
-    if ( S_ISREG( sb.st_mode ) || S_ISBLK( sb.st_mode ) ) {
-      if ( lseek( fildes, off, SEEK_SET ) < 0 ) {
-        mmap_mappings_lock_release( );
+  /*
+   * Do not seek on character devices, pipes, sockets, or memory objects.
+   */
+  if ( S_ISREG( sb.st_mode ) || S_ISBLK( sb.st_mode ) ) {
+    if ( lseek( fildes, off, SEEK_SET ) < 0 ) {
+      mmap_mappings_lock_release( );
+      if ( !map_fixed ) {
         free( mapping->addr );
-        free( mapping );
-        return MAP_FAILED;
       }
+      free( mapping );
+      return MAP_FAILED;
     }
   }
 
+  /* FIXME: MAP_SHARED is not supported. It's unclear how it could be. */
+
   /* read updates atime satisfying POSIX spec for mmap */
   r = read( fildes, mapping->addr, len );
 
   if ( r != len ) {
     mmap_mappings_lock_release( );
-    free( mapping->addr );
+    if ( !map_fixed ) {
+      free( mapping->addr );
+    }
     free( mapping );
     errno = ENXIO;
     return MAP_FAILED;
@@ -280,14 +291,9 @@ void *mmap(
     shm_mmap(iop);
   }
 
-  /* FIXME:
-   * MAP_SHARED is not supported for regular files, and probably should be?
-   * MAP_PRIVATE is not supported for shared memory objects, and should be?
-   */
-
   /* FIXME: for a mapping with MAP_SHARED and PROT_WRITE the mtime/ctime
    * should be updated when there is a write reference to the mapped region.
-   * How do we make this happen? */
+   * How do we make this happen? Anyway MAP_SHARED is not supported yet. */
 
   /* add an extra reference to the file associated with fildes that
    * is not removed by a subsequent close().  This reference shall be removed
-- 
2.7.4




More information about the devel mailing list