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

Gedare Bloom gedare at rtems.org
Fri Aug 26 20:25:30 UTC 2016


I'm contemplating adapting the mmap support from
https://git.rtems.org/chrisj/rtl.git/tree/mmap.c

This patch adds most of the plumbing necessary so that the libc calls
used there should work correctly. So far that code implicitly only
supports MAP_PRIVATE.

On Fri, Aug 26, 2016 at 4:17 PM, Gedare Bloom <gedare at rtems.org> wrote:
> ---
>  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