Update #2752. --- cpukit/score/src/threadhandler.c | 15 ++++--- testsuites/sptests/spextensions01/init.c | 74 ++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 7 deletions(-)
diff --git a/cpukit/score/src/threadhandler.c b/cpukit/score/src/threadhandler.c index 2fa6d07..9f004b9 100644 --- a/cpukit/score/src/threadhandler.c +++ b/cpukit/score/src/threadhandler.c @@ -59,13 +59,6 @@ void _Thread_Handler( void ) _Thread_Restore_fp( executing ); /* - * Take care that 'begin' extensions get to complete before - * 'switch' extensions can run. This means must keep dispatch - * disabled until all 'begin' extensions complete. - */ - _User_extensions_Thread_begin( executing ); - - /* * Do not use the level of the thread control block, since it has a * different format. */ @@ -86,6 +79,14 @@ void _Thread_Handler( void ) _Thread_Do_dispatch( cpu_self, level ); /* + * Invoke the thread begin extensions in the context of the thread entry + * function with thread dispatching enabled. This enables use of dynamic + * memory allocation, creation of POSIX keys and use of C++ thread local + * storage. Blocking synchronization primitives are allowed also. + */ + _User_extensions_Thread_begin( executing ); + + /* * RTEMS supports multiple APIs and each API can define a different * thread/task prototype. The following code supports invoking the * user thread entry point using the prototype expected. diff --git a/testsuites/sptests/spextensions01/init.c b/testsuites/sptests/spextensions01/init.c index 091d66f..7eac443 100644 --- a/testsuites/sptests/spextensions01/init.c +++ b/testsuites/sptests/spextensions01/init.c @@ -25,6 +25,10 @@ #include <bsp.h> +#include <rtems/score/apimutex.h> +#include <rtems/score/sysstate.h> +#include <rtems/score/threaddispatch.h> + const char rtems_test_name[] = "SPEXTENSIONS 1"; static int counter; @@ -33,6 +37,48 @@ static int active_extensions = 2; static rtems_id master_task; +static bool before_multitasking(void) +{ + return _System_state_Is_before_multitasking(_System_state_Get()); +} + +static bool life_protected(void) +{ + Thread_Control *executing; + + executing = _Thread_Get_executing(); + + return (executing->Life.state & THREAD_LIFE_PROTECTED) != 0; +} + +static void assert_normal_thread_context(void) +{ + assert(_Thread_Dispatch_is_enabled()); + assert(!_RTEMS_Allocator_is_owner()); + assert(!life_protected()); +} + +static void assert_life_protected_thread_context(void) +{ + assert(_Thread_Dispatch_is_enabled() || before_multitasking()); + assert(!_RTEMS_Allocator_is_owner()); + assert(life_protected() || before_multitasking()); +} + +static void assert_allocator_protected_thread_context(void) +{ + assert(_Thread_Dispatch_is_enabled() || before_multitasking()); + assert(_RTEMS_Allocator_is_owner()); + assert(life_protected() || before_multitasking()); +} + +static void assert_thread_dispatch_disabled_context(void) +{ + assert(!_Thread_Dispatch_is_enabled()); + assert(!_RTEMS_Allocator_is_owner()); + assert(!life_protected()); +} + static void assert_static_order(int index) { assert((counter % active_extensions) == index); @@ -54,22 +100,26 @@ static void assert_reverse_order(int index) static bool zero_thread_create(rtems_tcb *a, rtems_tcb *b) { assert_static_order(0); + assert_allocator_protected_thread_context(); return true; } static void zero_thread_start(rtems_tcb *a, rtems_tcb *b) { assert_static_order(0); + assert_thread_dispatch_disabled_context(); } static void zero_thread_restart(rtems_tcb *a, rtems_tcb *b) { assert_static_order(0); + assert_life_protected_thread_context(); } static void zero_thread_delete(rtems_tcb *a, rtems_tcb *b) { assert_static_order(0); + assert_allocator_protected_thread_context(); } static void zero_thread_switch(rtems_tcb *a, rtems_tcb *b) @@ -80,11 +130,13 @@ static void zero_thread_switch(rtems_tcb *a, rtems_tcb *b) static void zero_thread_begin(rtems_tcb *a) { assert_static_order(0); + assert_normal_thread_context(); } static void zero_thread_exitted(rtems_tcb *a) { assert_static_order(0); + assert_normal_thread_context(); } static void zero_fatal( @@ -101,27 +153,32 @@ static void zero_fatal( static void zero_thread_terminate(rtems_tcb *a) { assert_static_order(0); + assert_life_protected_thread_context(); } static bool one_thread_create(rtems_tcb *a, rtems_tcb *b) { assert_static_order(1); + assert_allocator_protected_thread_context(); return true; } static void one_thread_start(rtems_tcb *a, rtems_tcb *b) { assert_static_order(1); + assert_thread_dispatch_disabled_context(); } static void one_thread_restart(rtems_tcb *a, rtems_tcb *b) { assert_static_order(1); + assert_life_protected_thread_context(); } static void one_thread_delete(rtems_tcb *a, rtems_tcb *b) { assert_static_order(1); + assert_allocator_protected_thread_context(); } static void one_thread_switch(rtems_tcb *a, rtems_tcb *b) @@ -132,11 +189,13 @@ static void one_thread_switch(rtems_tcb *a, rtems_tcb *b) static void one_thread_begin(rtems_tcb *a) { assert_static_order(1); + assert_normal_thread_context(); } static void one_thread_exitted(rtems_tcb *a) { assert_static_order(1); + assert_normal_thread_context(); } static void one_fatal( @@ -153,27 +212,32 @@ static void one_fatal( static void one_thread_terminate(rtems_tcb *a) { assert_static_order(1); + assert_life_protected_thread_context(); } static bool two_thread_create(rtems_tcb *a, rtems_tcb *b) { assert_forward_order(2); + assert_allocator_protected_thread_context(); return true; } static void two_thread_start(rtems_tcb *a, rtems_tcb *b) { assert_forward_order(2); + assert_thread_dispatch_disabled_context(); } static void two_thread_restart(rtems_tcb *a, rtems_tcb *b) { assert_static_order(2); + assert_life_protected_thread_context(); } static void two_thread_delete(rtems_tcb *a, rtems_tcb *b) { assert_reverse_order(2); + assert_allocator_protected_thread_context(); } static void two_thread_switch(rtems_tcb *a, rtems_tcb *b) @@ -184,11 +248,13 @@ static void two_thread_switch(rtems_tcb *a, rtems_tcb *b) static void two_thread_begin(rtems_tcb *a) { assert_forward_order(2); + assert_normal_thread_context(); } static void two_thread_exitted(rtems_tcb *a) { assert_forward_order(2); + assert_normal_thread_context(); } static void two_fatal( @@ -207,27 +273,32 @@ static void two_fatal( static void two_thread_terminate(rtems_tcb *a) { assert_forward_order(2); + assert_life_protected_thread_context(); } static bool three_thread_create(rtems_tcb *a, rtems_tcb *b) { assert_forward_order(3); + assert_allocator_protected_thread_context(); return true; } static void three_thread_start(rtems_tcb *a, rtems_tcb *b) { assert_forward_order(3); + assert_thread_dispatch_disabled_context(); } static void three_thread_restart(rtems_tcb *a, rtems_tcb *b) { assert_static_order(3); + assert_life_protected_thread_context(); } static void three_thread_delete(rtems_tcb *a, rtems_tcb *b) { assert_reverse_order(3); + assert_allocator_protected_thread_context(); } static void three_thread_switch(rtems_tcb *a, rtems_tcb *b) @@ -238,11 +309,13 @@ static void three_thread_switch(rtems_tcb *a, rtems_tcb *b) static void three_thread_begin(rtems_tcb *a) { assert_forward_order(3); + assert_normal_thread_context(); } static void three_thread_exitted(rtems_tcb *a) { assert_forward_order(3); + assert_normal_thread_context(); } static void three_fatal( @@ -259,6 +332,7 @@ static void three_fatal( static void three_thread_terminate(rtems_tcb *a) { assert_forward_order(3); + assert_life_protected_thread_context(); } #define ZERO \ -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel