summaryrefslogtreecommitdiffstats
path: root/cpukit/posix/src/munmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/posix/src/munmap.c')
-rw-r--r--cpukit/posix/src/munmap.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/cpukit/posix/src/munmap.c b/cpukit/posix/src/munmap.c
index d3687dfef4..323a24e6f4 100644
--- a/cpukit/posix/src/munmap.c
+++ b/cpukit/posix/src/munmap.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2012 Chris Johns (chrisj@rtems.org)
+ * Copyright (c) 2017 Gedare Bloom (gedare@rtems.org)
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -16,13 +17,21 @@
#include <sys/mman.h>
#include <rtems/posix/mmanimpl.h>
+#include <rtems/posix/shmimpl.h>
-int munmap(
- void *addr, size_t len
-)
+static void shm_munmap( rtems_libio_t *iop )
{
- mmap_mapping* mapping;
- rtems_chain_node* node;
+ POSIX_Shm_Control *shm = iop_to_shm( iop );
+
+ /* decrement mmap's shm reference_count and maybe delete the object */
+ POSIX_Shm_Attempt_delete(shm);
+}
+
+int munmap(void *addr, size_t len)
+{
+ mmap_mapping *mapping;
+ rtems_chain_node *node;
+ uint32_t refcnt;
/*
* Clear errno.
@@ -45,19 +54,29 @@ int munmap(
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 );
+ /* FIXME: generally need a way to clean-up the backing object, but
+ * currently it only matters for MAP_SHARED shm objects. */
+ if ( mapping->is_shared_shm == true ) {
+ shm_munmap(mapping->iop);
+ }
+ refcnt = rtems_libio_decrement_mapping_refcnt(mapping->iop);
+ if ( refcnt == 0 ) {
+ rtems_libio_check_deferred_free(mapping->iop);
+ }
+ /* only free the mapping address for non-fixed mapping */
if (( mapping->flags & MAP_FIXED ) != MAP_FIXED ) {
- free( mapping->addr );
- free( mapping );
+ /* only free the mapping address for non-shared mapping, because we
+ * re-use the mapping address across all of the shared mappings, and
+ * it is memory managed independently... */
+ if (( mapping->flags & MAP_SHARED ) != MAP_SHARED ) {
+ free( mapping->addr );
+ }
}
+ free( mapping );
break;
}
node = rtems_chain_next( node );