[PATCH v4 3/3] Thread stack sharing

Utkarsh Rai utkarsh.rai60 at gmail.com
Sat Aug 22 15:19:01 UTC 2020


For the design details of the stack sharing mechanism please refer to the following post -
https://gsoc2020memoryprotection.blogspot.com/2020/08/high-level-design-and-implementation-of.html
---
 cpukit/posix/src/mmap.c                       |  39 ++++-
 cpukit/posix/src/shmopen.c                    |  62 +-------
 .../samples/thread_stack_sharing/init.c       | 136 ++++++++++++++++++
 3 files changed, 173 insertions(+), 64 deletions(-)
 create mode 100644 testsuites/samples/thread_stack_sharing/init.c

diff --git a/cpukit/posix/src/mmap.c b/cpukit/posix/src/mmap.c
index 176c6e4fe8..1d4b65cea6 100644
--- a/cpukit/posix/src/mmap.c
+++ b/cpukit/posix/src/mmap.c
@@ -28,7 +28,27 @@
 
 #include <rtems/posix/mmanimpl.h>
 #include <rtems/posix/shmimpl.h>
+#include <rtems/score/stackprotection.h>
+#include <rtems/score/memoryprotection.h>
 
+static uint32_t mmap_flag_translate(int prot)
+{
+  int prot_read;
+  int prot_write;
+  int memory_flag;
+
+  prot_read = (prot_read & PROT_READ) == PROT_READ;
+  prot_write = (prot_write & PROT_WRITE) == PROT_WRITE;
+ 
+  if(prot_read){
+    memory_flag |= ( RTEMS_READ_ONLY| RTEMS_MEMORY_CACHED );
+  }
+  if(prot_write) {
+    memory_flag |= ( RTEMS_READ_WRITE | RTEMS_MEMORY_CACHED );
+  }
+
+  return memory_flag;
+}
 
 /**
  * mmap chain of mappings.
@@ -50,6 +70,9 @@ void *mmap(
   bool            map_private;
   bool            is_shared_shm;
   int             err;
+  uint32_t memory_flags;
+  uintptr_t shared_stack_address;
+  int status;
 
   map_fixed = (flags & MAP_FIXED) == MAP_FIXED;
   map_anonymous = (flags & MAP_ANON) == MAP_ANON;
@@ -67,7 +90,10 @@ void *mmap(
 
   /*
    * We can provide read, write and execute because the memory in RTEMS does
-   * not normally have protections but we cannot hide access to memory.
+   * not normally have protections but we cannot hide access to memory. For
+   * thread-stack protection we can provide no-access option, but stacks are
+   * implicitly isolated and it makes no sense to specify no-access option for
+   * already isolated stacks.
    */
   if ( prot == PROT_NONE ) {
     errno = ENOTSUP;
@@ -292,9 +318,16 @@ void *mmap(
       free( mapping );
       return MAP_FAILED;
     }
+  /**
+    * We share thread-stacks only when we have a shared memory object and map
+    * shared flag set
+    */
+    memory_flags = mmap_flag_translate( prot );
+    status = _Stackprotection_Share_stack( mapping->addr, addr, len,memory_flags );
+  }
+  if(status == RTEMS_INVALID_ADDRESS ) {
+    rtems_chain_append_unprotected( &mmap_mappings, &mapping->node );
   }
-
-  rtems_chain_append_unprotected( &mmap_mappings, &mapping->node );
 
   mmap_mappings_lock_release( );
 
diff --git a/cpukit/posix/src/shmopen.c b/cpukit/posix/src/shmopen.c
index 1e7fda66f8..b439592fd7 100644
--- a/cpukit/posix/src/shmopen.c
+++ b/cpukit/posix/src/shmopen.c
@@ -19,13 +19,11 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/stat.h>
-#include <string.h>
 
 #include <rtems/libio_.h>
 #include <rtems/seterr.h>
 
 #include <rtems/posix/shmimpl.h>
-#include <rtems/posix/pthread.h>
 #include <rtems/score/wkspace.h>
 #include <rtems/sysinit.h>
 
@@ -93,61 +91,6 @@ static int shm_ftruncate( rtems_libio_t *iop, off_t length )
   return 0;
 }
 
-static int shm_stack_ftruncate ( rtems_libio_t *iop, off_t length )
-{
- int err;
- Objects_Id id;
- Objects_Name_or_id_lookup_errors obj_err;
- Thread_Control *Control;
- ISR_lock_Context lock_context;
- size_t size;
- char *name;
- POSIX_Shm_Control *shm = iop_to_shm ( iop );
-
- name = shm->Object.name.name_p;
-
- /** We assign fixed pattern of naming for thread-stacks, and treat them 
-   *  accordingly.
-   */
-  if( strncmp( name, "/taskfs/", 8) == 0 ) {
-    /**
-     * Obtain the object id of the thread and then get the thread control block
-     * corresponding to that id. 
-     */
-    obj_err = _Objects_Name_to_id_u32(
-            &_POSIX_Threads_Information.Objects,
-           _Objects_Build_name( name[8], name[9], name[10], name[11]),
-            RTEMS_LOCAL,
-            &id
-            );
-    Control = _Thread_Get( id, &lock_context );
-     if( Control != NULL ) {
-       shm->shm_object.handle = Control->Start.Initial_stack.area;
-       if( length != Control->Start.Initial_stack.size) {
-         return ENOMEM;
-       }
-     } else {
-       return ENOMEM;
-     }
-  }else{
-
-  _Objects_Allocator_lock();
-
-  err = (*shm->shm_object.ops->object_resize)( &shm->shm_object, length );
-
-  if ( err != 0 ) {
-    _Objects_Allocator_unlock();
-    rtems_set_errno_and_return_minus_one( err );
-  }
-
-  _POSIX_Shm_Update_mtime_ctime( shm );
-
-  _Objects_Allocator_unlock();
-  return 0;
-  }
-
-}
-
 static int shm_close( rtems_libio_t *iop )
 {
   POSIX_Shm_Control *shm = iop_to_shm( iop );
@@ -363,11 +306,7 @@ static const rtems_filesystem_file_handlers_r shm_handlers = {
   .ioctl_h = rtems_filesystem_default_ioctl,
   .lseek_h = rtems_filesystem_default_lseek,
   .fstat_h = shm_fstat,
-  #if defined ( RTEMS_THREAD_STACK_PROTECTION )
-  .ftruncate_h = shm_stack_ftruncate,
-  #else
   .ftruncate_h = shm_ftruncate,
-  #endif
   .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
   .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
   .fcntl_h = rtems_filesystem_default_fcntl,
@@ -388,3 +327,4 @@ RTEMS_SYSINIT_ITEM(
   RTEMS_SYSINIT_POSIX_SHM,
   RTEMS_SYSINIT_ORDER_MIDDLE
 );
+
diff --git a/testsuites/samples/thread_stack_sharing/init.c b/testsuites/samples/thread_stack_sharing/init.c
new file mode 100644
index 0000000000..5bb7d01418
--- /dev/null
+++ b/testsuites/samples/thread_stack_sharing/init.c
@@ -0,0 +1,136 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <tmacros.h>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <rtems/score/memoryprotection.h>
+
+const char rtems_test_name[] = " THREAD STACK SHARING ";
+
+void* Test_routine( void* arg )
+{
+    
+}
+
+void *POSIX_Init( void *argument ) 
+{
+  void *stack_addr1;
+  void *stack_addr2;
+  void* addr;
+  size_t stack_size1;
+  size_t stack_size2;
+  pthread_t id1;
+  pthread_t id2;
+  pthread_attr_t attr1;  
+  pthread_attr_t attr2;
+  int fd;
+  char name[4] = "0x01";
+  char thread_name[13] = "/taskfs/0x01";
+
+  TEST_BEGIN();
+ 
+ /*
+  *  We set the stack size as 8Kb.
+  */
+  stack_size1 = 8192;
+  stack_size2 = 8192;
+
+  /*
+   * We allocate page-aligned memory of the stack  from the application.
+   */
+  posix_memalign(&stack_addr1, sysconf( _SC_PAGESIZE ), stack_size1 );
+  posix_memalign(&stack_addr2, sysconf( _SC_PAGESIZE ), stack_size2 );
+
+  pthread_attr_init( &attr1 );  
+  pthread_attr_init( &attr2 );
+ 
+ /*
+  * We set the stack size and address of the thread from the application itself
+  */
+  pthread_attr_setstack( &attr1, stack_addr1, stack_size1 );
+  pthread_attr_setstack( &attr2, stack_addr2, stack_size2 );
+
+  pthread_create( &id1, &attr1, Test_routine, NULL );
+
+ /*
+  * We set the memory attributes of the stack from the application.
+  */
+  _Memory_protection_Set_entries( stack_addr1, stack_size1, RTEMS_READ_ONLY | RTEMS_MEMORY_CACHED );
+
+    pthread_create( &id2, &attr2, Test_routine, NULL );
+  _Memory_protection_Set_entries( stack_addr2, stack_size2, RTEMS_READ_ONLY | RTEMS_MEMORY_CACHED );
+
+  /*
+   * Add leading "/taskfs/" to denote thread-stack name.
+   */ 
+  strlcat( thread_name, name, 4);
+
+  /* 
+  * Set the name of the thread object same as that of the shared memory object name
+  */
+  rtems_object_set_name( id1, name);
+
+  /*
+   * Create a shared memory object of the  stack we want to share with
+   * appropraite permissions. We share the stack with read and write permission
+   */
+  fd = shm_open( thread_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
+  
+  /*
+   * Truncate the size of the file to the size of the stack.
+   */
+  ftruncate( fd, stack_size1 );
+  
+  /*
+   * For sharing the stack we specify the address of the
+   * thread-stack we want to share with, the size of the shared stack,
+   * protection and access flags, file descriptor of the shared memory objcet
+   */
+  addr = mmap( stack_addr2, stack_size1, PROT_READ | PROT_WRITE, O_RDWR, fd, 0 );
+  rtems_test_assert( addr != NULL );
+
+  pthread_join( id1, NULL );
+  /*
+   * Write to the stack address of thread1 after it has been switched out.
+   */ 
+  memset( stack_addr1, 0, stack_size1 );
+
+  pthread_join( id2, NULL );
+   /*
+   * Write to the stack address of thread2 after it has been switched out.
+   */  
+  memset( stack_addr2, 0, stack_size2 );
+
+
+  TEST_END();
+  rtems_test_exit( 0 );
+}
+
+/* configuration information */
+
+#define CONFIGURE_INIT
+
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS        4
+
+#define CONFIGURE_MAXIMUM_POSIX_SHMS           2
+
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 10
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_TASK_STACK_ALLOCATOR_INIT  bsp_stack_allocate_init
+#define CONFIGURE_TASK_STACK_ALLOCATOR       bsp_stack_allocate
+#define CONFIGURE_TASK_STACK_DEALLOCATOR     bsp_stack_free
+
+#include <bsp/stackalloc.h>
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
\ No newline at end of file
-- 
2.17.1



More information about the devel mailing list