[rtems commit] Disable per task variables when SMP is enabled
Joel Sherrill
joel at rtems.org
Fri Apr 4 19:19:49 UTC 2014
Module: rtems
Branch: master
Commit: d507c0373168e6375b1e876d79730bff8020cb58
Changeset: http://git.rtems.org/rtems/commit/?id=d507c0373168e6375b1e876d79730bff8020cb58
Author: Joel Sherrill <joel.sherrill at oarcorp.com>
Date: Thu Apr 3 12:55:43 2014 -0500
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.
---
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 4bfe4e8..a3ec7fa 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -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
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
More information about the vc
mailing list