[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