[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