[PATCH] cpukit: Disable per-task variables in SMP configurations
Joel Sherrill
joel.sherrill at oarcorp.com
Fri Mar 21 17:47:18 UTC 2014
This is my first shot at disabling per-task variables when SMP
is enabled. Since there are still uses of per-task variables, this
breaks the SMP build. It cannot be applied until those are addressed.
Hoping that those uses disappear while I am in Munich next week,
I am posting this for review. :)
Hopefully the uses will be gone soon and we can verify this patch
is OK.
---
cpukit/rtems/Makefile.am | 2 +
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 | 51 ++++++++++++++++----------
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 | 11 +++++-
testsuites/smptests/smpunsupported01/init.c | 10 +-----
testsuites/sptests/Makefile.am | 6 +++-
testsuites/sptests/configure.ac | 4 ++
16 files changed, 120 insertions(+), 49 deletions(-)
diff --git a/cpukit/rtems/Makefile.am b/cpukit/rtems/Makefile.am
index f89a896..e3084ae 100644
--- a/cpukit/rtems/Makefile.am
+++ b/cpukit/rtems/Makefile.am
@@ -106,10 +106,12 @@ 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
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 ead71b9..9b0a448 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 fbee00e..7908f25 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
@@ -65,6 +65,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
*
@@ -75,6 +76,7 @@ void _RTEMS_Tasks_Invoke_task_variable_dtor(
Thread_Control *the_thread,
rtems_task_variable_t *tvp
);
+#endif
/**
* @brief Allocates a task control block.
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 7e61068..240f144 100644
--- a/cpukit/rtems/src/tasks.c
+++ b/cpukit/rtems/src/tasks.c
@@ -6,7 +6,7 @@
*/
/*
- * COPYRIGHT (c) 1989-2014.
+ HAS_* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -70,7 +70,9 @@ static bool _RTEMS_tasks_Create_extension(
_Event_Initialize( &api->Event );
_Event_Initialize( &api->System_event );
_ASR_Initialize( &api->Signal );
- created->task_variables = NULL;
+ #if !defined(RTEMS_SMP)
+ created->task_variables = NULL;
+ #endif
if ( rtems_configuration_get_notepads_enabled() ) {
for (i=0; i < RTEMS_NUMBER_NOTEPADS; i++)
@@ -105,25 +107,30 @@ static void _RTEMS_tasks_Start_extension(
*
* This extension routine is invoked when a task is deleted.
*/
-
static void _RTEMS_tasks_Delete_extension(
Thread_Control *executing,
Thread_Control *deleted
)
{
- rtems_task_variable_t *tvp, *next;
-
/*
- * Free per task variable memory
+ * Per Task Variables are only enabled in uniprocessor configurations
*/
-
- tvp = deleted->task_variables;
- deleted->task_variables = NULL;
- while (tvp) {
- next = (rtems_task_variable_t *)tvp->next;
- _RTEMS_Tasks_Invoke_task_variable_dtor( deleted, tvp );
- tvp = next;
- }
+ #if !defined(RTEMS_SMP)
+ do {
+ rtems_task_variable_t *tvp, *next;
+
+ /*
+ * Free per task variable memory
+ */
+ tvp = deleted->task_variables;
+ deleted->task_variables = NULL;
+ while (tvp) {
+ next = (rtems_task_variable_t *)tvp->next;
+ _RTEMS_Tasks_Invoke_task_variable_dtor( deleted, tvp );
+ tvp = next;
+ }
+ } while (0);
+ #endif
/*
* Run all the key destructors
@@ -133,17 +140,19 @@ static void _RTEMS_tasks_Delete_extension(
/*
* Free API specific memory
*/
-
(void) _Workspace_Free( deleted->API_Extensions[ THREAD_API_RTEMS ] );
deleted->API_Extensions[ THREAD_API_RTEMS ] = NULL;
}
+#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
@@ -152,7 +161,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;
@@ -169,6 +178,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)
@@ -179,12 +192,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 a23e5e5..666af0c 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 aca99f0..6cefb93 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -1554,12 +1554,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
@@ -1568,6 +1577,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 3dc423f..e9f6cfc 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -169,6 +169,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..
*
@@ -195,6 +196,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
@@ -472,8 +474,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 4f3981d..b656252 100644
--- a/testsuites/psxtests/psxconfig01/init.c
+++ b/testsuites/psxtests/psxconfig01/init.c
@@ -7,6 +7,9 @@
*/
/*
+ * Copyright (c) 2014. On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2011-2012 embedded brains GmbH. All rights reserved.
* Copyright (c) 2011-2012 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
@@ -189,7 +192,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)
{
@@ -201,10 +206,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)))
{
@@ -396,12 +403,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 a2ffbed..f0c12d9 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 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
@@ -38,15 +39,6 @@ static void test(void)
sc = rtems_task_delete(RTEMS_SELF);
rtems_test_assert(sc == RTEMS_NOT_IMPLEMENTED);
- 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 d57ae69..a05743c 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 sp09 \
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 sp29 \
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 \
@@ -30,6 +30,10 @@ SUBDIRS = \
spsimplesched03 spnsext01 spedfsched01 spedfsched02 spedfsched03 \
spcbssched01 spcbssched02 spcbssched03 spqreslib sptimespec01 \
spregion_err01 sppartition_err01
+if HAS_SMP
+else
+SUBDIRS += sp29
+endif
SUBDIRS += spprofiling01
SUBDIRS += spcache01
SUBDIRS += sptls03
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index 5f98ba7..dfc4eff 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
spprofiling01/Makefile
--
1.7.1
More information about the devel
mailing list