From baef823cd550449bfbcc36625b9571389d8ad1af Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 13 Sep 2017 09:22:19 +0200 Subject: libio: Add hold/drop iop reference Check iop reference count in close() and return -1 with errno set to EBUSY in case the file descriptor is still in use. Update #3132. --- cpukit/libcsupport/include/rtems/libio.h | 8 ++-- cpukit/libcsupport/include/rtems/libio_.h | 75 +++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 26 deletions(-) (limited to 'cpukit/libcsupport/include/rtems') diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h index 2a67496800..804929915a 100644 --- a/cpukit/libcsupport/include/rtems/libio.h +++ b/cpukit/libcsupport/include/rtems/libio.h @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -1319,7 +1320,7 @@ extern const rtems_filesystem_limits_and_options_t struct rtems_libio_tt { rtems_driver_name_t *driver; off_t offset; /* current offset into file */ - uint32_t flags; + Atomic_Uint flags; rtems_filesystem_location_info_t pathinfo; uint32_t data0; /* private to "driver" */ void *data1; /* ... */ @@ -1371,12 +1372,13 @@ typedef struct { #define LIBIO_FLAGS_APPEND 0x0200U /* all writes append */ #define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800U /* close on process exec() */ #define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE) +#define LIBIO_FLAGS_REFERENCE_INC 0x1000U /** @} */ -static inline uint32_t rtems_libio_iop_flags( const rtems_libio_t *iop ) +static inline unsigned int rtems_libio_iop_flags( const rtems_libio_t *iop ) { - return iop->flags; + return _Atomic_Load_uint( &iop->flags, ATOMIC_ORDER_RELAXED ); } /** diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h index adf137d2f6..dc1fe9808a 100644 --- a/cpukit/libcsupport/include/rtems/libio_.h +++ b/cpukit/libcsupport/include/rtems/libio_.h @@ -104,7 +104,11 @@ static inline void rtems_libio_iop_flags_initialize( uint32_t flags ) { - iop->flags = LIBIO_FLAGS_OPEN | flags; + _Atomic_Store_uint( + &iop->flags, + LIBIO_FLAGS_OPEN | flags, + ATOMIC_ORDER_RELEASE + ); } /** @@ -115,16 +119,12 @@ static inline void rtems_libio_iop_flags_initialize( * * @return The previous flags. */ -static inline uint32_t rtems_libio_iop_flags_set( +static inline unsigned int rtems_libio_iop_flags_set( rtems_libio_t *iop, - uint32_t set + unsigned int set ) { - uint32_t flags; - - flags = iop->flags; - iop->flags = flags | set; - return flags; + return _Atomic_Fetch_or_uint( &iop->flags, set, ATOMIC_ORDER_RELAXED ); } /** @@ -135,16 +135,12 @@ static inline uint32_t rtems_libio_iop_flags_set( * * @return The previous flags. */ -static inline uint32_t rtems_libio_iop_flags_clear( +static inline unsigned int rtems_libio_iop_flags_clear( rtems_libio_t *iop, - uint32_t clear + unsigned int clear ) { - uint32_t flags; - - flags = iop->flags; - iop->flags = flags & ~clear; - return flags; + return _Atomic_Fetch_and_uint( &iop->flags, ~clear, ATOMIC_ORDER_RELAXED ); } /** @@ -161,6 +157,36 @@ static inline rtems_libio_t *rtems_libio_iop( int fd ) return &rtems_libio_iops[ fd ]; } +/** + * @brief Holds a refernece to the iop. + * + * @param[in] iop The iop. + * + * @return The flags corresponding to the specified iop. + */ +static inline unsigned int rtems_libio_iop_hold( rtems_libio_t *iop ) +{ + return _Atomic_Fetch_add_uint( + &iop->flags, + LIBIO_FLAGS_REFERENCE_INC, + ATOMIC_ORDER_ACQUIRE + ); +} + +/** + * @brief Drops a refernece to the iop. + * + * @param[in] iop The iop. + */ +static inline void rtems_libio_iop_drop( rtems_libio_t *iop ) +{ + _Atomic_Fetch_sub_uint( + &iop->flags, + LIBIO_FLAGS_REFERENCE_INC, + ATOMIC_ORDER_RELEASE + ); +} + /* * rtems_libio_iop_to_descriptor * @@ -192,13 +218,14 @@ static inline rtems_libio_t *rtems_libio_iop( int fd ) */ #define LIBIO_GET_IOP( _fd, _iop ) \ do { \ - uint32_t _flags; \ + unsigned int _flags; \ if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \ rtems_set_errno_and_return_minus_one( EBADF ); \ } \ _iop = rtems_libio_iop( _fd ); \ - _flags = _iop->flags; \ + _flags = rtems_libio_iop_hold( _iop ); \ if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \ + rtems_libio_iop_drop( _iop ); \ rtems_set_errno_and_return_minus_one( EBADF ); \ } \ } while ( 0 ) @@ -211,16 +238,17 @@ static inline rtems_libio_t *rtems_libio_iop( int fd ) */ #define LIBIO_GET_IOP_WITH_ACCESS( _fd, _iop, _access_flags, _access_error ) \ do { \ - uint32_t _flags; \ - uint32_t _mandatory; \ + unsigned int _flags; \ + unsigned int _mandatory; \ if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \ rtems_set_errno_and_return_minus_one( EBADF ); \ } \ _iop = rtems_libio_iop( _fd ); \ - _flags = _iop->flags; \ + _flags = rtems_libio_iop_hold( _iop ); \ _mandatory = LIBIO_FLAGS_OPEN | ( _access_flags ); \ if ( ( _flags & _mandatory ) != _mandatory ) { \ int _error; \ + rtems_libio_iop_drop( _iop ); \ if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \ _error = EBADF; \ } else { \ @@ -357,12 +385,12 @@ rtems_libio_t *rtems_libio_allocate(void); /** * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand */ -uint32_t rtems_libio_fcntl_flags( int fcntl_flags ); +unsigned int rtems_libio_fcntl_flags( int fcntl_flags ); /** * Convert RTEMS internal flags to UNIX fnctl(2) flags */ -int rtems_libio_to_fcntl_flags( uint32_t flags ); +int rtems_libio_to_fcntl_flags( unsigned int flags ); /** * This routine frees the resources associated with an IOP (file descriptor) @@ -932,7 +960,7 @@ static inline ssize_t rtems_libio_iovec_eval( int fd, const struct iovec *iov, int iovcnt, - uint32_t flags, + unsigned int flags, rtems_libio_iovec_adapter adapter ) { @@ -978,6 +1006,7 @@ static inline ssize_t rtems_libio_iovec_eval( total = ( *adapter )( iop, iov, iovcnt, total ); } + rtems_libio_iop_drop( iop ); return total; } -- cgit v1.2.3