From ba77628250ae7158db363fc0d7886ebd43e9cb69 Mon Sep 17 00:00:00 2001 From: Gedare Bloom Date: Fri, 12 Aug 2016 15:25:10 -0400 Subject: posix: shared memory support Add POSIX shared memory manager (Shm). Includes a hook-based approach for the backing memory storage that defaults to the Workspace, and a test is provided using the heap. A test is also provided for the basic use of mmap'ing a shared memory object. This test currently fails at the mmap stage due to no support for mmap. --- cpukit/posix/Makefile.am | 5 + cpukit/posix/include/rtems/posix/config.h | 5 + cpukit/posix/include/rtems/posix/shm.h | 182 +++++++++++++++++ cpukit/posix/include/rtems/posix/shmimpl.h | 115 +++++++++++ cpukit/posix/preinstall.am | 8 + cpukit/posix/src/shm.c | 48 +++++ cpukit/posix/src/shmheap.c | 90 ++++++++ cpukit/posix/src/shmopen.c | 283 +++++++++++++++++++++++++- cpukit/posix/src/shmunlink.c | 30 ++- cpukit/posix/src/shmwkspace.c | 78 +++++++ cpukit/rtems/src/rtemsobjectgetapiclassname.c | 1 + cpukit/sapi/include/confdefs.h | 39 ++++ cpukit/score/include/rtems/score/objectimpl.h | 5 +- cpukit/score/include/rtems/sysinit.h | 1 + 14 files changed, 882 insertions(+), 8 deletions(-) create mode 100644 cpukit/posix/include/rtems/posix/shm.h create mode 100644 cpukit/posix/include/rtems/posix/shmimpl.h create mode 100644 cpukit/posix/src/shm.c create mode 100644 cpukit/posix/src/shmheap.c create mode 100644 cpukit/posix/src/shmwkspace.c (limited to 'cpukit') diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am index 53faacee70..48617ccadf 100644 --- a/cpukit/posix/Makefile.am +++ b/cpukit/posix/Makefile.am @@ -41,6 +41,8 @@ include_rtems_posix_HEADERS += include/rtems/posix/psignalimpl.h include_rtems_posix_HEADERS += include/rtems/posix/pthread.h include_rtems_posix_HEADERS += include/rtems/posix/pthreadimpl.h include_rtems_posix_HEADERS += include/rtems/posix/ptimer.h +include_rtems_posix_HEADERS += include/rtems/posix/shm.h +include_rtems_posix_HEADERS += include/rtems/posix/shmimpl.h include_rtems_posix_HEADERS += include/rtems/posix/semaphore.h include_rtems_posix_HEADERS += include/rtems/posix/semaphoreimpl.h include_rtems_posix_HEADERS += include/rtems/posix/threadsup.h @@ -98,8 +100,11 @@ libposix_a_SOURCES += src/munlockall.c libposix_a_SOURCES += src/munlock.c libposix_a_SOURCES += src/munmap.c libposix_a_SOURCES += src/posix_madvise.c +libposix_a_SOURCES += src/shm.c +libposix_a_SOURCES += src/shmheap.c libposix_a_SOURCES += src/shmopen.c libposix_a_SOURCES += src/shmunlink.c +libposix_a_SOURCES += src/shmwkspace.c ## MESSAGE_QUEUE_C_FILES libposix_a_SOURCES += src/mqueue.c src/mqueueclose.c \ diff --git a/cpukit/posix/include/rtems/posix/config.h b/cpukit/posix/include/rtems/posix/config.h index 11c73c2b2f..6c74216dc2 100644 --- a/cpukit/posix/include/rtems/posix/config.h +++ b/cpukit/posix/include/rtems/posix/config.h @@ -110,6 +110,11 @@ typedef struct { */ uint32_t maximum_rwlocks; + /** + * Maximum configured number of POSIX Shared memory objects. + */ + uint32_t maximum_shms; + /** * This field contains the number of POSIX API Initialization * threads listed in @a User_initialization_thread_table. diff --git a/cpukit/posix/include/rtems/posix/shm.h b/cpukit/posix/include/rtems/posix/shm.h new file mode 100644 index 0000000000..dfdd58ed2a --- /dev/null +++ b/cpukit/posix/include/rtems/posix/shm.h @@ -0,0 +1,182 @@ +/** + * @file + * + * @brief Internal Support for POSIX Shared Memory + */ + +/* + * Copyright (c) 2016 Gedare Bloom. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef _RTEMS_POSIX_SHM_H +#define _RTEMS_POSIX_SHM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup POSIXShmPrivate POSIX Shared Memory Private Support + * + * @ingroup POSIXAPI + * + * Internal implementation support for POSIX shared memory. + * @{ + */ +typedef struct POSIX_Shm_Object_operations POSIX_Shm_Object_operations; +extern const POSIX_Shm_Object_operations _POSIX_Shm_Object_operations; + +/** + * @brief Encapsulation for the storage and manipulation of shm objects. + */ +typedef struct { + /** + * @brief The handle is private for finding object storage. + */ + void *handle; + + /** + * @brief The number of bytes allocated to the object. A size of 0 with + * a handle of NULL means no object is allocated. + */ + size_t size; + + /** + * @brief Implementation-specific operations on shm objects. + */ + const POSIX_Shm_Object_operations *ops; +} POSIX_Shm_Object; + +/** + * @brief Operations on POSIX Shared Memory Objects. + */ +struct POSIX_Shm_Object_operations { + /** + * @brief Allocates a new @a shm_obj with initial @a size. + * + * New shared memory is initialized to zeroes. + * + * Returns 0 for success. + */ + int ( *object_create ) ( POSIX_Shm_Object *shm_obj, size_t size ); + + /** + * @brief Changes the @a shm_obj size to @a size. + * + * Zeroes out the portion of the shared memory object that shrinks or grows. + * + * Returns 0 for success. + */ + int ( *object_resize ) ( POSIX_Shm_Object *shm_obj, size_t size ); + + /** + * @brief Deletes the @a shm_obj. + * + * Zeroes out the memory. + * + * Returns 0 for success. + */ + int ( *object_delete ) ( POSIX_Shm_Object *shm_obj ); + + /** + * @brief Copies up to @count bytes of the @a shm_obj data into @a buf. + * + * Returns the number of bytes read (copied) into @a buf. + */ + int ( *object_read ) ( POSIX_Shm_Object *shm_obj, void *buf, size_t count ); +}; + +/** + * @brief Control for a POSIX Shared Memory Object + */ +typedef struct { + Objects_Control Object; + Thread_queue_Control Wait_queue; + + int reference_count; + + POSIX_Shm_Object shm_object; + + uid_t uid; + gid_t gid; + mode_t mode; + + time_t atime; + time_t mtime; + time_t ctime; +} POSIX_Shm_Control; + +/** + * @brief object_create operation for shm objects stored in RTEMS Workspace. + */ +extern int _POSIX_Shm_Object_create_from_workspace( + POSIX_Shm_Object *shm_obj, + size_t size +); + +/** + * @brief object_delete operation for shm objects stored in RTEMS Workspace. + */ +extern int _POSIX_Shm_Object_delete_from_workspace( POSIX_Shm_Object *shm_obj ); + +/** + * @brief object_resize operation for shm objects stored in RTEMS Workspace. + */ +extern int _POSIX_Shm_Object_resize_from_workspace( + POSIX_Shm_Object *shm_obj, + size_t size +); + +/** + * @brief object_read operation for shm objects stored in RTEMS Workspace. + */ +extern int _POSIX_Shm_Object_read_from_workspace( + POSIX_Shm_Object *shm_obj, + void *buf, + size_t count +); + +/** + * @brief object_create operation for shm objects stored in C program heap. + */ +extern int _POSIX_Shm_Object_create_from_heap( + POSIX_Shm_Object *shm_obj, + size_t size +); + +/** + * @brief object_delete operation for shm objects stored in C program heap. + */ +extern int _POSIX_Shm_Object_delete_from_heap( POSIX_Shm_Object *shm_obj ); + +/** + * @brief object_resize operation for shm objects stored in C program heap. + */ +extern int _POSIX_Shm_Object_resize_from_heap( + POSIX_Shm_Object *shm_obj, + size_t size +); + +/** + * @brief object_read operation for shm objects stored in C program heap. + */ +extern int _POSIX_Shm_Object_read_from_heap( + POSIX_Shm_Object *shm_obj, + void *buf, + size_t count +); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cpukit/posix/include/rtems/posix/shmimpl.h b/cpukit/posix/include/rtems/posix/shmimpl.h new file mode 100644 index 0000000000..207f50fc95 --- /dev/null +++ b/cpukit/posix/include/rtems/posix/shmimpl.h @@ -0,0 +1,115 @@ +/** + * @file + * + * @brief Private Support Information for POSIX Shared Memory + * + */ + +/* + * Copyright (c) 2016 Gedare Bloom. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef _RTEMS_POSIX_SHMIMPL_H +#define _RTEMS_POSIX_SHMIMPL_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @ingroup POSIXShmPrivate + * @{ + */ + +extern Objects_Information _POSIX_Shm_Information; + +RTEMS_INLINE_ROUTINE void _POSIX_Shm_Acquire( + POSIX_Shm_Control *the_shm, + Thread_queue_Context *queue_context +) +{ + _Thread_queue_Acquire( + &the_shm->Wait_queue, + queue_context + ); +} + +RTEMS_INLINE_ROUTINE void _POSIX_Shm_Release( + POSIX_Shm_Control *the_shm, + Thread_queue_Context *queue_context +) +{ + _Thread_queue_Release( &the_shm->Wait_queue, queue_context ); +} + +RTEMS_INLINE_ROUTINE POSIX_Shm_Control *_POSIX_Shm_Allocate_unprotected( void ) +{ + return (POSIX_Shm_Control *) + _Objects_Allocate_unprotected( &_POSIX_Shm_Information ); +} + +/** + * @brief POSIX Shared Memory Free + * + * This routine frees a shm control block. + */ +RTEMS_INLINE_ROUTINE void _POSIX_Shm_Free ( + POSIX_Shm_Control *the_shm +) +{ + _Objects_Free( &_POSIX_Shm_Information, &the_shm->Object ); +} + +RTEMS_INLINE_ROUTINE POSIX_Shm_Control *_POSIX_Shm_Get_by_name( + const char *name, + size_t *name_length_p, + Objects_Get_by_name_error *error +) +{ + return (POSIX_Shm_Control *) _Objects_Get_by_name( + &_POSIX_Shm_Information, + name, + name_length_p, + error + ); +} + +RTEMS_INLINE_ROUTINE void _POSIX_Shm_Update_mtime_ctime( + POSIX_Shm_Control *shm +) +{ + struct timeval now; + gettimeofday( &now, 0 ); + shm->mtime = now.tv_sec; + 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 +} +#endif + +#endif diff --git a/cpukit/posix/preinstall.am b/cpukit/posix/preinstall.am index 41f7a26782..1269280652 100644 --- a/cpukit/posix/preinstall.am +++ b/cpukit/posix/preinstall.am @@ -108,6 +108,14 @@ $(PROJECT_INCLUDE)/rtems/posix/ptimer.h: include/rtems/posix/ptimer.h $(PROJECT_ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/ptimer.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/ptimer.h +$(PROJECT_INCLUDE)/rtems/posix/shm.h: include/rtems/posix/shm.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/shm.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/shm.h + +$(PROJECT_INCLUDE)/rtems/posix/shmimpl.h: include/rtems/posix/shmimpl.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/shmimpl.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/shmimpl.h + $(PROJECT_INCLUDE)/rtems/posix/semaphore.h: include/rtems/posix/semaphore.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphore.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphore.h diff --git a/cpukit/posix/src/shm.c b/cpukit/posix/src/shm.c new file mode 100644 index 0000000000..7dca6bbc1d --- /dev/null +++ b/cpukit/posix/src/shm.c @@ -0,0 +1,48 @@ +/** + * @file + */ + +/* + * Copyright (c) 2016 Gedare Bloom. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include +#include + +Objects_Information _POSIX_Shm_Information; + +static void _POSIX_Shm_Manager_initialization( void ) +{ + _Objects_Initialize_information( + &_POSIX_Shm_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_SHMS, /* object class */ + Configuration_POSIX_API.maximum_shms, + /* maximum objects of this class */ + sizeof( POSIX_Shm_Control ), + /* size of this object's control block */ + true, /* true if names for this object are strings */ + _POSIX_PATH_MAX, /* maximum length of each object's name */ + NULL /* Proxy extraction support callout */ + ); +} + +RTEMS_SYSINIT_ITEM( + _POSIX_Shm_Manager_initialization, + RTEMS_SYSINIT_POSIX_SHM, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/cpukit/posix/src/shmheap.c b/cpukit/posix/src/shmheap.c new file mode 100644 index 0000000000..3449c15cca --- /dev/null +++ b/cpukit/posix/src/shmheap.c @@ -0,0 +1,90 @@ +/** + * @file + */ + +/* + * Copyright (c) 2016 Gedare Bloom. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +int _POSIX_Shm_Object_create_from_heap( + POSIX_Shm_Object *shm_obj, + size_t size +) +{ + void *p = calloc( 1, size ); /* get zero'd memory */ + if ( p != NULL ) { + shm_obj->handle = p; + shm_obj->size = size; + } else { + errno = EIO; + } + return 0; +} + +int _POSIX_Shm_Object_delete_from_heap( POSIX_Shm_Object *shm_obj ) +{ + /* zero out memory before releasing it. */ + memset( shm_obj->handle, 0, shm_obj->size ); + free( shm_obj->handle ); + shm_obj->handle = NULL; + shm_obj->size = 0; + return 0; +} + +int _POSIX_Shm_Object_resize_from_heap( + POSIX_Shm_Object *shm_obj, + size_t size +) +{ + void *p; + int err = 0; + + if ( size < shm_obj->size ) { + /* zero out if shrinking */ + p = (void*)((uintptr_t)shm_obj->handle + (uintptr_t)size); + memset( p, 0, shm_obj->size - size ); + } + p = realloc( shm_obj->handle, size ); + if ( p != NULL ) { + shm_obj->handle = p; + if ( size > shm_obj->size ) { + /* initialize added memory */ + memset( p, 0, size - shm_obj->size ); + } + shm_obj->size = size; + } else { + err = EIO; + } + return err; +} + +int _POSIX_Shm_Object_read_from_heap( + POSIX_Shm_Object *shm_obj, + void *buf, + size_t count +) +{ + if ( shm_obj == NULL || shm_obj->handle == NULL ) + return 0; + + if ( shm_obj->size < count ) { + count = shm_obj->size; + } + + memcpy( buf, shm_obj->handle, count ); + + return count; +} + diff --git a/cpukit/posix/src/shmopen.c b/cpukit/posix/src/shmopen.c index abac3f4057..fec443abba 100644 --- a/cpukit/posix/src/shmopen.c +++ b/cpukit/posix/src/shmopen.c @@ -16,13 +16,288 @@ #include #include +#include +#include +#include + +#include #include +#include +#include + +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_atime = shm->atime; + buf->st_mtime = shm->mtime; + buf->st_ctime = shm->ctime; + + return 0; +} + +/* read() is unspecified for shared memory objects */ +static ssize_t shm_read( rtems_libio_t *iop, void *buffer, size_t count ) +{ + Thread_queue_Context queue_context; + ssize_t bytes_read; + POSIX_Shm_Control *shm = iop_to_shm( iop ); + + _Thread_queue_Context_initialize( &queue_context ); + _POSIX_Shm_Acquire( shm, &queue_context ); + bytes_read = (*shm->shm_object.ops->object_read)( + &shm->shm_object, + 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; + int err; + POSIX_Shm_Control *shm = iop_to_shm( iop ); + + _Thread_queue_Context_initialize( &queue_context ); + _POSIX_Shm_Acquire( shm, &queue_context ); + + err = (*shm->shm_object.ops->object_resize)( &shm->shm_object, length ); + + if ( err != 0 ) { + _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 *obj; + 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->shm_object ) != 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_ctx ); + } + } + 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, + int oflag, + mode_t mode, + int *error +) +{ + POSIX_Shm_Control *shm; + char *name; + struct timeval tv; + + /* Reject any name without a leading slash. */ + if ( name_arg[0] != '/' ) { + *error = EINVAL; + return NULL; + } + + /* Only create the object if requested. */ + if ( ( oflag & O_CREAT ) != O_CREAT ) { + *error = ENOENT; + return NULL; + } + + name = _Workspace_String_duplicate( name_arg, name_len ); + if ( name == NULL ) { + *error = ENOSPC; + return NULL; + } + + shm = _POSIX_Shm_Allocate_unprotected(); + if ( shm == NULL ) { + _Workspace_Free( name ); + *error = ENFILE; + return NULL; + } + + gettimeofday( &tv, 0 ); + + shm->reference_count = 1; + shm->shm_object.handle = NULL; + shm->shm_object.size = 0; + shm->shm_object.ops = &_POSIX_Shm_Object_operations; + shm->mode = mode & ~rtems_filesystem_umask; + shm->uid = geteuid(); + shm->gid = getegid(); + shm->atime = (time_t) tv.tv_sec; + shm->mtime = (time_t) tv.tv_sec; + shm->ctime = (time_t) tv.tv_sec; + + _Objects_Open_string( &_POSIX_Shm_Information, &shm->Object, name ); + + return shm; +} + +static inline bool shm_access_ok( POSIX_Shm_Control *shm, int oflag ) +{ + int flags; + if ( oflag & O_RDONLY ) { + flags = RTEMS_FS_PERMS_READ; + } else { + flags = RTEMS_FS_PERMS_WRITE; + } + return rtems_filesystem_check_access( flags, shm->mode, shm->uid, shm->gid ); +} + +static inline int shm_check_oflag( int oflag ) +{ + if ( ( oflag & O_ACCMODE ) != O_RDONLY && ( oflag & O_ACCMODE ) != O_RDWR ) { + rtems_set_errno_and_return_minus_one( EACCES ); + } + + if ( ( oflag & ~( O_RDONLY | O_RDWR | O_CREAT | O_EXCL | O_TRUNC ) ) != 0 ) { + rtems_set_errno_and_return_minus_one( EACCES ); + } + + if ( ( oflag & O_TRUNC ) != 0 && ( oflag & O_ACCMODE ) != O_RDWR ) { + rtems_set_errno_and_return_minus_one( EACCES ); + } + return 0; +} + int shm_open( const char *name, int oflag, mode_t mode ) { - (void) name; - (void) oflag; - (void) mode; + int err = 0; + int fd; + rtems_libio_t *iop; + POSIX_Shm_Control *shm; + size_t len; + Objects_Get_by_name_error obj_err; + + if ( shm_check_oflag( oflag ) != 0 ) { + return -1; + } + + iop = rtems_libio_allocate(); + if ( iop == NULL ) { + rtems_set_errno_and_return_minus_one( EMFILE ); + } - rtems_set_errno_and_return_minus_one( EINVAL ); + _Objects_Allocator_lock(); + shm = _POSIX_Shm_Get_by_name( name, &len, &obj_err ); + + if ( shm == NULL ) { + switch ( obj_err ) { + case OBJECTS_GET_BY_NAME_INVALID_NAME: + err = EINVAL; + break; + + case OBJECTS_GET_BY_NAME_NAME_TOO_LONG: + err = ENAMETOOLONG; + break; + + case OBJECTS_GET_BY_NAME_NO_OBJECT: + default: + shm = shm_allocate(name, len, oflag, mode, &err); + break; + } + } else { /* shm exists */ + 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 { + ++shm->reference_count; + } + } + _Objects_Allocator_unlock(); + if ( err != 0 ) { + rtems_libio_free( iop ); + rtems_set_errno_and_return_minus_one( err ); + } + + if ( oflag & O_TRUNC ) { + err = shm_ftruncate( iop, 0 ); + (void) err; /* ignore truncate error */ + } + + fd = rtems_libio_iop_to_descriptor( iop ); + iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC; + if ( oflag & O_RDONLY ) { + iop->flags |= LIBIO_FLAGS_READ; + } else { + iop->flags |= LIBIO_FLAGS_READ_WRITE; + } + 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 ); + + return fd; } + +static const rtems_filesystem_file_handlers_r shm_handlers = { + .open_h = rtems_filesystem_default_open, + .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 = shm_fstat, + .ftruncate_h = shm_ftruncate, + .fsync_h = rtems_filesystem_default_fsync_or_fdatasync, + .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync, + .fcntl_h = rtems_filesystem_default_fcntl, + .kqfilter_h = rtems_filesystem_default_kqfilter, + .poll_h = rtems_filesystem_default_poll, + .readv_h = rtems_filesystem_default_readv, + .writev_h = rtems_filesystem_default_writev +}; diff --git a/cpukit/posix/src/shmunlink.c b/cpukit/posix/src/shmunlink.c index f5599227b1..ab18450dc7 100644 --- a/cpukit/posix/src/shmunlink.c +++ b/cpukit/posix/src/shmunlink.c @@ -18,9 +18,35 @@ #include #include +#include + int shm_unlink( const char *name ) { - (void) name; + Objects_Get_by_name_error obj_err; + int err = 0; + 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 new file mode 100644 index 0000000000..6d6cd211a5 --- /dev/null +++ b/cpukit/posix/src/shmwkspace.c @@ -0,0 +1,78 @@ +/** + * @file + */ + +/* + * Copyright (c) 2016 Gedare Bloom. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +int _POSIX_Shm_Object_create_from_workspace( + POSIX_Shm_Object *shm_obj, + size_t size +) +{ + shm_obj->handle = _Workspace_Allocate_or_fatal_error( size ); + memset( shm_obj->handle, 0, size ); + shm_obj->size = size; + return 0; +} + +int _POSIX_Shm_Object_delete_from_workspace( POSIX_Shm_Object *shm_obj ) +{ + /* zero out memory before releasing it. */ + memset( shm_obj->handle, 0, shm_obj->size ); + _Workspace_Free( shm_obj->handle ); + shm_obj->handle = NULL; + shm_obj->size = 0; + return 0; +} + +int _POSIX_Shm_Object_resize_from_workspace( + POSIX_Shm_Object *shm_obj, + size_t size +) +{ + int err; + + if ( size == 0 ) { + err = _POSIX_Shm_Object_delete_from_workspace( shm_obj ); + } else if ( shm_obj->handle == NULL && shm_obj->size == 0 ) { + err = _POSIX_Shm_Object_create_from_workspace( shm_obj, size ); + } else { + /* Refuse to resize a workspace object. */ + err = EIO; + } + return err; +} + +int _POSIX_Shm_Object_read_from_workspace( + POSIX_Shm_Object *shm_obj, + void *buf, + size_t count +) +{ + if ( shm_obj == NULL || shm_obj->handle == NULL ) + return 0; + + if ( shm_obj->size < count ) { + count = shm_obj->size; + } + + memcpy( buf, shm_obj->handle, count ); + + return count; +} + + diff --git a/cpukit/rtems/src/rtemsobjectgetapiclassname.c b/cpukit/rtems/src/rtemsobjectgetapiclassname.c index 07bfb1b3a0..4d3b1cb37c 100644 --- a/cpukit/rtems/src/rtemsobjectgetapiclassname.c +++ b/cpukit/rtems/src/rtemsobjectgetapiclassname.c @@ -55,6 +55,7 @@ static const rtems_assoc_t rtems_object_api_posix_assoc[] = { { "Timer", OBJECTS_POSIX_TIMERS, 0}, { "Barrier", OBJECTS_POSIX_BARRIERS, 0}, { "RWLock", OBJECTS_POSIX_RWLOCKS, 0}, + { "Shared Memory", OBJECTS_POSIX_SHMS, 0}, { NULL, 0, 0} }; #endif diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h index 12eec53c0f..e00d079554 100644 --- a/cpukit/sapi/include/confdefs.h +++ b/cpukit/sapi/include/confdefs.h @@ -2068,6 +2068,10 @@ extern rtems_initialization_tasks_table Initialization_tasks[]; #define CONFIGURE_MAXIMUM_POSIX_RWLOCKS \ rtems_resource_unlimited(CONFIGURE_UNLIMITED_ALLOCATION_SIZE) #endif + #if !defined(CONFIGURE_MAXIMUM_POSIX_SHMS) + #define CONFIGURE_MAXIMUM_POSIX_SHMS \ + rtems_resource_unlimited(CONFIGURE_UNLIMITED_ALLOCATION_SIZE) + #endif #endif /* RTEMS_POSIX_API */ #endif /* CONFIGURE_UNLIMITED_OBJECTS */ @@ -2464,6 +2468,7 @@ extern rtems_initialization_tasks_table Initialization_tasks[]; #include #include #include + #include #include #include @@ -2626,6 +2631,34 @@ extern rtems_initialization_tasks_table Initialization_tasks[]; #define CONFIGURE_MEMORY_FOR_POSIX_RWLOCKS(_rwlocks) \ _Configure_Object_RAM(_rwlocks, sizeof(POSIX_RWLock_Control) ) + /** + * Configure the maximum number of POSIX shared memory objects. + */ + #if !defined(CONFIGURE_MAXIMUM_POSIX_SHMS) + #define CONFIGURE_MAXIMUM_POSIX_SHMS 0 + #else + #ifdef CONFIGURE_INIT + #if !defined(CONFIGURE_HAS_OWN_POSIX_SHM_OBJECT_OPERATIONS) + const POSIX_Shm_Object_operations _POSIX_Shm_Object_operations = { + _POSIX_Shm_Object_create_from_workspace, + _POSIX_Shm_Object_resize_from_workspace, + _POSIX_Shm_Object_delete_from_workspace, + _POSIX_Shm_Object_read_from_workspace + }; + #endif + #endif + #endif + + /** + * This macro is calculated to specify the memory required for + * POSIX API shared memory. + * + * This is an internal parameter. + */ + #define CONFIGURE_MEMORY_FOR_POSIX_SHMS(_shms) \ + _Configure_POSIX_Named_Object_RAM(_shms, sizeof(POSIX_Shm_Control) ) + + #ifdef CONFIGURE_POSIX_INIT_THREAD_TABLE #ifdef CONFIGURE_POSIX_HAS_OWN_INIT_THREAD_TABLE @@ -2851,6 +2884,8 @@ extern rtems_initialization_tasks_table Initialization_tasks[]; CONFIGURE_MEMORY_FOR_POSIX_BARRIERS(CONFIGURE_MAXIMUM_POSIX_BARRIERS) + \ CONFIGURE_MEMORY_FOR_POSIX_RWLOCKS( \ CONFIGURE_MAXIMUM_POSIX_RWLOCKS) + \ + CONFIGURE_MEMORY_FOR_POSIX_SHMS( \ + CONFIGURE_MAXIMUM_POSIX_SHMS) + \ CONFIGURE_MEMORY_FOR_POSIX_TIMERS(CONFIGURE_MAXIMUM_POSIX_TIMERS)) #else /** @@ -3333,6 +3368,7 @@ extern rtems_initialization_tasks_table Initialization_tasks[]; CONFIGURE_MAXIMUM_POSIX_SEMAPHORES, CONFIGURE_MAXIMUM_POSIX_BARRIERS, CONFIGURE_MAXIMUM_POSIX_RWLOCKS, + CONFIGURE_MAXIMUM_POSIX_SHMS, CONFIGURE_POSIX_INIT_THREAD_TABLE_SIZE, CONFIGURE_POSIX_INIT_THREAD_TABLE_NAME }; @@ -3548,6 +3584,7 @@ extern rtems_initialization_tasks_table Initialization_tasks[]; uint32_t POSIX_SEMAPHORES; uint32_t POSIX_BARRIERS; uint32_t POSIX_RWLOCKS; + uint32_t POSIX_SHMS; #endif /* Stack space sizes */ @@ -3601,6 +3638,7 @@ extern rtems_initialization_tasks_table Initialization_tasks[]; CONFIGURE_MEMORY_FOR_POSIX_SEMAPHORES( CONFIGURE_MAXIMUM_POSIX_SEMAPHORES ), CONFIGURE_MEMORY_FOR_POSIX_BARRIERS( CONFIGURE_MAXIMUM_POSIX_BARRIERS ), CONFIGURE_MEMORY_FOR_POSIX_RWLOCKS( CONFIGURE_MAXIMUM_POSIX_RWLOCKS ), + CONFIGURE_MEMORY_FOR_POSIX_SHMS( CONFIGURE_MAXIMUM_POSIX_SHMS ), CONFIGURE_MEMORY_FOR_POSIX_TIMERS( CONFIGURE_MAXIMUM_POSIX_TIMERS ), #endif @@ -3672,6 +3710,7 @@ extern rtems_initialization_tasks_table Initialization_tasks[]; (CONFIGURE_MAXIMUM_POSIX_SEMAPHORES != 0) || \ (CONFIGURE_MAXIMUM_POSIX_BARRIERS != 0) || \ (CONFIGURE_MAXIMUM_POSIX_RWLOCKS != 0) || \ + (CONFIGURE_MAXIMUM_POSIX_SHMS != 0) || \ defined(CONFIGURE_POSIX_INIT_THREAD_TABLE)) #error "CONFIGURATION ERROR: POSIX API support not configured!!" #endif diff --git a/cpukit/score/include/rtems/score/objectimpl.h b/cpukit/score/include/rtems/score/objectimpl.h index 1ec688a793..cd36ce6316 100644 --- a/cpukit/score/include/rtems/score/objectimpl.h +++ b/cpukit/score/include/rtems/score/objectimpl.h @@ -92,11 +92,12 @@ typedef enum { OBJECTS_POSIX_CONDITION_VARIABLES = 8, OBJECTS_POSIX_TIMERS = 9, OBJECTS_POSIX_BARRIERS = 10, - OBJECTS_POSIX_RWLOCKS = 11 + OBJECTS_POSIX_RWLOCKS = 11, + OBJECTS_POSIX_SHMS = 12 } Objects_POSIX_API; /** This macro is used to generically specify the last API index. */ -#define OBJECTS_POSIX_CLASSES_LAST OBJECTS_POSIX_RWLOCKS +#define OBJECTS_POSIX_CLASSES_LAST OBJECTS_POSIX_SHMS /* * For fake objects, which have an object identifier, but no objects diff --git a/cpukit/score/include/rtems/sysinit.h b/cpukit/score/include/rtems/sysinit.h index a0ab17c8ec..7923385cd1 100644 --- a/cpukit/score/include/rtems/sysinit.h +++ b/cpukit/score/include/rtems/sysinit.h @@ -54,6 +54,7 @@ extern "C" { #define RTEMS_SYSINIT_POSIX_TIMER 000366 #define RTEMS_SYSINIT_POSIX_BARRIER 000367 #define RTEMS_SYSINIT_POSIX_RWLOCK 000368 +#define RTEMS_SYSINIT_POSIX_SHM 000369 #define RTEMS_SYSINIT_POSIX_CLEANUP 00036a #define RTEMS_SYSINIT_POSIX_KEYS 00036b #define RTEMS_SYSINIT_IDLE_THREADS 000380 -- cgit v1.2.3