[rtems commit] posix: shared memory support

Gedare Bloom gedare at rtems.org
Fri Jan 13 17:40:02 UTC 2017


Module:    rtems
Branch:    master
Commit:    ba77628250ae7158db363fc0d7886ebd43e9cb69
Changeset: http://git.rtems.org/rtems/commit/?id=ba77628250ae7158db363fc0d7886ebd43e9cb69

Author:    Gedare Bloom <gedare at rtems.org>
Date:      Fri Aug 12 15:25:10 2016 -0400

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 +
 testsuites/psxtests/Makefile.am               |   4 +-
 testsuites/psxtests/configure.ac              |   2 +
 testsuites/psxtests/psxshm01/Makefile.am      |  22 ++
 testsuites/psxtests/psxshm01/init.c           |  91 +++++++++
 testsuites/psxtests/psxshm01/psxshm01.scn     |   0
 testsuites/psxtests/psxshm01/system.h         |  29 +++
 testsuites/psxtests/psxshm02/Makefile.am      |  22 ++
 testsuites/psxtests/psxshm02/init.c           |  91 +++++++++
 testsuites/psxtests/psxshm02/psxshm02.scn     |   0
 testsuites/psxtests/psxshm02/system.h         |  38 ++++
 testsuites/sptests/spsysinit01/init.c         |  17 ++
 25 files changed, 1196 insertions(+), 10 deletions(-)

diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am
index 53faace..48617cc 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 11c73c2..6c74216 100644
--- a/cpukit/posix/include/rtems/posix/config.h
+++ b/cpukit/posix/include/rtems/posix/config.h
@@ -111,6 +111,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 0000000..dfdd58e
--- /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 <rtems/score/object.h>
+#include <rtems/score/threadq.h>
+
+#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 0000000..207f50f
--- /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 <rtems/fs.h>
+#include <rtems/libio.h>
+#include <rtems/posix/posixapi.h>
+#include <rtems/posix/shm.h>
+#include <rtems/score/objectimpl.h>
+
+#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 41f7a26..1269280 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 0000000..7dca6bb
--- /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 <sys/stat.h>
+#include <fcntl.h>
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/libio.h>
+#include <rtems/sysinit.h>
+#include <rtems/posix/shmimpl.h>
+
+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 0000000..3449c15
--- /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 <errno.h>
+#include <stdlib.h>
+#include <rtems/posix/shmimpl.h>
+
+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 abac3f4..fec443a 100644
--- a/cpukit/posix/src/shmopen.c
+++ b/cpukit/posix/src/shmopen.c
@@ -16,13 +16,288 @@
 
 #include <sys/mman.h>
 #include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <rtems/libio_.h>
 #include <rtems/seterr.h>
 
+#include <rtems/posix/shmimpl.h>
+#include <rtems/score/wkspace.h>
+
+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 f559922..ab18450 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 = 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 0000000..6d6cd21
--- /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 <errno.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/shmimpl.h>
+
+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 07bfb1b..4d3b1cb 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 12eec53..e00d079 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 <rtems/posix/pthread.h>
   #include <rtems/posix/rwlock.h>
   #include <rtems/posix/semaphore.h>
+  #include <rtems/posix/shm.h>
   #include <rtems/posix/threadsup.h>
   #include <rtems/posix/timer.h>
 
@@ -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 1ec688a..cd36ce6 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 a0ab17c..7923385 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
diff --git a/testsuites/psxtests/Makefile.am b/testsuites/psxtests/Makefile.am
index e0ce36f..2bea8ab 100644
--- a/testsuites/psxtests/Makefile.am
+++ b/testsuites/psxtests/Makefile.am
@@ -10,8 +10,8 @@ _SUBDIRS += psxhdrs psx01 psx02 psx03 psx04 psx05 psx06 psx07 psx08 psx09 \
     psxcancel psxcancel01 psxclassic01 psxcleanup psxcleanup01 \
     psxconcurrency01 psxcond01 psxcond02 psxconfig01 psxenosys \
     psxitimer psxmsgq01 psxmsgq02 psxmsgq03 psxmsgq04 \
-    psxmutexattr01 psxobj01 psxrwlock01 psxsem01 psxsignal01 psxsignal02 \
-    psxsignal03 psxsignal04 psxsignal05 psxsignal06 \
+    psxmutexattr01 psxobj01 psxrwlock01 psxsem01 psxshm01 psxshm02 \
+    psxsignal01 psxsignal02 psxsignal03 psxsignal04 psxsignal05 psxsignal06 \
     psxspin01 psxsysconf \
     psxtime psxtimer01 psxtimer02 psxualarm psxusleep psxfatal01 psxfatal02 \
     psxintrcritical01 psxstack01 psxstack02 \
diff --git a/testsuites/psxtests/configure.ac b/testsuites/psxtests/configure.ac
index 7401258..77af14e 100644
--- a/testsuites/psxtests/configure.ac
+++ b/testsuites/psxtests/configure.ac
@@ -188,6 +188,8 @@ psxreaddir/Makefile
 psxrdwrv/Makefile
 psxrwlock01/Makefile
 psxsem01/Makefile
+psxshm01/Makefile
+psxshm02/Makefile
 psxsignal01/Makefile
 psxsignal02/Makefile
 psxsignal03/Makefile
diff --git a/testsuites/psxtests/psxshm01/Makefile.am b/testsuites/psxtests/psxshm01/Makefile.am
new file mode 100644
index 0000000..7082a50
--- /dev/null
+++ b/testsuites/psxtests/psxshm01/Makefile.am
@@ -0,0 +1,22 @@
+
+rtems_tests_PROGRAMS = psxshm01
+psxshm01_SOURCES = init.c system.h
+
+dist_rtems_tests_DATA = psxshm01.scn
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+
+AM_CPPFLAGS += -I$(top_srcdir)/include
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxshm01_OBJECTS)
+LINK_LIBS = $(psxshm01_LDLIBS)
+
+psxshm01$(EXEEXT): $(psxshm01_OBJECTS) $(psxshm01_DEPENDENCIES)
+	@rm -f psxshm01$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxshm01/init.c b/testsuites/psxtests/psxshm01/init.c
new file mode 100644
index 0000000..24c9b96
--- /dev/null
+++ b/testsuites/psxtests/psxshm01/init.c
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+/*
+ * From http://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define CONFIGURE_INIT
+#include "system.h"
+#include "pritime.h"
+
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+const char rtems_test_name[] = "PSX SHM01";
+
+#define MAX_LEN 10000
+struct region {        /* Defines "structure" of shared memory */
+  int len;
+  char buf[MAX_LEN];
+};
+
+void *POSIX_Init(
+  void *argument
+)
+{
+  struct region *p;
+  int fd;
+  int err;
+  char *name = "/shm";
+
+  TEST_BEGIN();
+
+  puts( "Init: shm_open" );
+  fd = shm_open( name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
+  if ( fd == -1 ) {
+    printf ( "Error: %s\n", strerror(errno) );
+    rtems_test_assert( fd != -1 );
+  }
+
+  puts( "Init: ftruncate" );
+  err = ftruncate( fd, sizeof( struct region ) );
+  if ( err == -1 ) {
+    printf ( "Error: %s\n", strerror(errno) );
+    rtems_test_assert( err != -1 );
+  }
+
+  puts( "Init: mmap" );
+  p = mmap(
+    NULL,
+    sizeof( struct region ),
+    PROT_READ | PROT_WRITE, MAP_SHARED,
+    fd,
+    0
+  );
+  rtems_test_assert( p != MAP_FAILED );
+
+  puts( "Init: write to mapped region" );
+  p->len = MAX_LEN;
+
+  puts( "Init: munmap" );
+  err = munmap( p, sizeof( struct region ) );
+  if ( err == -1 ) {
+    printf ( "Error: %s\n", strerror(errno) );
+    rtems_test_assert( err != -1 );
+  }
+
+  puts( "Init: close" );
+  err = close( fd );
+  if ( err == -1 ) {
+    printf ( "Error: %s\n", strerror(errno) );
+    rtems_test_assert( err != -1 );
+  }
+
+  TEST_END();
+
+  rtems_test_exit(0);
+  return 0;
+}
diff --git a/testsuites/psxtests/psxshm01/psxshm01.scn b/testsuites/psxtests/psxshm01/psxshm01.scn
new file mode 100644
index 0000000..e69de29
diff --git a/testsuites/psxtests/psxshm01/system.h b/testsuites/psxtests/psxshm01/system.h
new file mode 100644
index 0000000..531a926
--- /dev/null
+++ b/testsuites/psxtests/psxshm01/system.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#include <pmacros.h>
+#include <unistd.h>
+#include <errno.h>
+
+void *POSIX_Init(
+  void *argument
+);
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS     1
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 10
+#define CONFIGURE_MAXIMUM_POSIX_SHMS 1
+#define CONFIGURE_MEMORY_OVERHEAD 10
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/psxtests/psxshm02/Makefile.am b/testsuites/psxtests/psxshm02/Makefile.am
new file mode 100644
index 0000000..c174b0c
--- /dev/null
+++ b/testsuites/psxtests/psxshm02/Makefile.am
@@ -0,0 +1,22 @@
+
+rtems_tests_PROGRAMS = psxshm02
+psxshm02_SOURCES = init.c system.h
+
+dist_rtems_tests_DATA = psxshm02.scn
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+
+AM_CPPFLAGS += -I$(top_srcdir)/include
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxshm02_OBJECTS)
+LINK_LIBS = $(psxshm02_LDLIBS)
+
+psxshm02$(EXEEXT): $(psxshm02_OBJECTS) $(psxshm02_DEPENDENCIES)
+	@rm -f psxshm02$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxshm02/init.c b/testsuites/psxtests/psxshm02/init.c
new file mode 100644
index 0000000..29dea97
--- /dev/null
+++ b/testsuites/psxtests/psxshm02/init.c
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+/*
+ * From http://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define CONFIGURE_INIT
+#include "system.h"
+#include "pritime.h"
+
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+const char rtems_test_name[] = "PSX SHM02";
+
+#define MAX_LEN 10000
+struct region {        /* Defines "structure" of shared memory */
+  int len;
+  char buf[MAX_LEN];
+};
+
+void *POSIX_Init(
+  void *argument
+)
+{
+  struct region *p;
+  int fd;
+  int err;
+  char *name = "/shm";
+
+  TEST_BEGIN();
+
+  puts( "Init: shm_open" );
+  fd = shm_open( name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
+  if ( fd == -1 ) {
+    printf ( "Error: %s\n", strerror(errno) );
+    rtems_test_assert( fd != -1 );
+  }
+
+  puts( "Init: ftruncate" );
+  err = ftruncate( fd, sizeof( struct region ) );
+  if ( err == -1 ) {
+    printf ( "Error: %s\n", strerror(errno) );
+    rtems_test_assert( err != -1 );
+  }
+
+  puts( "Init: mmap" );
+  p = mmap(
+    NULL,
+    sizeof( struct region ),
+    PROT_READ | PROT_WRITE, MAP_SHARED,
+    fd,
+    0
+  );
+  rtems_test_assert( p != MAP_FAILED );
+
+  puts( "Init: write to mapped region" );
+  p->len = MAX_LEN;
+
+  puts( "Init: munmap" );
+  err = munmap( p, sizeof( struct region ) );
+  if ( err == -1 ) {
+    printf ( "Error: %s\n", strerror(errno) );
+    rtems_test_assert( err != -1 );
+  }
+
+  puts( "Init: close" );
+  err = close( fd );
+  if ( err == -1 ) {
+    printf ( "Error: %s\n", strerror(errno) );
+    rtems_test_assert( err != -1 );
+  }
+
+  TEST_END();
+
+  rtems_test_exit(0);
+  return 0;
+}
diff --git a/testsuites/psxtests/psxshm02/psxshm02.scn b/testsuites/psxtests/psxshm02/psxshm02.scn
new file mode 100644
index 0000000..e69de29
diff --git a/testsuites/psxtests/psxshm02/system.h b/testsuites/psxtests/psxshm02/system.h
new file mode 100644
index 0000000..d02c87f
--- /dev/null
+++ b/testsuites/psxtests/psxshm02/system.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include <pmacros.h>
+#include <unistd.h>
+#include <errno.h>
+
+void *POSIX_Init(
+  void *argument
+);
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS     1
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 10
+#define CONFIGURE_MAXIMUM_POSIX_SHMS 1
+#define CONFIGURE_MEMORY_OVERHEAD 10
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#include <rtems/posix/shm.h>
+const POSIX_Shm_Object_operations _POSIX_Shm_Object_operations = {
+  _POSIX_Shm_Object_create_from_heap,
+  _POSIX_Shm_Object_resize_from_heap,
+  _POSIX_Shm_Object_delete_from_heap,
+  _POSIX_Shm_Object_read_from_heap
+};
+#define CONFIGURE_HAS_OWN_POSIX_SHM_OBJECT_OPERATIONS
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/sptests/spsysinit01/init.c b/testsuites/sptests/spsysinit01/init.c
index b81fbab..15072c3 100644
--- a/testsuites/sptests/spsysinit01/init.c
+++ b/testsuites/sptests/spsysinit01/init.c
@@ -43,6 +43,7 @@
 #include <rtems/posix/pthreadimpl.h>
 #include <rtems/posix/rwlockimpl.h>
 #include <rtems/posix/semaphoreimpl.h>
+#include <rtems/posix/shmimpl.h>
 #include <rtems/posix/timerimpl.h>
 #endif /* RTEMS_POSIX_API */
 #include <rtems/posix/keyimpl.h>
@@ -117,6 +118,8 @@ typedef enum {
   POSIX_BARRIER_POST,
   POSIX_RWLOCK_PRE,
   POSIX_RWLOCK_POST,
+  POSIX_SHM_PRE,
+  POSIX_SHM_POST,
   POSIX_CLEANUP_PRE,
   POSIX_CLEANUP_POST,
 #endif /* RTEMS_POSIX_API */
@@ -524,6 +527,18 @@ LAST(RTEMS_SYSINIT_POSIX_RWLOCK)
   next_step(POSIX_RWLOCK_POST);
 }
 
+FIRST(RTEMS_SYSINIT_POSIX_SHM)
+{
+  assert(_POSIX_Shm_Information.maximum == 0);
+  next_step(POSIX_SHM_PRE);
+}
+
+LAST(RTEMS_SYSINIT_POSIX_SHM)
+{
+  assert(_POSIX_Shm_Information.maximum != 0);
+  next_step(POSIX_SHM_POST);
+}
+
 static size_t user_extensions_pre_posix_cleanup;
 
 FIRST(RTEMS_SYSINIT_POSIX_CLEANUP)
@@ -752,6 +767,8 @@ static void *POSIX_Init(void *arg)
 
 #define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 1
 
+#define CONFIGURE_MAXIMUM_POSIX_SHMS 1
+
 #define CONFIGURE_MAXIMUM_POSIX_TIMERS 1
 
 #define CONFIGURE_MAXIMUM_POSIX_THREADS 1



More information about the vc mailing list