From 87de70a2984cece87db94f4b445589c4e24e5c77 Mon Sep 17 00:00:00 2001 From: Gedare Bloom Date: Wed, 15 Mar 2017 14:31:00 -0400 Subject: posix/mman: add mmap support for shm objects Update #2859. --- cpukit/libcsupport/include/rtems/libio.h | 1 + cpukit/libcsupport/include/rtems/libio_.h | 41 +++++++++++++++++++++++++++++++ cpukit/libcsupport/src/libio.c | 32 ++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) (limited to 'cpukit/libcsupport') diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h index a87031ca91..d0824b4e85 100644 --- a/cpukit/libcsupport/include/rtems/libio.h +++ b/cpukit/libcsupport/include/rtems/libio.h @@ -1282,6 +1282,7 @@ struct rtems_libio_tt { rtems_driver_name_t *driver; off_t offset; /* current offset into file */ uint32_t flags; + uint32_t mapping_refcnt; /* current mappings */ rtems_filesystem_location_info_t pathinfo; uint32_t data0; /* private to "driver" */ void *data1; /* ... */ diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h index c2fb975bf7..695a4c45a5 100644 --- a/cpukit/libcsupport/include/rtems/libio_.h +++ b/cpukit/libcsupport/include/rtems/libio_.h @@ -304,6 +304,47 @@ void rtems_libio_free( rtems_libio_t *iop ); +/** + * Garbage collects the free libio in case it was previously freed but there + * were still references to it. + */ +void rtems_libio_check_deferred_free( rtems_libio_t *iop ); + +/** + * Increment the reference count tracking number of mmap mappings of a file. + * Returns the updated reference count value. + */ +static inline uint32_t rtems_libio_increment_mapping_refcnt(rtems_libio_t *iop) +{ + uint32_t refcnt; + rtems_libio_lock(); + refcnt = ++iop->mapping_refcnt; + rtems_libio_unlock(); + return refcnt; +} + +/** + * Decrement the reference count tracking number of mmap mappings of a file. + * Returns the updated reference count value. + */ +static inline uint32_t rtems_libio_decrement_mapping_refcnt(rtems_libio_t *iop) +{ + uint32_t refcnt; + rtems_libio_lock(); + refcnt = --iop->mapping_refcnt; + rtems_libio_unlock(); + return refcnt; +} + +static inline bool rtems_libio_is_mapped(rtems_libio_t *iop) +{ + bool is_mapped; + rtems_libio_lock(); + is_mapped = iop->mapping_refcnt != 0; + rtems_libio_unlock(); + return is_mapped; +} + /* * File System Routine Prototypes */ diff --git a/cpukit/libcsupport/src/libio.c b/cpukit/libcsupport/src/libio.c index 22be6411a2..e89634f090 100644 --- a/cpukit/libcsupport/src/libio.c +++ b/cpukit/libcsupport/src/libio.c @@ -138,8 +138,36 @@ void rtems_libio_free( rtems_libio_lock(); iop->flags = 0; - iop->data1 = rtems_libio_iop_freelist; - rtems_libio_iop_freelist = iop; + /* If the mapping_refcnt is non-zero, the deferred free will be + * called by munmap. The iop is no longer good to use, but it cannot + * be recycled until the mapped file is unmapped. deferred free knows + * it can recycle the iop in case flags == 0 and iop->data1 == iop, + * since these two conditions are not otherwise satisifed at + * the same time. It may be possible that iop->data1 == iop when + * flags != 0 because data1 is private to the driver. However, flags == 0 + * means a freed iop, and an iop on the freelist cannot store a pointer + * to itself in data1, or else the freelist is corrupted. We can't use + * NULL in data1 as an indicator because it is used by the tail of the + * freelist. */ + if ( iop->mapping_refcnt == 0 ) { + iop->data1 = rtems_libio_iop_freelist; + rtems_libio_iop_freelist = iop; + } else { + iop->data1 = iop; + } rtems_libio_unlock(); } + +void rtems_libio_check_deferred_free( + rtems_libio_t *iop +) +{ + rtems_libio_lock(); + if ( iop->mapping_refcnt == 0 && iop->flags == 0 && iop->data1 == iop) { + /* No mappings and rtems_libio_free already called, recycle the iop */ + iop->data1 = rtems_libio_iop_freelist; + rtems_libio_iop_freelist = iop; + } + rtems_libio_unlock(); +} -- cgit v1.2.3