From e4ad14cc789090290550e3aa9640e4969037e8b7 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 12 Feb 2019 12:19:38 +0100 Subject: score: Avoid some deadlocks in _Once() Recursive usage of the same pthread_once_t results now in a deadlock. Previously, an error of EINVAL was returned. This usage scenario is invalid according to the POSIX pthread_once() specification. Close #3334. --- testsuites/psxtests/psxonce01/init.c | 82 ++++++++++++++++++++++++----- testsuites/psxtests/psxonce01/psxonce01.scn | 15 +++--- testsuites/psxtests/psxonce01/system.h | 2 +- 3 files changed, 80 insertions(+), 19 deletions(-) (limited to 'testsuites/psxtests') diff --git a/testsuites/psxtests/psxonce01/init.c b/testsuites/psxtests/psxonce01/init.c index 1c90769d38..41ff5b146b 100644 --- a/testsuites/psxtests/psxonce01/init.c +++ b/testsuites/psxtests/psxonce01/init.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2019 embedded brains GmbH + * Copyright (C) 2019 Sebastian Huber + * * COPYRIGHT (c) 1989-2009. * On-Line Applications Research Corporation (OAR). * @@ -16,16 +19,11 @@ const char rtems_test_name[] = "PSXONCE 1"; -static pthread_once_t nesting_once = PTHREAD_ONCE_INIT; +static pthread_once_t once_a = PTHREAD_ONCE_INIT; -static void Test_init_routine_nesting( void ) -{ - int status; - puts( "Test_init_routine_nesting: invoked" ); - puts( "Test_init_routine_nesting: pthread_once - EINVAL (init_routine_nesting does not execute)" ); - status = pthread_once( &nesting_once, Test_init_routine_nesting ); - rtems_test_assert( status == EINVAL ); -} +static pthread_once_t once_b = PTHREAD_ONCE_INIT; + +static rtems_id master; static int test_init_routine_call_counter = 0; @@ -35,6 +33,66 @@ static void Test_init_routine( void ) ++test_init_routine_call_counter; } +static void routine_b( void ) +{ + rtems_status_code sc; + + rtems_test_assert( test_init_routine_call_counter == 2 ); + ++test_init_routine_call_counter; + + sc = rtems_event_send( master, RTEMS_EVENT_0 ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); +} + +static void use_b( rtems_task_argument arg ) +{ + int status; + + (void) arg; + + status = pthread_once( &once_b, routine_b ); + rtems_test_assert( status == 0 ); + + rtems_task_exit(); +} + +static void routine_a( void ) +{ + rtems_status_code sc; + rtems_id id; + rtems_event_set events; + + rtems_test_assert( test_init_routine_call_counter == 1 ); + ++test_init_routine_call_counter; + + master = rtems_task_self(); + + sc = rtems_task_create( + rtems_build_name( 'T', 'A', 'S', 'K' ), + RTEMS_MINIMUM_PRIORITY, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &id + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start( id, use_b, 0 ); + assert( sc == RTEMS_SUCCESSFUL ); + + events = 0; + sc = rtems_event_receive( + RTEMS_EVENT_0, + RTEMS_EVENT_ANY | RTEMS_WAIT, + RTEMS_NO_TIMEOUT, + &events + ); + rtems_test_assert( sc == RTEMS_SUCCESSFUL ); + rtems_test_assert( events == RTEMS_EVENT_0 ); + + rtems_test_assert( test_init_routine_call_counter == 3 ); +} + rtems_task Init(rtems_task_argument argument) { int status; @@ -62,9 +120,9 @@ rtems_task Init(rtems_task_argument argument) printf( "Init: call counter: %d\n", test_init_routine_call_counter ); rtems_test_assert( test_init_routine_call_counter == 1 ); - puts( "Init: pthread_once - SUCCESSFUL (init_routine_nesting executes)" ); - status = pthread_once( &nesting_once, Test_init_routine_nesting ); - rtems_test_assert( !status ); + status = pthread_once( &once_a, routine_a ); + rtems_test_assert( status == 0 ); + rtems_test_assert( test_init_routine_call_counter == 3 ); TEST_END(); rtems_test_exit( 0 ); diff --git a/testsuites/psxtests/psxonce01/psxonce01.scn b/testsuites/psxtests/psxonce01/psxonce01.scn index 2c5d47d2d1..a7afa154cb 100644 --- a/testsuites/psxtests/psxonce01/psxonce01.scn +++ b/testsuites/psxtests/psxonce01/psxonce01.scn @@ -1,11 +1,14 @@ - - -*** TEST POSIX ONCE 01 *** -Init: pthread_once - SUCCESSFUL (init_routine_nesting executes) -Test_init_routine_nesting: invoked +*** BEGIN OF TEST PSXONCE 1 *** +*** TEST VERSION: 5.0.0.e214ff4b636011bd149e3683c89aa982e361fd1c +*** TEST STATE: EXPECTED-PASS +*** TEST BUILD: +*** TEST TOOLS: 7.4.0 20181206 (RTEMS 5, RSB c41b9d0df7e5b4a5056ca50c2534380a44e92769, Newlib 3e24fbf6f) Init: pthread_once - EINVAL (NULL once_control) Init: pthread_once - EINVAL (NULL init_routine) Init: pthread_once - SUCCESSFUL (init_routine executes) Test_init_routine: invoked +Init: call counter: 1 Init: pthread_once - SUCCESSFUL (init_routine does not execute) -*** END OF TEST POSIX ONCE 01 *** +Init: call counter: 1 + +*** END OF TEST PSXONCE 1 *** diff --git a/testsuites/psxtests/psxonce01/system.h b/testsuites/psxtests/psxonce01/system.h index 10d611b86d..fe95285d5f 100644 --- a/testsuites/psxtests/psxonce01/system.h +++ b/testsuites/psxtests/psxonce01/system.h @@ -21,7 +21,7 @@ #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION -#define CONFIGURE_MAXIMUM_TASKS 1 +#define CONFIGURE_MAXIMUM_TASKS 2 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE -- cgit v1.2.3