score: PR788: Add INTERNAL_ERROR_RESOURCE_IN_USE

Issue a fatal error in case a thread is deleted which still owns
resources (e.g. a binary semaphore with priority inheritance or ceiling
protocol).  The resource count must be checked quite late since RTEMS
task variable destructors, POSIX key destructors, POSIX cleanup handler,
the Newlib thread termination extension or other thread termination
extensions may release resources.  In this context it would be quite
difficult to return an error status to the caller.

An alternative would be to place threads with a non-zero resource count
not on the zombie chain.  Thus we have a resource leak instead of a
fatal error.  The terminator thread can see this error if we return an
RTEMS_RESOURCE_IN_USE status for the rtems_task_delete() for example.
This commit is contained in:
Sebastian Huber
2014-04-03 11:13:25 +02:00
parent 499492793b
commit 3f5f2ce229
14 changed files with 101 additions and 18 deletions
+2 -1
View File
@@ -51,7 +51,8 @@ static const char *const internal_error_text[] = {
"INTERNAL_ERROR_GXX_KEY_ADD_FAILED",
"INTERNAL_ERROR_GXX_MUTEX_INIT_FAILED",
"INTERNAL_ERROR_NO_MEMORY_FOR_HEAP",
"INTERNAL_ERROR_CPU_ISR_INSTALL_VECTOR"
"INTERNAL_ERROR_CPU_ISR_INSTALL_VECTOR",
"INTERNAL_ERROR_RESOURCE_IN_USE"
};
const char *rtems_internal_error_text( rtems_fatal_code error )
+2 -1
View File
@@ -147,7 +147,8 @@ typedef enum {
INTERNAL_ERROR_GXX_KEY_ADD_FAILED,
INTERNAL_ERROR_GXX_MUTEX_INIT_FAILED,
INTERNAL_ERROR_NO_MEMORY_FOR_HEAP,
INTERNAL_ERROR_CPU_ISR_INSTALL_VECTOR
INTERNAL_ERROR_CPU_ISR_INSTALL_VECTOR,
INTERNAL_ERROR_RESOURCE_IN_USE
} Internal_errors_Core_list;
typedef uint32_t Internal_errors_t;
+8
View File
@@ -47,6 +47,14 @@ static void _Thread_Make_zombie( Thread_Control *the_thread )
ISR_lock_Context lock_context;
Thread_Zombie_control *zombies = &_Thread_Zombies;
if ( the_thread->resource_count != 0 ) {
_Terminate(
INTERNAL_ERROR_CORE,
false,
INTERNAL_ERROR_RESOURCE_IN_USE
);
}
_Thread_Set_state( the_thread, STATES_ZOMBIE );
_Thread_queue_Extract_with_proxy( the_thread );
_Watchdog_Remove( &the_thread->Timer );
+1
View File
@@ -33,6 +33,7 @@ SUBDIRS = \
spsignal_err01 spport_err01 spmsgq_err01 spmsgq_err02 spsem_err01 \
spsem_err02 sptask_err01 spevent_err03 sptask_err03 sptask_err02 \
sptask_err04 spclock_err01
SUBDIRS += spfatal28
SUBDIRS += spthreadlife01
SUBDIRS += spprofiling01
SUBDIRS += spcache01
+1
View File
@@ -36,6 +36,7 @@ AM_CONDITIONAL(HAS_CPUSET,test x"${ac_cv_header_sys_cpuset_h}" = x"yes")
# Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile
spfatal28/Makefile
spthreadlife01/Makefile
spprofiling01/Makefile
spcache01/Makefile
+19
View File
@@ -0,0 +1,19 @@
rtems_tests_PROGRAMS = spfatal28
spfatal28_SOURCES = ../spfatal_support/init.c ../spfatal_support/system.h testcase.h
dist_rtems_tests_DATA = spfatal28.scn spfatal28.doc
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../automake/compile.am
include $(top_srcdir)/../automake/leaf.am
AM_CPPFLAGS += -I$(top_srcdir)/../support/include
LINK_OBJS = $(spfatal28_OBJECTS)
LINK_LIBS = $(spfatal28_LDLIBS)
spfatal28$(EXEEXT): $(spfatal28_OBJECTS) $(spfatal28_DEPENDENCIES)
@rm -f spfatal28$(EXEEXT)
$(make-exe)
include $(top_srcdir)/../automake/local.am
@@ -0,0 +1,12 @@
This file describes the directives and concepts tested by this test set.
test set name: spfatal28
directives:
- rtems_task_delete()
concepts:
- Ensure that deletion of a task with a semaphore in use leads to a fatal
error.
@@ -0,0 +1,3 @@
*** BEGIN OF TEST SPFATAL 28 ***
Fatal error (delete a task with a semaphore in use) hit
*** END OF TEST SPFATAL 28 ***
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#define FATAL_ERROR_TEST_NAME "28"
#define FATAL_ERROR_DESCRIPTION "delete a task with a semaphore in use"
#define FATAL_ERROR_EXPECTED_SOURCE INTERNAL_ERROR_CORE
#define FATAL_ERROR_EXPECTED_IS_INTERNAL FALSE
#define FATAL_ERROR_EXPECTED_ERROR INTERNAL_ERROR_RESOURCE_IN_USE
#define CONFIGURE_MAXIMUM_SEMAPHORES 1
void force_error()
{
rtems_status_code sc;
rtems_id id;
sc = rtems_semaphore_create(
rtems_build_name('S', 'E', 'M', 'A'),
0,
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
0,
&id
);
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
sc = rtems_task_delete(RTEMS_SELF);
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
}
+1 -1
View File
@@ -35,7 +35,7 @@ static void test_internal_error_text(void)
puts( text );
} while ( text != text_last );
rtems_test_assert( error - 3 == INTERNAL_ERROR_CPU_ISR_INSTALL_VECTOR );
rtems_test_assert( error - 3 == INTERNAL_ERROR_RESOURCE_IN_USE );
}
static void test_fatal_source_text(void)
+3 -3
View File
@@ -150,8 +150,8 @@ rtems_task Task02(rtems_task_argument ignored)
directive_failed( status, " rtems_semaphore_obtain S1");
printf("TA02: priority %d, holding S1\n", getprio());
printf("TA02: exiting\n");
status = rtems_task_delete( RTEMS_SELF);
directive_failed( status, "rtems_task_delete TA02");
printf("TA02: suspending\n");
status = rtems_task_suspend( RTEMS_SELF);
directive_failed( status, "rtems_task_suspend TA02");
}
+4 -5
View File
@@ -1,4 +1,4 @@
*** TEST SEM01 ***
*** BEGIN OF TEST SPSEM 1 ***
init: S0 created
init: S1 created
init: TA01 created with priority 36
@@ -7,10 +7,9 @@ TA01: started with priority 36
TA01: priority 36, holding S0
TA01: priority 36, holding S0, S1
TA02: started with priority 34
TA01: priority 34, holding S0
TA02: priority 34, holding S1
TA02: exiting
TA01: priority 36, holding S0
TA02: suspending
TA01: priority 36
TA01: exiting
*** END OF SEM01 ***
*** END OF TEST SPSEM 1 ***
+3 -3
View File
@@ -168,9 +168,9 @@ rtems_task Task02(rtems_task_argument ignored)
directive_failed( status, " rtems_semaphore_obtain S1");
printf("TA02: priority %d, holding S1\n", getprio());
printf("TA02: exiting\n");
status = rtems_task_delete( RTEMS_SELF);
directive_failed( status, "rtems_task_delete TA02");
printf("TA02: suspending\n");
status = rtems_task_suspend( RTEMS_SELF);
directive_failed( status, "rtems_task_suspend TA02");
}
/* Task03 starts with priority 32 */
+3 -4
View File
@@ -1,4 +1,4 @@
*** TEST SEM02 ***
*** BEGIN OF TEST SPSEM 2 ***
init: S0 created
init: S1 created
init: TA01 created with priority 36
@@ -15,8 +15,7 @@ TA03: priority 32, holding S0
TA03: priority 32
TA03: exiting
TA02: priority 34, holding S1
TA02: exiting
TA02: suspending
TA01: priority 36
TA01: exiting
*** END OF SEM02 ***
*** END OF TEST SPSEM 2 ***