--- 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 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel