forked from Imagelibrary/rtems
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.
This commit is contained in:
committed by
Gedare Bloom
parent
bd9d5ebc33
commit
8290f95cbd
@@ -32,6 +32,7 @@ include_HEADERS += include/mqueue.h
|
||||
include_rtems_posix_HEADERS += include/rtems/posix/aio_misc.h
|
||||
include_rtems_posix_HEADERS += include/rtems/posix/cond.h
|
||||
include_rtems_posix_HEADERS += include/rtems/posix/condimpl.h
|
||||
include_rtems_posix_HEADERS += include/rtems/posix/mmanimpl.h
|
||||
include_rtems_posix_HEADERS += include/rtems/posix/mqueue.h
|
||||
include_rtems_posix_HEADERS += include/rtems/posix/mqueueimpl.h
|
||||
include_rtems_posix_HEADERS += include/rtems/posix/mutex.h
|
||||
|
||||
44
cpukit/posix/include/rtems/posix/mmanimpl.h
Normal file
44
cpukit/posix/include/rtems/posix/mmanimpl.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Internal Support for POSIX 1003.1b 6.3.1 - map pages of memory
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 Chris Johns
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef _RTEMS_POSIX_MMANIMPL_H
|
||||
#define _RTEMS_POSIX_MMANIMPL_H
|
||||
|
||||
#include <rtems/chain.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Every mmap'ed region has a mapping.
|
||||
*/
|
||||
typedef struct mmap_mappings_s {
|
||||
rtems_chain_node node; /**< The mapping chain's node */
|
||||
void* addr; /**< The address of the mapped memory */
|
||||
size_t len; /**< The length of memory mapped */
|
||||
int flags; /**< The mapping flags */
|
||||
} mmap_mapping;
|
||||
|
||||
extern rtems_chain_control mmap_mappings;
|
||||
|
||||
bool mmap_mappings_lock_obtain( void );
|
||||
bool mmap_mappings_lock_release( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -72,6 +72,10 @@ $(PROJECT_INCLUDE)/rtems/posix/condimpl.h: include/rtems/posix/condimpl.h $(PROJ
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/condimpl.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/condimpl.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/posix/mmanimpl.h: include/rtems/posix/mmanimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mmanimpl.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mmanimpl.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/posix/mqueue.h: include/rtems/posix/mqueue.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mqueue.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mqueue.h
|
||||
|
||||
@@ -1,36 +1,230 @@
|
||||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
/*
|
||||
* COPYRIGHT (c) 2014.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright (c) 2012 Chris Johns (chrisj@rtems.org)
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void *mmap(
|
||||
void *addr,
|
||||
size_t length,
|
||||
int prot,
|
||||
int flags,
|
||||
int fildes,
|
||||
off_t off
|
||||
#include "rtems/libio_.h"
|
||||
|
||||
#include <rtems/posix/mmanimpl.h>
|
||||
|
||||
#define RTEMS_MUTEX_ATTRIBS \
|
||||
(RTEMS_PRIORITY | RTEMS_SIMPLE_BINARY_SEMAPHORE | \
|
||||
RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
|
||||
|
||||
/**
|
||||
* Mmap chain of mappings.
|
||||
*/
|
||||
rtems_chain_control mmap_mappings;
|
||||
|
||||
/**
|
||||
* The id of the MMAP lock.
|
||||
*/
|
||||
static rtems_id mmap_mappings_lock;
|
||||
|
||||
/**
|
||||
* Create the lock.
|
||||
*/
|
||||
static
|
||||
bool mmap_mappings_lock_create(
|
||||
void
|
||||
)
|
||||
{
|
||||
(void) addr;
|
||||
(void) length;
|
||||
(void) prot;
|
||||
(void) flags;
|
||||
(void) fildes;
|
||||
(void) off;
|
||||
return MAP_FAILED;
|
||||
/*
|
||||
* Lock the mapping table. We only create a lock if a call is made. First we
|
||||
* test if a mapping lock is present. If one is present we lock it. If not
|
||||
* the libio lock is locked and we then test the mapping lock again. If not
|
||||
* present we create the mapping lock then release libio lock.
|
||||
*/
|
||||
if ( mmap_mappings_lock == 0 ) {
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
rtems_chain_initialize_empty( &mmap_mappings );
|
||||
rtems_semaphore_obtain( rtems_libio_semaphore,
|
||||
RTEMS_WAIT, RTEMS_NO_TIMEOUT );
|
||||
if ( mmap_mappings_lock == 0 )
|
||||
sc = rtems_semaphore_create( rtems_build_name( 'M', 'M', 'A', 'P' ),
|
||||
1,
|
||||
RTEMS_MUTEX_ATTRIBS,
|
||||
RTEMS_NO_PRIORITY,
|
||||
&mmap_mappings_lock );
|
||||
rtems_semaphore_release( rtems_libio_semaphore );
|
||||
if ( sc != RTEMS_SUCCESSFUL ) {
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mmap_mappings_lock_obtain(
|
||||
void
|
||||
)
|
||||
{
|
||||
if ( mmap_mappings_lock_create( ) ) {
|
||||
rtems_status_code sc;
|
||||
sc = rtems_semaphore_obtain( mmap_mappings_lock,
|
||||
RTEMS_WAIT, RTEMS_NO_TIMEOUT );
|
||||
if ( sc != RTEMS_SUCCESSFUL ) {
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mmap_mappings_lock_release(
|
||||
void
|
||||
)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
sc = rtems_semaphore_release( mmap_mappings_lock );
|
||||
if (( sc != RTEMS_SUCCESSFUL ) && ( errno == 0 )) {
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void *mmap(
|
||||
void *addr, size_t len, int prot, int flags, int fildes, off_t off
|
||||
)
|
||||
{
|
||||
struct stat sb;
|
||||
mmap_mapping* mapping;
|
||||
ssize_t r;
|
||||
|
||||
/*
|
||||
* Clear errno.
|
||||
*/
|
||||
errno = 0;
|
||||
|
||||
/*
|
||||
* Get a stat of the file to get the dev + inode number and to make sure the
|
||||
* fd is ok. The normal libio calls cannot be used because we need to return
|
||||
* MAP_FAILED on error and they return -1 directly without coming back to
|
||||
* here.
|
||||
*/
|
||||
if ( fstat( fildes, &sb ) < 0 ) {
|
||||
errno = EBADF;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
if ( len == 0 ) {
|
||||
errno = EINVAL;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the type of file we have and make sure it is supported.
|
||||
*/
|
||||
if ( S_ISDIR( sb.st_mode ) || S_ISLNK( sb.st_mode )) {
|
||||
errno = ENODEV;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can provide read, write and execute because the memory in RTEMS does
|
||||
* not normally have protections but we cannot hide access to memory.
|
||||
*/
|
||||
if ( prot == PROT_NONE ) {
|
||||
errno = EINVAL;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the mapping is valid for the file.
|
||||
*/
|
||||
if ( S_ISREG( sb.st_mode )
|
||||
&& (( off >= sb.st_size ) || (( off + len ) >= sb.st_size ))) {
|
||||
errno = EOVERFLOW;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the mmap lock. Sets errno on failure.
|
||||
*/
|
||||
if ( !mmap_mappings_lock_obtain( ) )
|
||||
return MAP_FAILED;
|
||||
|
||||
if (( flags & MAP_FIXED ) == 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.
|
||||
*/
|
||||
mapping = (mmap_mapping*) node;
|
||||
if ( ( addr >= mapping->addr ) &&
|
||||
( addr < ( mapping->addr + mapping->len )) ) {
|
||||
mmap_mappings_lock_release( );
|
||||
errno = ENXIO;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
node = rtems_chain_next( node );
|
||||
}
|
||||
}
|
||||
|
||||
mapping = malloc( sizeof( mmap_mapping ));
|
||||
if ( !mapping ) {
|
||||
mmap_mappings_lock_release( );
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset( mapping, 0, sizeof( mmap_mapping ));
|
||||
|
||||
mapping->len = len;
|
||||
mapping->flags = flags;
|
||||
|
||||
if (( flags & MAP_FIXED ) != MAP_FIXED ) {
|
||||
mapping->addr = malloc( len );
|
||||
if ( !mapping->addr ) {
|
||||
mmap_mappings_lock_release( );
|
||||
free( mapping );
|
||||
errno = ENOMEM;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not seek on character devices, pipes or sockets.
|
||||
*/
|
||||
if ( S_ISREG( sb.st_mode ) || S_ISBLK( sb.st_mode ) ) {
|
||||
if ( lseek( fildes, off, SEEK_SET ) < 0 ) {
|
||||
mmap_mappings_lock_release( );
|
||||
free( mapping->addr );
|
||||
free( mapping );
|
||||
return MAP_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = read( fildes, mapping->addr, len );
|
||||
|
||||
if ( r != len ) {
|
||||
mmap_mappings_lock_release( );
|
||||
free( mapping->addr );
|
||||
free( mapping );
|
||||
errno = ENXIO;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
rtems_chain_append( &mmap_mappings, &mapping->node );
|
||||
|
||||
mmap_mappings_lock_release( );
|
||||
|
||||
return mapping->addr;
|
||||
}
|
||||
|
||||
@@ -1,28 +1,68 @@
|
||||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
/*
|
||||
* COPYRIGHT (c) 2014.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright (c) 2012 Chris Johns (chrisj@rtems.org)
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <rtems/posix/mmanimpl.h>
|
||||
|
||||
int munmap(
|
||||
void *addr,
|
||||
size_t length
|
||||
void *addr, size_t len
|
||||
)
|
||||
{
|
||||
(void) addr;
|
||||
(void) length;
|
||||
return -1;
|
||||
mmap_mapping* mapping;
|
||||
rtems_chain_node* node;
|
||||
|
||||
/*
|
||||
* Clear errno.
|
||||
*/
|
||||
errno = 0;
|
||||
|
||||
/*
|
||||
* Length cannot be 0.
|
||||
*/
|
||||
if ( len == 0 ) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the mmap lock. Sets errno on failure.
|
||||
*/
|
||||
if ( !mmap_mappings_lock_obtain( ))
|
||||
return -1;
|
||||
|
||||
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.
|
||||
*/
|
||||
mapping = (mmap_mapping*) node;
|
||||
if ( ( addr >= mapping->addr ) &&
|
||||
( addr < ( mapping->addr + mapping->len )) ) {
|
||||
rtems_chain_extract( node );
|
||||
if (( mapping->flags & MAP_FIXED ) != MAP_FIXED ) {
|
||||
free( mapping->addr );
|
||||
free( mapping );
|
||||
}
|
||||
break;
|
||||
}
|
||||
node = rtems_chain_next( node );
|
||||
}
|
||||
|
||||
mmap_mappings_lock_release( );
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user