[PATCH] posix: add shm_unlink and close, fstat, read for shm objects

Gedare Bloom gedare at rtems.org
Fri Aug 26 20:17:45 UTC 2016


---
 cpukit/posix/include/rtems/posix/shm.h     |  8 +--
 cpukit/posix/include/rtems/posix/shmimpl.h | 12 ++++
 cpukit/posix/src/shmheap.c                 | 19 ++++--
 cpukit/posix/src/shmopen.c                 | 92 ++++++++++++++++++++++++++----
 cpukit/posix/src/shmunlink.c               | 30 +++++++++-
 cpukit/posix/src/shmwkspace.c              | 19 ++++--
 6 files changed, 151 insertions(+), 29 deletions(-)

diff --git a/cpukit/posix/include/rtems/posix/shm.h b/cpukit/posix/include/rtems/posix/shm.h
index eae0dcf..33d59f8 100644
--- a/cpukit/posix/include/rtems/posix/shm.h
+++ b/cpukit/posix/include/rtems/posix/shm.h
@@ -56,10 +56,10 @@ typedef struct {
 } POSIX_Shm_Control;
 
 struct POSIX_Shm_Object_operations {
-  int   ( *object_create ) ( POSIX_Shm_Control *shm, size_t size );
-  int   ( *object_resize ) ( POSIX_Shm_Control *shm, size_t size );
-  int   ( *object_delete ) ( POSIX_Shm_Control *shm );
-  void *( *object_mmap   ) ( POSIX_Shm_Control *shm, size_t len, int prot, int flags, off_t off );
+  int ( *object_create ) ( POSIX_Shm_Control *shm, size_t size );
+  int ( *object_resize ) ( POSIX_Shm_Control *shm, size_t size );
+  int ( *object_delete ) ( POSIX_Shm_Control *shm );
+  int ( *object_read   ) ( POSIX_Shm_Control *shm, void *buf, size_t count );
 };
 
 extern int _POSIX_Shm_Object_create_from_workspace(
diff --git a/cpukit/posix/include/rtems/posix/shmimpl.h b/cpukit/posix/include/rtems/posix/shmimpl.h
index c012771..97a7442 100644
--- a/cpukit/posix/include/rtems/posix/shmimpl.h
+++ b/cpukit/posix/include/rtems/posix/shmimpl.h
@@ -92,6 +92,18 @@ RTEMS_INLINE_ROUTINE void _POSIX_Shm_Update_mtime_ctime(
   shm->ctime = now.tv_sec;
 }
 
+static inline POSIX_Shm_Control* iop_to_shm( rtems_libio_t *iop )
+{
+  return (POSIX_Shm_Control*) iop->data1;
+}
+
+static inline POSIX_Shm_Control* loc_to_shm(
+    const rtems_filesystem_location_info_t *loc
+)
+{
+  return (POSIX_Shm_Control*) loc->node_access;
+}
+
 /** @} */
 
 #ifdef __cplusplus
diff --git a/cpukit/posix/src/shmheap.c b/cpukit/posix/src/shmheap.c
index 5896445..cd56e5f 100644
--- a/cpukit/posix/src/shmheap.c
+++ b/cpukit/posix/src/shmheap.c
@@ -65,15 +65,22 @@ int _POSIX_Shm_Object_resize_from_heap(
   return err;
 }
 
-void *_POSIX_Shm_Object_mmap_from_heap(
+int _POSIX_Shm_Object_read_from_heap(
   POSIX_Shm_Control *shm,
-  size_t len,
-  int prot,
-  int flags,
-  off_t off
+  void *buf,
+  size_t count
 )
 {
-  return NULL;
+  if ( shm == NULL || shm->shm_object.handle == NULL )
+    return 0;
+
+  if ( shm->shm_object.size < count ) {
+    count = shm->shm_object.size;
+  }
+
+  memcpy( buf, shm->shm_object.handle, count );
+
+  return count;
 }
 
 
diff --git a/cpukit/posix/src/shmopen.c b/cpukit/posix/src/shmopen.c
index cbea88c..7c92194 100644
--- a/cpukit/posix/src/shmopen.c
+++ b/cpukit/posix/src/shmopen.c
@@ -28,11 +28,49 @@
 
 static const rtems_filesystem_file_handlers_r shm_handlers;
 
+static int shm_fstat(
+  const rtems_filesystem_location_info_t *loc,
+  struct stat *buf
+)
+{
+  POSIX_Shm_Control *shm = loc_to_shm( loc );
+
+  if ( shm == NULL )
+    rtems_set_errno_and_return_minus_one( EIO );
+
+  /* mandatory for shm objects */
+  buf->st_uid = shm->uid;
+  buf->st_gid = shm->gid;
+  buf->st_size = shm->shm_object.size;
+  buf->st_mode = shm->mode;
+
+  /* optional for shm objects */
+  buf->st_atim = shm->atime;
+  buf->st_mtim = shm->mtime;
+  buf->st_ctim = shm->ctime;
+
+  return 0;
+}
+
+/* read() is unspecified for shared memory objects */
+static int shm_read( rtems_libio_t *iop, void *buffer, size_t count )
+{
+  Thread_queue_Context queue_context;
+  int bytes_read;
+  POSIX_Shm_Control *shm = iop_to_shm( iop );
+
+  _POSIX_Shm_Acquire_critical( shm, &queue_context );
+  bytes_read = (*shm->shm_object.ops->object_read)( shm, buffer, count );
+  _POSIX_Shm_Release( shm, &queue_context );
+
+  return bytes_read;
+}
+
 static int shm_ftruncate( rtems_libio_t *iop, off_t length )
 {
-  Thread_queue_Context  queue_context;
-  POSIX_Shm_Control *shm = (POSIX_Shm_Control *) iop->data1;
+  Thread_queue_Context queue_context;
   int err;
+  POSIX_Shm_Control *shm = iop_to_shm( iop );
 
   _POSIX_Shm_Acquire_critical( shm, &queue_context );
 
@@ -42,13 +80,48 @@ static int shm_ftruncate( rtems_libio_t *iop, off_t length )
     _POSIX_Shm_Release( shm, &queue_context );
     rtems_set_errno_and_return_minus_one( err );
   }
- 
+
   _POSIX_Shm_Update_mtime_ctime( shm );
 
   _POSIX_Shm_Release( shm, &queue_context );
   return 0;
 }
 
+static int shm_close( rtems_libio_t *iop )
+{
+  POSIX_Shm_Control *shm = iop_to_shm( iop );
+  Objects_Control       *the_object;
+  ISR_lock_Context       lock_ctx;
+  int err;
+
+  _Objects_Allocator_lock();
+
+  --shm->reference_count;
+  if ( shm->reference_count == 0 ) {
+    /* TODO: need to make sure this counts mmaps too! */
+    if ( (*shm->shm_object.ops->object_delete)( shm ) != 0 ) {
+      err = EIO;
+    }
+    /* check if the object has been unlinked yet. */
+    obj = _Objects_Get( shm->Object.id, &lock_ctx, &_POSIX_Shm_Information );
+    if ( obj == NULL ) {
+      /* if it was unlinked, then it can be freed. */
+      _POSIX_Shm_Free( shm );
+    } else {
+      /* it will be freed when it is unlinked. */
+      _ISR_lock_ISR_enable( &lock_context );
+    }
+  }
+  iop->pathinfo.node_access = NULL;
+
+  _Objects_Allocator_unlock();
+
+  if ( err != 0 ) {
+    rtems_set_errno_and_return_minus_one( err );
+  }
+  return 0;
+}
+
 static inline POSIX_Shm_Control *shm_allocate(
   const char *name_arg,
   size_t name_len,
@@ -145,7 +218,6 @@ int shm_open( const char *name, int oflag, mode_t mode )
     return -1;
   }
 
-  /* TODO see if the object exists, shms available */
   iop = rtems_libio_allocate();
   if ( iop == NULL ) {
     rtems_set_errno_and_return_minus_one( EMFILE );
@@ -169,20 +241,17 @@ int shm_open( const char *name, int oflag, mode_t mode )
         shm = shm_allocate(name, len, oflag, mode, &err);
         break;
     }
-    _Objects_Allocator_unlock();
   } else { /* shm exists */
-    _Objects_Allocator_unlock();
     if ( ( oflag & ( O_EXCL | O_CREAT ) ) == ( O_EXCL | O_CREAT ) ) {
       /* Request to create failed. */
       err = EEXIST;
     } else if ( !shm_access_ok( shm, oflag ) ) {
       err = EACCES;
     } else {
-      _POSIX_Shm_Acquire_critical( shm, &queue_context );
       ++shm->reference_count;
-      _POSIX_Shm_Release( shm, &queue_context );
     }
   }
+  _Objects_Allocator_unlock();
   if ( err != 0 ) {
     rtems_libio_free( iop );
     rtems_set_errno_and_return_minus_one( err );
@@ -202,6 +271,7 @@ int shm_open( const char *name, int oflag, mode_t mode )
   }
   iop->data0 = fd;
   iop->data1 = shm;
+  iop->pathinfo.node_access = shm;
   iop->pathinfo.handlers = &shm_handlers;
   iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
   rtems_filesystem_location_add_to_mt_entry( &iop->pathinfo );
@@ -211,12 +281,12 @@ int shm_open( const char *name, int oflag, mode_t mode )
 
 static const rtems_filesystem_file_handlers_r shm_handlers = {
   .open_h = rtems_filesystem_default_open,
-  .close_h = rtems_filesystem_default_close,
-  .read_h = rtems_filesystem_default_read,
+  .close_h = shm_close,
+  .read_h = shm_read,
   .write_h = rtems_filesystem_default_write,
   .ioctl_h = rtems_filesystem_default_ioctl,
   .lseek_h = rtems_filesystem_default_lseek,
-  .fstat_h = rtems_filesystem_default_fstat,
+  .fstat_h = shm_fstat,
   .ftruncate_h = shm_ftruncate,
   .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
   .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
diff --git a/cpukit/posix/src/shmunlink.c b/cpukit/posix/src/shmunlink.c
index f559922..c4f4b4e 100644
--- a/cpukit/posix/src/shmunlink.c
+++ b/cpukit/posix/src/shmunlink.c
@@ -18,9 +18,35 @@
 #include <errno.h>
 #include <rtems/seterr.h>
 
+#include <rtems/posix/shmimpl.h>
+
 int shm_unlink( const char *name )
 {
-  (void) name;
+  Objects_Get_by_name_error obj_err;
+  int err;
+  POSIX_Shm_Control *shm;
+
+  shm = _POSIX_Shm_Get_by_name( name, 0, &obj_err );
+  switch ( obj_err ) {
+    case OBJECTS_GET_BY_NAME_INVALID_NAME:
+      err = ENOENT;
+      break;
+
+    case OBJECTS_GET_BY_NAME_NAME_TOO_LONG:
+      err = ENAMETOOLONG;
+      break;
 
-  rtems_set_errno_and_return_minus_one( ENOENT );
+    case OBJECTS_GET_BY_NAME_NO_OBJECT:
+    default:
+      _Objects_Close( &_POSIX_Shm_Information, &shm->Object );
+      if ( shm->reference_count == 0 ) {
+        /* TODO: need to make sure this counts mmaps too! */
+        /* only remove the shm object if no references exist to it. */
+        _POSIX_Shm_Free( shm );
+      }
+      break;
+  }
+  if ( err != 0 )
+    rtems_set_errno_and_return_minus_one( err );
+  return 0;
 }
diff --git a/cpukit/posix/src/shmwkspace.c b/cpukit/posix/src/shmwkspace.c
index 59573dd..54df9c5 100644
--- a/cpukit/posix/src/shmwkspace.c
+++ b/cpukit/posix/src/shmwkspace.c
@@ -57,15 +57,22 @@ int _POSIX_Shm_Object_resize_from_workspace(
   return err;
 }
 
-void *_POSIX_Shm_Object_mmap_from_workspace(
+int _POSIX_Shm_Object_read_from_workspace(
   POSIX_Shm_Control *shm,
-  size_t len,
-  int prot,
-  int flags,
-  off_t off
+  void *buf,
+  size_t count
 )
 {
-  return NULL;
+  if ( shm == NULL || shm->shm_object.handle == NULL )
+    return 0;
+
+  if ( shm->shm_object.size < count ) {
+    count = shm->shm_object.size;
+  }
+
+  memcpy( buf, shm->shm_object.handle, count );
+
+  return count;
 }
 
 
-- 
1.9.1



More information about the devel mailing list