[PATCH] Disable per task variables when SMP is enabled
Joel Sherrill
joel.sherrill at oarcorp.com
Thu Apr 3 18:53:12 UTC 2014
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.
---
cpukit/rtems/Makefile.am | 3 ++
cpukit/rtems/include/rtems/rtems/tasks.h | 14 ++++++---
cpukit/rtems/include/rtems/rtems/tasksimpl.h | 4 ++-
cpukit/rtems/mainpage.h | 6 +++-
cpukit/rtems/src/tasks.c | 41 +++++++++++++++++--------
cpukit/rtems/src/taskvariable_invoke_dtor.c | 4 ++-
cpukit/rtems/src/taskvariableadd.c | 4 ++-
cpukit/rtems/src/taskvariabledelete.c | 4 ++-
cpukit/rtems/src/taskvariableget.c | 4 ++-
cpukit/sapi/include/confdefs.h | 22 ++++++++++----
cpukit/score/include/rtems/score/thread.h | 4 ++
doc/user/task.t | 19 +++++++++++-
testsuites/psxtests/psxconfig01/init.c | 13 +++++++-
testsuites/smptests/smpunsupported01/init.c | 10 +------
testsuites/sptests/Makefile.am | 7 ++++-
testsuites/sptests/configure.ac | 4 ++
16 files changed, 119 insertions(+), 44 deletions(-)
diff --git a/cpukit/rtems/Makefile.am b/cpukit/rtems/Makefile.am
index cf8ca3b..6cb5181 100644
--- a/cpukit/rtems/Makefile.am
+++ b/cpukit/rtems/Makefile.am
@@ -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
diff --git a/cpukit/rtems/include/rtems/rtems/tasks.h b/cpukit/rtems/include/rtems/rtems/tasks.h
index 325723f..263cc53 100644
--- a/cpukit/rtems/include/rtems/rtems/tasks.h
+++ b/cpukit/rtems/include/rtems/rtems/tasks.h
@@ -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)
/**
diff --git a/cpukit/rtems/include/rtems/rtems/tasksimpl.h b/cpukit/rtems/include/rtems/rtems/tasksimpl.h
index c86d591..280be2f 100644
--- a/cpukit/rtems/include/rtems/rtems/tasksimpl.h
+++ b/cpukit/rtems/include/rtems/rtems/tasksimpl.h
@@ -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)
{
diff --git a/cpukit/rtems/mainpage.h b/cpukit/rtems/mainpage.h
index c3fc44d..7206981 100644
--- a/cpukit/rtems/mainpage.h
+++ b/cpukit/rtems/mainpage.h
@@ -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
diff --git a/cpukit/rtems/src/tasks.c b/cpukit/rtems/src/tasks.c
index 5946950..209a43c 100644
--- a/cpukit/rtems/src/tasks.c
+++ b/cpukit/rtems/src/tasks.c
@@ -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
*/
-
- 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;
- }
+ #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;
+ }
+ } 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 */
diff --git a/cpukit/rtems/src/taskvariable_invoke_dtor.c b/cpukit/rtems/src/taskvariable_invoke_dtor.c
index 51b9453..0627723 100644
--- a/cpukit/rtems/src/taskvariable_invoke_dtor.c
+++ b/cpukit/rtems/src/taskvariable_invoke_dtor.c
@@ -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
diff --git a/cpukit/rtems/src/taskvariableadd.c b/cpukit/rtems/src/taskvariableadd.c
index bd45018..c79195e 100644
--- a/cpukit/rtems/src/taskvariableadd.c
+++ b/cpukit/rtems/src/taskvariableadd.c
@@ -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
diff --git a/cpukit/rtems/src/taskvariabledelete.c b/cpukit/rtems/src/taskvariabledelete.c
index 49e2746..f5362f9 100644
--- a/cpukit/rtems/src/taskvariabledelete.c
+++ b/cpukit/rtems/src/taskvariabledelete.c
@@ -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
diff --git a/cpukit/rtems/src/taskvariableget.c b/cpukit/rtems/src/taskvariableget.c
index 627d40a..ba49b4d 100644
--- a/cpukit/rtems/src/taskvariableget.c
+++ b/cpukit/rtems/src/taskvariableget.c
@@ -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
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index ef8f09a..4a3181f 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -1588,12 +1588,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
@@ -1602,6 +1611,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
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 1fc5076..2765f56 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -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
diff --git a/doc/user/task.t b/doc/user/task.t
index 40759fc..a172a0c 100644
--- a/doc/user/task.t
+++ b/doc/user/task.t
@@ -1,5 +1,5 @@
@c
- at c COPYRIGHT (c) 1988-2008.
+ at 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.
+ at 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.
+
diff --git a/testsuites/psxtests/psxconfig01/init.c b/testsuites/psxtests/psxconfig01/init.c
index b090fe7..afce9f6 100644
--- a/testsuites/psxtests/psxconfig01/init.c
+++ b/testsuites/psxtests/psxconfig01/init.c
@@ -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) {
diff --git a/testsuites/smptests/smpunsupported01/init.c b/testsuites/smptests/smpunsupported01/init.c
index 3a819b8..9d69b6b 100644
--- a/testsuites/smptests/smpunsupported01/init.c
+++ b/testsuites/smptests/smpunsupported01/init.c
@@ -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);
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index c344ce0..1d530e2 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -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
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index 3f2f952..30d2787 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -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
--
1.7.1
More information about the devel
mailing list