[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