Changeset 8290f95 in rtems


Ignore:
Timestamp:
Mar 13, 2017, 4:00:35 PM (3 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
master
Children:
87de70a2
Parents:
bd9d5eb
git-author:
Chris Johns <chrisj@…> (03/13/17 16:00:35)
git-committer:
Gedare Bloom <gedare@…> (05/05/17 14:34:08)
Message:

posix: Add mmap/unmap support for mapping files.

This version of mmap comes from early work done
on the RTL code base circa 2012.

Update #2859.

Location:
cpukit/posix
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • cpukit/posix/Makefile.am

    rbd9d5eb r8290f95  
    3333include_rtems_posix_HEADERS += include/rtems/posix/cond.h
    3434include_rtems_posix_HEADERS += include/rtems/posix/condimpl.h
     35include_rtems_posix_HEADERS += include/rtems/posix/mmanimpl.h
    3536include_rtems_posix_HEADERS += include/rtems/posix/mqueue.h
    3637include_rtems_posix_HEADERS += include/rtems/posix/mqueueimpl.h
  • cpukit/posix/preinstall.am

    rbd9d5eb r8290f95  
    7272        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/condimpl.h
    7373PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/condimpl.h
     74
     75$(PROJECT_INCLUDE)/rtems/posix/mmanimpl.h: include/rtems/posix/mmanimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
     76        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mmanimpl.h
     77PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mmanimpl.h
    7478
    7579$(PROJECT_INCLUDE)/rtems/posix/mqueue.h: include/rtems/posix/mqueue.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
  • cpukit/posix/src/mmap.c

    rbd9d5eb r8290f95  
    1 /**
    2  * @file
    3  */
    4 
    51/*
    6  *  COPYRIGHT (c) 2014.
    7  *  On-Line Applications Research Corporation (OAR).
     2 * Copyright (c) 2012 Chris Johns (chrisj@rtems.org)
    83 *
    9  *  The license and distribution terms for this file may be
    10  *  found in the file LICENSE in this distribution or at
    11  *  http://www.rtems.org/license/LICENSE.
     4 * The license and distribution terms for this file may be
     5 * found in the file LICENSE in this distribution or at
     6 * http://www.rtems.org/license/LICENSE.
    127 */
    138
     
    1611#endif
    1712
     13#include <rtems.h>
     14#include <errno.h>
     15#include <stdlib.h>
    1816#include <sys/mman.h>
     17#include <sys/stat.h>
     18#include <unistd.h>
     19
     20#include "rtems/libio_.h"
     21
     22#include <rtems/posix/mmanimpl.h>
     23
     24#define RTEMS_MUTEX_ATTRIBS \
     25  (RTEMS_PRIORITY | RTEMS_SIMPLE_BINARY_SEMAPHORE | \
     26   RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
     27
     28/**
     29 * Mmap chain of mappings.
     30 */
     31rtems_chain_control mmap_mappings;
     32
     33/**
     34 * The id of the MMAP lock.
     35 */
     36static rtems_id mmap_mappings_lock;
     37
     38/**
     39 * Create the lock.
     40 */
     41static
     42bool mmap_mappings_lock_create(
     43  void
     44)
     45{
     46  /*
     47   * Lock the mapping table. We only create a lock if a call is made. First we
     48   * test if a mapping lock is present. If one is present we lock it. If not
     49   * the libio lock is locked and we then test the mapping lock again. If not
     50   * present we create the mapping lock then release libio lock.
     51   */
     52  if ( mmap_mappings_lock == 0 ) {
     53    rtems_status_code sc = RTEMS_SUCCESSFUL;
     54    rtems_chain_initialize_empty( &mmap_mappings );
     55    rtems_semaphore_obtain( rtems_libio_semaphore,
     56                            RTEMS_WAIT, RTEMS_NO_TIMEOUT );
     57    if ( mmap_mappings_lock == 0 )
     58      sc = rtems_semaphore_create( rtems_build_name( 'M', 'M', 'A', 'P' ),
     59                                   1,
     60                                   RTEMS_MUTEX_ATTRIBS,
     61                                   RTEMS_NO_PRIORITY,
     62                                   &mmap_mappings_lock );
     63    rtems_semaphore_release( rtems_libio_semaphore );
     64    if ( sc != RTEMS_SUCCESSFUL ) {
     65      errno = EINVAL;
     66      return false;
     67    }
     68  }
     69  return true;
     70}
     71
     72bool mmap_mappings_lock_obtain(
     73  void
     74)
     75{
     76  if ( mmap_mappings_lock_create( ) ) {
     77    rtems_status_code sc;
     78    sc = rtems_semaphore_obtain( mmap_mappings_lock,
     79                                 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
     80    if ( sc != RTEMS_SUCCESSFUL ) {
     81      errno = EINVAL;
     82      return false;
     83    }
     84  }
     85  return true;
     86}
     87
     88bool mmap_mappings_lock_release(
     89  void
     90)
     91{
     92  rtems_status_code sc;
     93  sc = rtems_semaphore_release( mmap_mappings_lock );
     94  if (( sc != RTEMS_SUCCESSFUL ) && ( errno == 0 )) {
     95    errno = EINVAL;
     96    return false;
     97  }
     98  return true;
     99}
    19100
    20101void *mmap(
    21   void   *addr,
    22   size_t  length,
    23   int     prot,
    24   int     flags,
    25   int     fildes,
    26   off_t   off
    27 )
    28 {
    29   (void) addr;
    30   (void) length;
    31   (void) prot;
    32   (void) flags;
    33   (void) fildes;
    34   (void) off;
    35   return MAP_FAILED;
    36 }
     102  void *addr, size_t len, int prot, int flags, int fildes, off_t off
     103)
     104{
     105  struct stat   sb;
     106  mmap_mapping* mapping;
     107  ssize_t       r;
     108 
     109  /*
     110   * Clear errno.
     111   */
     112  errno = 0;
     113 
     114  /*
     115   * Get a stat of the file to get the dev + inode number and to make sure the
     116   * fd is ok. The normal libio calls cannot be used because we need to return
     117   * MAP_FAILED on error and they return -1 directly without coming back to
     118   * here.
     119   */
     120  if ( fstat( fildes, &sb ) < 0 ) {
     121    errno = EBADF;
     122    return MAP_FAILED;
     123  }
     124
     125  if ( len == 0 ) {
     126    errno = EINVAL;
     127    return MAP_FAILED;
     128  }
     129
     130  /*
     131   * Check the type of file we have and make sure it is supported.
     132   */
     133  if ( S_ISDIR( sb.st_mode ) || S_ISLNK( sb.st_mode )) {
     134    errno = ENODEV;
     135    return MAP_FAILED;
     136  }
     137 
     138  /*
     139   * We can provide read, write and execute because the memory in RTEMS does
     140   * not normally have protections but we cannot hide access to memory.
     141   */
     142  if ( prot == PROT_NONE ) {
     143    errno = EINVAL;
     144    return MAP_FAILED;
     145  }
     146 
     147  /*
     148   * Check to see if the mapping is valid for the file.
     149   */
     150  if ( S_ISREG( sb.st_mode )
     151       && (( off >= sb.st_size ) || (( off + len ) >= sb.st_size ))) {
     152    errno = EOVERFLOW;
     153    return MAP_FAILED;
     154  }
     155
     156  /*
     157   * Obtain the mmap lock. Sets errno on failure.
     158   */
     159  if ( !mmap_mappings_lock_obtain( ) )
     160    return MAP_FAILED;
     161
     162  if (( flags & MAP_FIXED ) == MAP_FIXED ) {
     163    rtems_chain_node* node = rtems_chain_first (&mmap_mappings);
     164    while ( !rtems_chain_is_tail( &mmap_mappings, node )) {
     165      /*
     166       * If the map is fixed see if this address is already mapped. At this
     167       * point in time if there is an overlap in the mappings we return an
     168       * error.
     169       */
     170      mapping = (mmap_mapping*) node;
     171      if ( ( addr >= mapping->addr ) &&
     172           ( addr < ( mapping->addr + mapping->len )) ) {
     173        mmap_mappings_lock_release( );
     174        errno = ENXIO;
     175        return MAP_FAILED;
     176      }
     177      node = rtems_chain_next( node );
     178    }
     179  }
     180
     181  mapping = malloc( sizeof( mmap_mapping ));
     182  if ( !mapping ) {
     183    mmap_mappings_lock_release( );
     184    errno = ENOMEM;
     185    return NULL;
     186  }
     187
     188  memset( mapping, 0, sizeof( mmap_mapping ));
     189
     190  mapping->len = len;
     191  mapping->flags = flags;
     192 
     193  if (( flags & MAP_FIXED ) != MAP_FIXED ) {
     194    mapping->addr = malloc( len );
     195    if ( !mapping->addr ) {
     196      mmap_mappings_lock_release( );
     197      free( mapping );
     198      errno = ENOMEM;
     199      return MAP_FAILED;
     200    }
     201
     202    /*
     203     * Do not seek on character devices, pipes or sockets.
     204     */
     205    if ( S_ISREG( sb.st_mode ) || S_ISBLK( sb.st_mode ) ) {
     206      if ( lseek( fildes, off, SEEK_SET ) < 0 ) {
     207        mmap_mappings_lock_release( );
     208        free( mapping->addr );
     209        free( mapping );
     210        return MAP_FAILED;
     211      }
     212    }
     213  }
     214
     215  r = read( fildes, mapping->addr, len );
     216
     217  if ( r != len ) {
     218    mmap_mappings_lock_release( );
     219    free( mapping->addr );
     220    free( mapping );
     221    errno = ENXIO;
     222    return MAP_FAILED;
     223  }
     224
     225  rtems_chain_append( &mmap_mappings, &mapping->node );
     226
     227  mmap_mappings_lock_release( );
     228 
     229  return mapping->addr;
     230}
  • cpukit/posix/src/munmap.c

    rbd9d5eb r8290f95  
    1 /**
    2  * @file
    3  */
    4 
    51/*
    6  *  COPYRIGHT (c) 2014.
    7  *  On-Line Applications Research Corporation (OAR).
     2 * Copyright (c) 2012 Chris Johns (chrisj@rtems.org)
    83 *
    9  *  The license and distribution terms for this file may be
    10  *  found in the file LICENSE in this distribution or at
    11  *  http://www.rtems.org/license/LICENSE.
     4 * The license and distribution terms for this file may be
     5 * found in the file LICENSE in this distribution or at
     6 * http://www.rtems.org/license/LICENSE.
    127 */
    138
     
    1611#endif
    1712
     13#include <rtems.h>
     14#include <errno.h>
     15#include <stdlib.h>
    1816#include <sys/mman.h>
    1917
     18#include <rtems/posix/mmanimpl.h>
     19
    2020int munmap(
    21   void   *addr,
    22   size_t  length
     21  void *addr, size_t len
    2322)
    2423{
    25   (void) addr;
    26   (void) length;
    27   return -1;
     24  mmap_mapping*     mapping;
     25  rtems_chain_node* node;
     26 
     27  /*
     28   * Clear errno.
     29   */
     30  errno = 0;
     31
     32  /*
     33   * Length cannot be 0.
     34   */
     35  if ( len == 0 ) {
     36    errno = EINVAL;
     37    return -1;
     38  }
     39
     40  /*
     41   * Obtain the mmap lock. Sets errno on failure.
     42   */
     43  if ( !mmap_mappings_lock_obtain( ))
     44    return -1;
     45
     46  node = rtems_chain_first (&mmap_mappings);
     47  while ( !rtems_chain_is_tail( &mmap_mappings, node )) {
     48    /*
     49     * If the map is fixed see if this address is already mapped. At this
     50     * point in time if there is an overlap in the mappings we return an
     51     * error.
     52     */
     53    mapping = (mmap_mapping*) node;
     54    if ( ( addr >= mapping->addr ) &&
     55         ( addr < ( mapping->addr + mapping->len )) ) {
     56      rtems_chain_extract( node );
     57      if (( mapping->flags & MAP_FIXED ) != MAP_FIXED ) {
     58        free( mapping->addr );
     59        free( mapping );
     60      }
     61      break;
     62    }
     63    node = rtems_chain_next( node );
     64  }
     65
     66  mmap_mappings_lock_release( );
     67  return 0;
    2868}
Note: See TracChangeset for help on using the changeset viewer.