[PATCH v4 3/3] Thread stack sharing

Gedare Bloom gedare at rtems.org
Sat Aug 22 18:16:51 UTC 2020


On Sat, Aug 22, 2020 at 9:19 AM Utkarsh Rai <utkarsh.rai60 at gmail.com> wrote:
>
> 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){
ws

> +    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 );
ws

This function doesn't exist. This patch won't compile. Normally I
would stop reviewing here.

The _Stack_protection_Share_stack() function returns 0 or -1. It
doesn't return a status code.

> +  }
> +  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;
> -  }
> -
> -}
> -
Why are you removing this code?

>  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