summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport/src/close.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-09-13 09:22:19 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-09-15 10:29:34 +0200
commitbaef823cd550449bfbcc36625b9571389d8ad1af (patch)
tree238c1952d23dc09d41ae99d186d0656f78ed857b /cpukit/libcsupport/src/close.c
parentlibio: Unify readv() and writev() (diff)
downloadrtems-baef823cd550449bfbcc36625b9571389d8ad1af.tar.bz2
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.
Diffstat (limited to 'cpukit/libcsupport/src/close.c')
-rw-r--r--cpukit/libcsupport/src/close.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/cpukit/libcsupport/src/close.c b/cpukit/libcsupport/src/close.c
index 7eaeb64fea..d478e231c6 100644
--- a/cpukit/libcsupport/src/close.c
+++ b/cpukit/libcsupport/src/close.c
@@ -24,12 +24,45 @@ int close(
int fd
)
{
- rtems_libio_t *iop;
- int rc;
+ rtems_libio_t *iop;
+ unsigned int flags;
+ int rc;
- LIBIO_GET_IOP( fd, iop );
+ if ( (uint32_t) fd >= rtems_libio_number_iops ) {
+ rtems_set_errno_and_return_minus_one( EBADF );
+ }
- rtems_libio_iop_flags_clear( iop, LIBIO_FLAGS_OPEN );
+ iop = rtems_libio_iop( fd );
+ flags = rtems_libio_iop_flags( iop );
+
+ while ( true ) {
+ unsigned int desired;
+ bool success;
+
+ if ( ( flags & LIBIO_FLAGS_OPEN ) == 0 ) {
+ rtems_set_errno_and_return_minus_one( EBADF );
+ }
+
+ /* The expected flags */
+ flags &= LIBIO_FLAGS_REFERENCE_INC - 1U;
+
+ desired = flags & ~LIBIO_FLAGS_OPEN;
+ success = _Atomic_Compare_exchange_uint(
+ &iop->flags,
+ &flags,
+ desired,
+ ATOMIC_ORDER_ACQ_REL,
+ ATOMIC_ORDER_RELAXED
+ );
+
+ if ( success ) {
+ break;
+ }
+
+ if ( ( flags & ~( LIBIO_FLAGS_REFERENCE_INC - 1U ) ) != 0 ) {
+ rtems_set_errno_and_return_minus_one( EBUSY );
+ }
+ }
rc = (*iop->pathinfo.handlers->close_h)( iop );