[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