Disable per task variables when SMP is enabled

Per task variables are inherently unsafe in SMP systems. This
patch disables them from the build and adds warnings in the
appropriate documentation and configuration sections.
This commit is contained in:
Joel Sherrill
2014-04-04 14:27:27 -05:00
parent cae120e23c
commit d507c03731
16 changed files with 118 additions and 43 deletions
+3
View File
@@ -106,10 +106,13 @@ librtems_a_SOURCES += src/taskstart.c
librtems_a_SOURCES += src/tasksuspend.c
librtems_a_SOURCES += src/taskwakeafter.c
librtems_a_SOURCES += src/taskwakewhen.c
if HAS_SMP
else
librtems_a_SOURCES += src/taskvariableadd.c
librtems_a_SOURCES += src/taskvariabledelete.c
librtems_a_SOURCES += src/taskvariableget.c
librtems_a_SOURCES += src/taskvariable_invoke_dtor.c
endif
librtems_a_SOURCES += src/taskdata.c
## RATEMON_C_FILES
+9 -5
View File
@@ -28,7 +28,7 @@
*/
/*
* COPYRIGHT (c) 1989-2011.
* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -449,17 +449,18 @@ rtems_status_code rtems_task_wake_after(
*
* This directive returns a status indicating whether or not
* the specified task is suspended.
*
* RTEMS Task Manager
*/
rtems_status_code rtems_task_is_suspended(
rtems_id id
);
#if !defined(RTEMS_SMP)
/**
* @brief RTEMS Add Task Variable
*
* This directive adds a per task variable.
*
* @note This service is not available in SMP configurations.
*/
rtems_status_code rtems_task_variable_add(
rtems_id tid,
@@ -470,9 +471,9 @@ rtems_status_code rtems_task_variable_add(
/**
* @brief Get a per-task variable
*
* RTEMS Task Variable Get
*
* This directive gets the value of a task variable.
*
* @note This service is not available in SMP configurations.
*/
rtems_status_code rtems_task_variable_get(
rtems_id tid,
@@ -484,11 +485,14 @@ rtems_status_code rtems_task_variable_get(
* @brief RTEMS Delete Task Variable
*
* This directive removes a per task variable.
*
* @note This service is not available in SMP configurations.
*/
rtems_status_code rtems_task_variable_delete(
rtems_id tid,
void **ptr
);
#endif
#if defined(__RTEMS_HAVE_SYS_CPUSET_H__) && defined(RTEMS_SMP)
/**
+3 -1
View File
@@ -6,7 +6,7 @@
* @brief Classic Tasks Manager Implementation
*/
/* COPYRIGHT (c) 1989-2008.
/* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -66,6 +66,7 @@ void _RTEMS_tasks_Manager_initialization(void);
*/
void _RTEMS_tasks_Initialize_user_tasks( void );
#if !defined(RTEMS_SMP)
/**
* @brief RTEMS Tasks Invoke Task Variable Destructor
*
@@ -76,6 +77,7 @@ void _RTEMS_Tasks_Invoke_task_variable_dtor(
Thread_Control *the_thread,
rtems_task_variable_t *tvp
);
#endif
RTEMS_INLINE_ROUTINE Thread_Control *_RTEMS_tasks_Allocate(void)
{
+5 -1
View File
@@ -5,7 +5,7 @@
*/
/*
* COPYRIGHT (c) 1989-2011.
* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -887,6 +887,10 @@
* A critical point with per-task variables is that each task must separately
* request that the same global variable is per-task private.
*
* @b{WARNING}: Per-task variables are fundamentally incorrect in SMP
* systems and should not be used in SMP applications. They
* are disabled.
*
* @section ClassicTasksSecBuildingTaskAttributeSet Building a Task Attribute Set
*
* In general, an attribute set is built by a bitwise OR of the desired
+27 -12
View File
@@ -72,7 +72,9 @@ static bool _RTEMS_tasks_Create_extension(
_Event_Initialize( &api->System_event );
_ASR_Initialize( &api->Signal );
_Thread_Action_initialize( &api->Signal_action, _Signal_Action_handler );
#if !defined(RTEMS_SMP)
created->task_variables = NULL;
#endif
if ( rtems_configuration_get_notepads_enabled() ) {
for (i=0; i < RTEMS_NUMBER_NOTEPADS; i++)
@@ -124,19 +126,25 @@ static void _RTEMS_tasks_Terminate_extension(
Thread_Control *executing
)
{
rtems_task_variable_t *tvp, *next;
/*
* Free per task variable memory
*
* Per Task Variables are only enabled in uniprocessor configurations
*/
#if !defined(RTEMS_SMP)
do {
rtems_task_variable_t *tvp, *next;
tvp = executing->task_variables;
executing->task_variables = NULL;
while (tvp) {
next = (rtems_task_variable_t *)tvp->next;
_RTEMS_Tasks_Invoke_task_variable_dtor( executing, tvp );
tvp = next;
}
tvp = executing->task_variables;
executing->task_variables = NULL;
while (tvp) {
next = (rtems_task_variable_t *)tvp->next;
_RTEMS_Tasks_Invoke_task_variable_dtor( executing, tvp );
tvp = next;
}
} while (0);
#endif
/*
* Run all the key destructors
@@ -144,12 +152,15 @@ static void _RTEMS_tasks_Terminate_extension(
_POSIX_Keys_Run_destructors( executing );
}
#if !defined(RTEMS_SMP)
/*
* _RTEMS_tasks_Switch_extension
*
* This extension routine is invoked at each context switch.
*
* @note Since this only needs to address per-task variables, it is
* disabled entirely for SMP configurations.
*/
static void _RTEMS_tasks_Switch_extension(
Thread_Control *executing,
Thread_Control *heir
@@ -158,7 +169,7 @@ static void _RTEMS_tasks_Switch_extension(
rtems_task_variable_t *tvp;
/*
* Per Task Variables
* Per Task Variables are only enabled in uniprocessor configurations
*/
tvp = executing->task_variables;
@@ -175,6 +186,10 @@ static void _RTEMS_tasks_Switch_extension(
tvp = (rtems_task_variable_t *)tvp->next;
}
}
#define RTEMS_TASKS_SWITCH_EXTENSION _RTEMS_tasks_Switch_extension
#else
#define RTEMS_TASKS_SWITCH_EXTENSION NULL
#endif
API_extensions_Control _RTEMS_tasks_API_extensions = {
#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
@@ -185,12 +200,12 @@ API_extensions_Control _RTEMS_tasks_API_extensions = {
User_extensions_Control _RTEMS_tasks_User_extensions = {
{ NULL, NULL },
{ { NULL, NULL }, _RTEMS_tasks_Switch_extension },
{ { NULL, NULL }, RTEMS_TASKS_SWITCH_EXTENSION },
{ _RTEMS_tasks_Create_extension, /* create */
_RTEMS_tasks_Start_extension, /* start */
_RTEMS_tasks_Start_extension, /* restart */
_RTEMS_tasks_Delete_extension, /* delete */
_RTEMS_tasks_Switch_extension, /* switch */
RTEMS_TASKS_SWITCH_EXTENSION, /* switch */
NULL, /* begin */
NULL, /* exitted */
NULL, /* fatal */
+3 -1
View File
@@ -6,7 +6,7 @@
*/
/*
* COPYRIGHT (c) 1989-2007.
* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -18,6 +18,7 @@
#include "config.h"
#endif
#if !defined(RTEMS_SMP)
#include <rtems/rtems/tasksimpl.h>
#include <rtems/score/threadimpl.h>
#include <rtems/score/wkspace.h>
@@ -43,3 +44,4 @@ void _RTEMS_Tasks_Invoke_task_variable_dtor(
_Workspace_Free(tvp);
}
#endif
+3 -1
View File
@@ -6,7 +6,7 @@
*/
/*
* COPYRIGHT (c) 1989-2007.
* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -18,6 +18,7 @@
#include "config.h"
#endif
#if !defined(RTEMS_SMP)
#include <rtems/rtems/tasks.h>
#include <rtems/score/threadimpl.h>
#include <rtems/score/wkspace.h>
@@ -88,3 +89,4 @@ rtems_status_code rtems_task_variable_add(
}
return RTEMS_INVALID_ID;
}
#endif
+3 -1
View File
@@ -6,7 +6,7 @@
*/
/*
* COPYRIGHT (c) 1989-2007.
* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -18,6 +18,7 @@
#include "config.h"
#endif
#if !defined(RTEMS_SMP)
#include <rtems/rtems/tasksimpl.h>
#include <rtems/score/threadimpl.h>
#include <rtems/score/wkspace.h>
@@ -77,3 +78,4 @@ rtems_status_code rtems_task_variable_delete(
return RTEMS_INVALID_ID;
}
#endif
+3 -1
View File
@@ -6,7 +6,7 @@
*/
/*
* COPYRIGHT (c) 1989-2007.
* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -18,6 +18,7 @@
#include "config.h"
#endif
#if !defined(RTEMS_SMP)
#include <rtems/rtems/tasksimpl.h>
#include <rtems/score/threadimpl.h>
#include <rtems/score/wkspace.h>
@@ -85,3 +86,4 @@ rtems_status_code rtems_task_variable_get(
}
return RTEMS_INVALID_ID;
}
#endif
+16 -6
View File
@@ -1591,12 +1591,21 @@ const rtems_libio_helper rtems_fs_init_helper =
(RTEMS_NUMBER_NOTEPADS * sizeof(uint32_t)))
#endif
/**
* This macro calculates the memory required for task variables.
*
* NOTE: Each task variable is individually allocated from the Workspace.
* Hence, we do the multiplication on the configured size.
*/
/**
* This macro calculates the memory required for task variables.
*
* Each task variable is individually allocated from the Workspace.
* Hence, we do the multiplication on the configured size.
*
* @note Per-task variables are disabled for SMP configurations.
*/
#if defined(RTEMS_SMP)
#ifdef CONFIGURE_MAXIMUM_TASK_VARIABLES
#error "Per-Task Variables are not safe for SMP systems and disabled"
#endif
#define CONFIGURE_MAXIMUM_TASK_VARIABLES 0
#define CONFIGURE_MEMORY_FOR_TASK_VARIABLES(_task_variables) 0
#else
#ifndef CONFIGURE_MAXIMUM_TASK_VARIABLES
#define CONFIGURE_MAXIMUM_TASK_VARIABLES 0
#define CONFIGURE_MEMORY_FOR_TASK_VARIABLES(_task_variables) 0
@@ -1605,6 +1614,7 @@ const rtems_libio_helper rtems_fs_init_helper =
(_task_variables) * \
_Configure_From_workspace(sizeof(rtems_task_variable_t))
#endif
#endif
#ifndef CONFIGURE_MAXIMUM_TIMERS
#define CONFIGURE_MAXIMUM_TIMERS 0
@@ -171,6 +171,7 @@ typedef enum {
*/
typedef void (*Thread_CPU_budget_algorithm_callout )( Thread_Control * );
#if !defined(RTEMS_SMP)
/**
* @brief Forward reference to the per task variable structure..
*
@@ -197,6 +198,7 @@ typedef struct {
/** This field points to the destructor for this per task variable. */
void (*dtor)(void *);
} rtems_task_variable_t;
#endif
/**
* The following structure contains the information which defines
@@ -567,8 +569,10 @@ struct Thread_Control_struct {
/** This field points to the user extension pointers. */
void **extensions;
#if !defined(RTEMS_SMP)
/** This field points to the set of per task variables. */
rtems_task_variable_t *task_variables;
#endif
/**
* This is the thread key value chain's control, which is used
+17 -2
View File
@@ -1,5 +1,5 @@
@c
@c COPYRIGHT (c) 1988-2008.
@c COPYRIGHT (c) 1988-2014.
@c On-Line Applications Research Corporation (OAR).
@c All rights reserved.
@@ -340,6 +340,13 @@ containing the task's private "global" data.
A critical point with per-task variables is that each task must separately
request that the same global variable is per-task private.
@b{WARNING}: Per-Task variables are inherently broken on SMP systems. They
only work correctly when there is one task executing in the system and
that task is the logical owner of the value in the per-task variable's
location. There is no way for a single memory image to contain the
correct value for each task executing on each core. Consequently,
per-task variables are disabled in SMP configurations of RTEMS.
@subsection Building a Task Attribute Set
@cindex task attributes, building
@@ -1779,6 +1786,9 @@ is to have a single task variable that is a pointer to a dynamically
allocated structure containing the task's private `global' data.
In this case the destructor function could be `free'.
Per-task variables are disabled in SMP configurations and this service
is not available.
@page
@subsection TASK_VARIABLE_GET - Obtain value of a per task variable
@@ -1832,6 +1842,9 @@ will optimize it correctly. In this case both the pointer
@code{task_variable_value} and data referenced by @code{task_variable_value}
should be considered volatile.
Per-task variables are disabled in SMP configurations and this service
is not available.
@page
@subsection TASK_VARIABLE_DELETE - Remove per task variable
@@ -1874,4 +1887,6 @@ This directive removes the given location from a task's context.
@subheading NOTES:
NONE
Per-task variables are disabled in SMP configurations and this service
is not available.
+11 -2
View File
@@ -7,6 +7,7 @@
*/
/*
* Copyright (c) 2014. On-Line Applications Research Corporation (OAR).
* Copyright (c) 2011-2012 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
@@ -51,7 +52,9 @@ const char rtems_test_name[] = "PSXCONFIG 1";
#define CONFIGURE_MAXIMUM_REGIONS 43
#define CONFIGURE_MAXIMUM_SEMAPHORES 47
#define CONFIGURE_MAXIMUM_TASKS 11
#define CONFIGURE_MAXIMUM_TASK_VARIABLES 13
#if !defined(RTEMS_SMP)
#define CONFIGURE_MAXIMUM_TASK_VARIABLES 13
#endif
#define CONFIGURE_MAXIMUM_TIMERS 59
#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 17
@@ -196,7 +199,9 @@ typedef struct {
static char posix_name [NAME_MAX];
static void *task_var;
#if !defined(RTEMS_SMP)
static void *task_var;
#endif
static char *get_posix_name(char a, char b, char c, int i)
{
@@ -208,10 +213,12 @@ static char *get_posix_name(char a, char b, char c, int i)
return posix_name;
}
#if !defined(RTEMS_SMP)
static void task_var_dtor(void *var __attribute__((unused)))
{
/* Do nothing */
}
#endif
static void *posix_thread(void *arg __attribute__((unused)))
{
@@ -403,12 +410,14 @@ static rtems_task Init(rtems_task_argument argument)
);
#endif
#if !defined(RTEMS_SMP)
#ifdef CONFIGURE_MAXIMUM_TASK_VARIABLES
for (i = 0; i < CONFIGURE_MAXIMUM_TASK_VARIABLES; ++i) {
sc = rtems_task_variable_add(RTEMS_SELF, &task_var, task_var_dtor);
directive_failed(sc, "rtems_task_variable_add");
}
#endif
#endif
#ifdef CONFIGURE_MAXIMUM_TIMERS
for (i = 0; i < CONFIGURE_MAXIMUM_TIMERS; ++i) {
+1 -9
View File
@@ -1,4 +1,5 @@
/*
* Copyright (c) 2014 On-Line Applications Research Corporation (OAR).
* Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
@@ -28,15 +29,6 @@ static void test(void)
rtems_test_assert(rtems_configuration_is_smp_enabled());
sc = rtems_task_variable_add(RTEMS_SELF, NULL, NULL);
rtems_test_assert(sc == RTEMS_NOT_IMPLEMENTED);
sc = rtems_task_variable_delete(RTEMS_SELF, NULL);
rtems_test_assert(sc == RTEMS_NOT_IMPLEMENTED);
sc = rtems_task_variable_get(RTEMS_SELF, NULL, NULL);
rtems_test_assert(sc == RTEMS_NOT_IMPLEMENTED);
sc = rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &mode);
rtems_test_assert(sc == RTEMS_NOT_IMPLEMENTED);
+6 -1
View File
@@ -5,7 +5,7 @@ ACLOCAL_AMFLAGS = -I ../aclocal
SUBDIRS = \
sp01 sp02 sp03 sp04 sp05 sp06 sp07 sp08 \
sp10 sp11 sp12 sp13 sp14 sp15 sp16 sp17 sp18 sp19 \
sp20 sp21 sp22 sp23 sp24 sp25 sp26 sp27 sp27a sp28 sp29 \
sp20 sp21 sp22 sp23 sp24 sp25 sp26 sp27 sp27a \
sp30 sp31 sp32 sp33 sp34 sp35 sp37 sp38 sp39 \
sp40 sp41 sp42 sp43 sp44 sp45 sp46 sp47 sp48 sp49 \
sp50 sp51 sp52 sp53 sp54 sp55 sp56 sp57 sp58 sp59 \
@@ -33,6 +33,11 @@ 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
if HAS_SMP
else
SUBDIRS += sp29
endif
SUBDIRS += spprofiling01
SUBDIRS += spfatal28
SUBDIRS += spthreadlife01
SUBDIRS += spprofiling01
+4
View File
@@ -34,6 +34,10 @@ AC_CHECK_SIZEOF([time_t])
AC_CHECK_HEADERS([sys/cpuset.h])
AM_CONDITIONAL(HAS_CPUSET,test x"${ac_cv_header_sys_cpuset_h}" = x"yes")
# Some tests should not be built/run in SMP configurations
RTEMS_CHECK_CPUOPTS([RTEMS_SMP])
AM_CONDITIONAL(HAS_SMP,test "$rtems_cv_RTEMS_SMP" = "yes")
# Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile
spfatal28/Makefile