[PATCH 5/5] score: Simplify thread control initialization

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Apr 4 15:07:41 UTC 2014


The thread control structure contains fields that point to application
configuration dependent objects, like the scheduler information, the API
control blocks, the user extensions, the RTEMS notepads and the Newlib
re-entrancy support.  Account for these objects in the configuration and
avoid extra workspace allocations for these objects.

This helps also to avoid heap fragementation and reduces the per thread
memory due to a reduced heap allocation overhead.
---
 cpukit/libcsupport/include/rtems/libcsupport.h     |    7 +-
 cpukit/libcsupport/src/newlibc_reent.c             |   26 +---
 cpukit/posix/src/pthread.c                         |   25 +---
 cpukit/rtems/include/rtems/rtems/tasks.h           |    2 +-
 cpukit/rtems/src/tasks.c                           |   40 +-----
 cpukit/sapi/include/confdefs.h                     |  158 +++++++++-----------
 cpukit/score/Makefile.am                           |    3 -
 .../score/include/rtems/score/schedulercbsimpl.h   |    2 +-
 .../score/include/rtems/score/scheduleredfimpl.h   |   15 +--
 cpukit/score/include/rtems/score/schedulerimpl.h   |    6 +-
 .../include/rtems/score/schedulerpriorityimpl.h    |   26 ----
 cpukit/score/include/rtems/score/thread.h          |   20 +++-
 cpukit/score/src/schedulercbsallocate.c            |   18 +--
 cpukit/score/src/schedulercbsops.c                 |    2 +-
 cpukit/score/src/schedulerdefaultallocatefree.c    |    4 +-
 cpukit/score/src/scheduleredfallocate.c            |   18 +--
 cpukit/score/src/scheduleredffree.c                |   33 ----
 cpukit/score/src/scheduleredfops.c                 |    2 +-
 cpukit/score/src/schedulerpriorityaffinitysmp.c    |    6 +-
 cpukit/score/src/schedulerpriorityallocate.c       |   37 -----
 cpukit/score/src/schedulerpriorityfree.c           |   35 -----
 cpukit/score/src/schedulerpriorityops.c            |    4 +-
 cpukit/score/src/schedulerprioritysmp.c            |    4 +-
 cpukit/score/src/thread.c                          |    3 +-
 cpukit/score/src/threadinitialize.c                |   59 +++-----
 cpukit/score/src/threadrestart.c                   |    2 -
 26 files changed, 150 insertions(+), 407 deletions(-)
 delete mode 100644 cpukit/score/src/scheduleredffree.c
 delete mode 100644 cpukit/score/src/schedulerpriorityallocate.c
 delete mode 100644 cpukit/score/src/schedulerpriorityfree.c

diff --git a/cpukit/libcsupport/include/rtems/libcsupport.h b/cpukit/libcsupport/include/rtems/libcsupport.h
index 7d40084..c1bb9a1 100644
--- a/cpukit/libcsupport/include/rtems/libcsupport.h
+++ b/cpukit/libcsupport/include/rtems/libcsupport.h
@@ -85,11 +85,6 @@ bool newlib_create_hook(
 
 #define __RTEMS_NEWLIB_BEGIN 0
 
-void newlib_delete_hook(
-  rtems_tcb *current_task,
-  rtems_tcb *deleted_task
-);
-
 void newlib_terminate_hook(
   rtems_tcb *current_task
 );
@@ -99,7 +94,7 @@ void newlib_terminate_hook(
   newlib_create_hook,     /* rtems_task_create  */ \
   0,                      /* rtems_task_start   */ \
   0,                      /* rtems_task_restart */ \
-  newlib_delete_hook,     /* rtems_task_delete  */ \
+  0,                      /* rtems_task_delete  */ \
   0,                      /* task_switch  */ \
   __RTEMS_NEWLIB_BEGIN,   /* task_begin   */ \
   0,                      /* task_exitted */ \
diff --git a/cpukit/libcsupport/src/newlibc_reent.c b/cpukit/libcsupport/src/newlibc_reent.c
index cd3ac2a..430157c 100644
--- a/cpukit/libcsupport/src/newlibc_reent.c
+++ b/cpukit/libcsupport/src/newlibc_reent.c
@@ -35,9 +35,6 @@ bool newlib_create_hook(
   rtems_tcb *creating_task
 )
 {
-  struct _reent *ptr;
-  bool ok;
-
 #if !defined(__DYNAMIC_REENT__)
   if (_Thread_libc_reent == 0)
   {
@@ -47,28 +44,9 @@ bool newlib_create_hook(
   }
 #endif
 
-  /* It is OK to allocate from the workspace because these
-   * hooks run with thread dispatching disabled.
-   */
-  ptr = (struct _reent *) _Workspace_Allocate(sizeof(*ptr));
-  creating_task->libc_reent = ptr;
-  ok = ptr != NULL;
-
-  if (ok) {
-    _REENT_INIT_PTR((ptr)); /* GCC extension: structure constants */
-  }
-
-  return ok;
-}
-
-void newlib_delete_hook(
-  rtems_tcb *current_task,
-  rtems_tcb *deleted_task
-)
-{
-  (void) current_task;
+  _REENT_INIT_PTR((creating_task->libc_reent)); /* GCC extension: structure constants */
 
-  _Workspace_Free(deleted_task->libc_reent);
+  return true;
 }
 
 void newlib_terminate_hook(
diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c
index 6f79658..ab197f3 100644
--- a/cpukit/posix/src/pthread.c
+++ b/cpukit/posix/src/pthread.c
@@ -190,12 +190,7 @@ static bool _POSIX_Threads_Create_extension(
   POSIX_API_Control *api;
   POSIX_API_Control *executing_api;
 
-  api = _Workspace_Allocate( sizeof( POSIX_API_Control ) );
-
-  if ( !api )
-    return false;
-
-  created->API_Extensions[ THREAD_API_POSIX ] = api;
+  api = created->API_Extensions[ THREAD_API_POSIX ];
 
   /* XXX check all fields are touched */
   _POSIX_Threads_Initialize_attributes( &api->Attributes );
@@ -266,19 +261,6 @@ static void _POSIX_Threads_Restart_extension(
   _POSIX_Threads_cancel_run( restarted );
 }
 
-/*
- *  _POSIX_Threads_Delete_extension
- *
- *  This method is invoked for each thread deleted.
- */
-static void _POSIX_Threads_Delete_extension(
-  Thread_Control *executing __attribute__((unused)),
-  Thread_Control *deleted
-)
-{
-  _Workspace_Free( deleted->API_Extensions[ THREAD_API_POSIX ] );
-}
-
 static void _POSIX_Threads_Terminate_extension(
   Thread_Control *executing
 )
@@ -355,7 +337,7 @@ User_extensions_Control _POSIX_Threads_User_extensions = {
   { _POSIX_Threads_Create_extension,          /* create */
     NULL,                                     /* start */
     _POSIX_Threads_Restart_extension,         /* restart */
-    _POSIX_Threads_Delete_extension,          /* delete */
+    NULL,                                     /* delete */
     NULL,                                     /* switch */
     NULL,                                     /* begin */
     _POSIX_Threads_Exitted_extension,         /* exitted */
@@ -392,8 +374,7 @@ void _POSIX_Threads_Manager_initialization(void)
     OBJECTS_POSIX_THREADS,       /* object class */
     Configuration_POSIX_API.maximum_threads,
                                  /* maximum objects of this class */
-    sizeof( Thread_Control ),
-                                 /* size of this object's control block */
+    _Thread_Control_size,        /* size of this object's control block */
     true,                        /* true if names for this object are strings */
     _POSIX_PATH_MAX              /* maximum length of each object's name */
 #if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/rtems/include/rtems/rtems/tasks.h b/cpukit/rtems/include/rtems/rtems/tasks.h
index 325723f..2d3588c 100644
--- a/cpukit/rtems/include/rtems/rtems/tasks.h
+++ b/cpukit/rtems/include/rtems/rtems/tasks.h
@@ -570,7 +570,7 @@ typedef struct {
    *
    *  @note MUST BE LAST ENTRY.
    */
-  uint32_t                 Notepads[ RTEMS_NUMBER_NOTEPADS ];
+  uint32_t                 Notepads[ 0 ];
 }  RTEMS_API_Control;
 
 /**
diff --git a/cpukit/rtems/src/tasks.c b/cpukit/rtems/src/tasks.c
index 5946950..45c50b9 100644
--- a/cpukit/rtems/src/tasks.c
+++ b/cpukit/rtems/src/tasks.c
@@ -50,23 +50,9 @@ static bool _RTEMS_tasks_Create_extension(
 )
 {
   RTEMS_API_Control *api;
-  int                i;
-  size_t             to_allocate;
+  size_t             i;
 
-  /*
-   *  Notepads must be the last entry in the structure and they
-   *  can be left off if disabled in the configuration.
-   */
-  to_allocate = sizeof( RTEMS_API_Control );
-  if ( !rtems_configuration_get_notepads_enabled() )
-    to_allocate -= (RTEMS_NUMBER_NOTEPADS * sizeof(uint32_t));
-
-  api = _Workspace_Allocate( to_allocate );
-
-  if ( !api )
-    return false;
-
-  created->API_Extensions[ THREAD_API_RTEMS ] = api;
+  api = created->API_Extensions[ THREAD_API_RTEMS ];
 
   _Event_Initialize( &api->Event );
   _Event_Initialize( &api->System_event );
@@ -102,24 +88,6 @@ static void _RTEMS_tasks_Start_extension(
   _Event_Initialize( &api->System_event );
 }
 
-/*
- *  _RTEMS_tasks_Delete_extension
- *
- *  This extension routine is invoked when a task is deleted.
- */
-
-static void _RTEMS_tasks_Delete_extension(
-  Thread_Control *executing,
-  Thread_Control *deleted
-)
-{
-  /*
-   *  Free API specific memory
-   */
-
-  (void) _Workspace_Free( deleted->API_Extensions[ THREAD_API_RTEMS ] );
-}
-
 static void _RTEMS_tasks_Terminate_extension(
   Thread_Control *executing
 )
@@ -189,7 +157,7 @@ User_extensions_Control _RTEMS_tasks_User_extensions = {
   { _RTEMS_tasks_Create_extension,            /* create */
     _RTEMS_tasks_Start_extension,             /* start */
     _RTEMS_tasks_Start_extension,             /* restart */
-    _RTEMS_tasks_Delete_extension,            /* delete */
+    NULL,                                     /* delete */
     _RTEMS_tasks_Switch_extension,            /* switch */
     NULL,                                     /* begin */
     NULL,                                     /* exitted */
@@ -206,7 +174,7 @@ void _RTEMS_tasks_Manager_initialization(void)
     OBJECTS_RTEMS_TASKS,       /* object class */
     Configuration_RTEMS_API.maximum_tasks,
                                /* maximum objects of this class */
-    sizeof( Thread_Control ),  /* size of this object's control block */
+    _Thread_Control_size,      /* size of this object's control block */
     false,                     /* true if the name is a string */
     RTEMS_MAXIMUM_NAME_LENGTH  /* maximum length of an object name */
 #if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index dccf7ce..5d917df 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -642,7 +642,7 @@ const rtems_libio_helper rtems_fs_init_helper =
  * CONFIGURE_SCHEDULER_USER and the following:
  *    - CONFIGURE_SCHEDULER_INSTANCE
  *    - CONFIGURE_SCHEDULER_REGISTER
- *    - CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER - per task memory
+ *    - CONFIGURE_SCHEDULER_USER_PER_THREAD
  */
 
 /* If no scheduler is specified, the priority scheduler is default. */
@@ -675,12 +675,6 @@ const rtems_libio_helper rtems_fs_init_helper =
 
   #define CONFIGURE_SCHEDULER_REGISTER \
     RTEMS_SCHEDULER_REGISTER_PRIORITY(priority)
-
-  /**
-   * This defines the memory used by the priority scheduler.
-   */
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER ( \
-    _Configure_From_workspace(sizeof(Scheduler_priority_Per_thread)) )
 #endif
 
 /*
@@ -696,12 +690,6 @@ const rtems_libio_helper rtems_fs_init_helper =
 
   #define CONFIGURE_SCHEDULER_REGISTER \
     RTEMS_SCHEDULER_REGISTER_PRIORITY_SMP(priority_SMP)
-
-  /**
-   * This defines the memory used by the priority scheduler.
-   */
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER ( \
-    _Configure_From_workspace(sizeof(Scheduler_priority_Per_thread)) )
 #endif
 
 /*
@@ -717,12 +705,6 @@ const rtems_libio_helper rtems_fs_init_helper =
 
   #define CONFIGURE_SCHEDULER_REGISTER \
     RTEMS_SCHEDULER_REGISTER_PRIORITY_AFFINITY_SMP(priority_affinity_SMP)
-
-  /**
-   * This defines the memory used by the priority scheduler.
-   */
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER ( \
-    _Configure_From_workspace(sizeof(Scheduler_priority_Per_thread)) )
 #endif
 
 /*
@@ -732,11 +714,6 @@ const rtems_libio_helper rtems_fs_init_helper =
   #define CONFIGURE_SCHEDULER_INSTANCE RTEMS_SCHEDULER_INSTANCE_SIMPLE(simple)
 
   #define CONFIGURE_SCHEDULER_REGISTER RTEMS_SCHEDULER_REGISTER_SIMPLE(simple)
-
-  /**
-   * define the memory used by the simple scheduler
-   */
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER (0)
 #endif
 
 /*
@@ -748,13 +725,6 @@ const rtems_libio_helper rtems_fs_init_helper =
 
   #define CONFIGURE_SCHEDULER_REGISTER \
     RTEMS_SCHEDULER_REGISTER_SIMPLE_SMP(simple_SMP)
-
-  /**
-   * Define the memory used by the Simple SMP Scheduler
-   *
-   * NOTE: This is the same as the Simple Scheduler
-   */
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER (0)
 #endif
 
 /*
@@ -764,12 +734,6 @@ const rtems_libio_helper rtems_fs_init_helper =
   #define CONFIGURE_SCHEDULER_INSTANCE RTEMS_SCHEDULER_INSTANCE_EDF(EDF)
 
   #define CONFIGURE_SCHEDULER_REGISTER RTEMS_SCHEDULER_REGISTER_EDF(EDF)
-
-  /**
-   * define the memory used by the EDF scheduler
-   */
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER ( \
-    _Configure_From_workspace(sizeof(Scheduler_EDF_Per_thread)))
 #endif
 
 /*
@@ -792,12 +756,6 @@ const rtems_libio_helper rtems_fs_init_helper =
     Scheduler_CBS_Server
       _Scheduler_CBS_Server_list[ CONFIGURE_CBS_MAXIMUM_SERVERS ];
   #endif
-
-  /**
-   * define the memory used by the CBS scheduler
-   */
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER ( \
-    _Configure_From_workspace(sizeof(Scheduler_CBS_Per_thread)))
 #endif
 
 /*
@@ -1585,15 +1543,6 @@ const rtems_libio_helper rtems_fs_init_helper =
     #define CONFIGURE_NOTEPADS_ENABLED           FALSE
   #endif
 
-  #ifndef CONFIGURE_DISABLE_CLASSIC_API_NOTEPADS
-    #define CONFIGURE_MEMORY_PER_TASK_FOR_CLASSIC_API \
-      _Configure_From_workspace( sizeof(RTEMS_API_Control) )
-  #else
-    #define CONFIGURE_MEMORY_PER_TASK_FOR_CLASSIC_API \
-      _Configure_From_workspace( sizeof(RTEMS_API_Control) - \
-        (RTEMS_NUMBER_NOTEPADS * sizeof(uint32_t)))
-  #endif
-
   /**
    * This macro calculates the memory required for task variables.
    *
@@ -1819,9 +1768,6 @@ const rtems_libio_helper rtems_fs_init_helper =
     #define CONFIGURE_MAXIMUM_POSIX_THREADS 0
   #endif
 
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_POSIX_API \
-    _Configure_From_workspace(sizeof(POSIX_API_Control))
-
   #ifndef CONFIGURE_MAXIMUM_POSIX_MUTEXES
     #define CONFIGURE_MAXIMUM_POSIX_MUTEXES 0
   #endif
@@ -1958,7 +1904,6 @@ const rtems_libio_helper rtems_fs_init_helper =
 #else
 
   #define CONFIGURE_MAXIMUM_POSIX_THREADS         0
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_POSIX_API 0
   #define CONFIGURE_MEMORY_FOR_POSIX              0
 
 #endif    /* RTEMS_POSIX_API */
@@ -2035,23 +1980,6 @@ const rtems_libio_helper rtems_fs_init_helper =
   #define CONFIGURE_MAXIMUM_GO_CHANNELS         0
 #endif
 
-#ifndef RTEMS_SCHEDSIM
-/**
- * This macro specifies the amount of memory to be reserved for the
- * Newlib C Library reentrancy structure -- if we are using newlib.
- */
-
-#if (defined(RTEMS_NEWLIB) && !defined(CONFIGURE_DISABLE_NEWLIB_REENTRANCY))
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_NEWLIB \
-    _Configure_From_workspace(sizeof(struct _reent))
-#else
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_NEWLIB 0
-#endif
-
-#else
-  #define CONFIGURE_MEMORY_PER_TASK_FOR_NEWLIB 0
-#endif
-
 /**
  * This is so we can account for tasks with stacks greater than minimum
  * size.  This is in bytes.
@@ -2075,17 +2003,7 @@ const rtems_libio_helper rtems_fs_init_helper =
 
 #define CONFIGURE_MEMORY_FOR_TASKS(_tasks, _number_FP_tasks) \
   ( \
-    _Configure_Object_RAM(_tasks, sizeof(Thread_Control)) \
-      + _Configure_Max_Objects(_tasks) \
-        * ( \
-            CONFIGURE_MEMORY_PER_TASK_FOR_CLASSIC_API \
-              + CONFIGURE_MEMORY_PER_TASK_FOR_NEWLIB \
-              + CONFIGURE_MEMORY_PER_TASK_FOR_POSIX_API \
-              + CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER \
-              + _Configure_From_workspace( \
-                CONFIGURE_MAXIMUM_USER_EXTENSIONS * sizeof(void *) \
-              ) \
-          ) \
+    _Configure_Object_RAM(_tasks, sizeof(Configuration_Thread_control)) \
       + _Configure_Max_Objects(_number_FP_tasks) \
         * _Configure_From_workspace(CONTEXT_FP_SIZE) \
         * (CONTEXT_FP_SIZE != 0) \
@@ -2358,6 +2276,76 @@ const rtems_libio_helper rtems_fs_init_helper =
   )
 
 #ifdef CONFIGURE_INIT
+  typedef struct {
+    Thread_Control Control;
+    #if CONFIGURE_MAXIMUM_USER_EXTENSIONS > 0
+      void *extensions[ CONFIGURE_MAXIMUM_USER_EXTENSIONS ];
+    #endif
+    union {
+      #ifdef CONFIGURE_SCHEDULER_CBS
+        Scheduler_CBS_Per_thread CBS;
+      #endif
+      #ifdef CONFIGURE_SCHEDULER_EDF
+        Scheduler_EDF_Per_thread EDF;
+      #endif
+      #if defined(CONFIGURE_SCHEDULER_PRIORITY) \
+        || defined(CONFIGURE_SCHEDULER_PRIORITY_AFFINITY_SMP) \
+        || defined(CONFIGURE_SCHEDULER_PRIORITY_SMP)
+        Scheduler_priority_Per_thread Priority;
+      #endif
+      #ifdef CONFIGURE_SCHEDULER_USER_PER_THREAD
+        CONFIGURE_SCHEDULER_USER_PER_THREAD User;
+      #endif
+    } Scheduler;
+    RTEMS_API_Control API_RTEMS;
+    #ifndef CONFIGURE_DISABLE_CLASSIC_API_NOTEPADS
+      uint32_t Notepads[ RTEMS_NUMBER_NOTEPADS ];
+    #endif
+    #ifdef RTEMS_POSIX_API
+      POSIX_API_Control API_POSIX;
+    #endif
+    #if !defined(RTEMS_SCHEDSIM) \
+      && defined(RTEMS_NEWLIB) \
+      && !defined(CONFIGURE_DISABLE_NEWLIB_REENTRANCY)
+      struct _reent Newlib;
+    #else
+      struct { /* Empty */ } Newlib;
+    #endif
+  } Configuration_Thread_control;
+
+  const size_t _Thread_Control_size = sizeof( Configuration_Thread_control );
+
+  const Thread_Control_add_on _Thread_Control_add_ons[] = {
+    {
+      offsetof( Configuration_Thread_control, Control.scheduler_info ),
+      offsetof( Configuration_Thread_control, Scheduler )
+    }, {
+      offsetof(
+        Configuration_Thread_control,
+        Control.API_Extensions[ THREAD_API_RTEMS ]
+      ),
+      offsetof( Configuration_Thread_control, API_RTEMS )
+    }, {
+      offsetof(
+        Configuration_Thread_control,
+        Control.libc_reent
+      ),
+      offsetof( Configuration_Thread_control, Newlib )
+    }
+    #ifdef RTEMS_POSIX_API
+      , {
+        offsetof(
+          Configuration_Thread_control,
+          Control.API_Extensions[ THREAD_API_POSIX ]
+        ),
+        offsetof( Configuration_Thread_control, API_POSIX )
+      }
+    #endif
+  };
+
+  const size_t _Thread_Control_add_on_count =
+    RTEMS_ARRAY_SIZE( _Thread_Control_add_ons );
+
   /**
    * This is the Classic API Configuration Table.
    */
@@ -2554,7 +2542,6 @@ const rtems_libio_helper rtems_fs_init_helper =
     uint32_t INTERRUPT_VECTOR_TABLE;
     uint32_t INTERRUPT_STACK_MEMORY;
     uint32_t MEMORY_FOR_IDLE_TASK;
-    uint32_t MEMORY_PER_TASK_FOR_SCHEDULER;
 
     /* Classic API Pieces */
     uint32_t CLASSIC_TASKS;
@@ -2610,7 +2597,6 @@ const rtems_libio_helper rtems_fs_init_helper =
     CONFIGURE_INTERRUPT_VECTOR_TABLE,
     CONFIGURE_INTERRUPT_STACK_MEMORY,
     CONFIGURE_MEMORY_FOR_IDLE_TASK,
-    CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER,
 
     /* Classic API Pieces */
     CONFIGURE_MEMORY_FOR_TASKS(CONFIGURE_MAXIMUM_TASKS, 0),
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 9db4295..f697d7b 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -205,12 +205,10 @@ libscore_a_SOURCES += src/schedulerdefaultupdate.c
 
 ## SCHEDULERPRIORITY_C_FILES
 libscore_a_SOURCES += src/schedulerpriority.c \
-    src/schedulerpriorityallocate.c \
     src/schedulerpriorityblock.c \
     src/schedulerpriorityenqueue.c \
     src/schedulerpriorityenqueuefirst.c \
     src/schedulerpriorityextract.c \
-    src/schedulerpriorityfree.c \
     src/schedulerpriorityops.c \
     src/schedulerpriorityprioritycompare.c \
     src/schedulerpriorityschedule.c \
@@ -238,7 +236,6 @@ libscore_a_SOURCES += src/scheduleredf.c \
     src/scheduleredfenqueue.c \
     src/scheduleredfenqueuefirst.c \
     src/scheduleredfextract.c \
-    src/scheduleredffree.c \
     src/scheduleredfops.c \
     src/scheduleredfprioritycompare.c \
     src/scheduleredfreleasejob.c \
diff --git a/cpukit/score/include/rtems/score/schedulercbsimpl.h b/cpukit/score/include/rtems/score/schedulercbsimpl.h
index 0f59d97..253a1a6 100644
--- a/cpukit/score/include/rtems/score/schedulercbsimpl.h
+++ b/cpukit/score/include/rtems/score/schedulercbsimpl.h
@@ -228,7 +228,7 @@ void _Scheduler_CBS_Budget_callout(
  *  @param[in] the_thread is the thread the scheduler is allocating
  *             management memory for.
  */
-void *_Scheduler_CBS_Allocate(
+bool _Scheduler_CBS_Allocate(
   Scheduler_Control *scheduler,
   Thread_Control    *the_thread
 );
diff --git a/cpukit/score/include/rtems/score/scheduleredfimpl.h b/cpukit/score/include/rtems/score/scheduleredfimpl.h
index 5aa53b2..be1e576 100644
--- a/cpukit/score/include/rtems/score/scheduleredfimpl.h
+++ b/cpukit/score/include/rtems/score/scheduleredfimpl.h
@@ -73,20 +73,7 @@ void _Scheduler_EDF_Schedule(
  *  @param[in] the_thread is the thread the scheduler is allocating
  *             management memory for.
  */
-void *_Scheduler_EDF_Allocate(
-  Scheduler_Control *scheduler,
-  Thread_Control    *the_thread
-);
-
-/**
- *  @brief Frees EDF information of a thread.
- *
- *  This routine frees the EDF specific information of @a the_thread.
- *
- *  @param[in] the_thread is the thread whose scheduler specific information
- *             will be deallocated.
- */
-void _Scheduler_EDF_Free(
+bool _Scheduler_EDF_Allocate(
   Scheduler_Control *scheduler,
   Thread_Control    *the_thread
 );
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index b0f5c4b..ce0d207 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -61,7 +61,7 @@ struct Scheduler_Operations {
   void ( *unblock )( Scheduler_Control *, Thread_Control * );
 
   /** allocates the scheduler field of the given thread */
-  void * ( *allocate )( Scheduler_Control *, Thread_Control * );
+  bool ( *allocate )( Scheduler_Control *, Thread_Control * );
 
   /** frees the scheduler field of the given thread */
   void ( *free )( Scheduler_Control *, Thread_Control * );
@@ -225,7 +225,7 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Unblock(
  *
  * This routine allocates @a the_thread->scheduler
  */
-RTEMS_INLINE_ROUTINE void* _Scheduler_Allocate(
+RTEMS_INLINE_ROUTINE bool _Scheduler_Allocate(
   Scheduler_Control *scheduler,
   Thread_Control    *the_thread
 )
@@ -520,7 +520,7 @@ RTEMS_INLINE_ROUTINE Scheduler_Control *_Scheduler_Get(
  *
  * @return An arbitrary non-NULL value.
  */
-void *_Scheduler_default_Allocate(
+bool _Scheduler_default_Allocate(
   Scheduler_Control *scheduler,
   Thread_Control    *the_thread
 );
diff --git a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
index 8a84669..8175173 100644
--- a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h
@@ -68,32 +68,6 @@ void _Scheduler_priority_Schedule(
 );
 
 /**
- *  @brief Allocates @a the_thread->scheduler.
- *
- *  This routine allocates @a the_thread->scheduler.
- *
- *  @param[in] the_thread is the thread the scheduler is allocating
- *             management memory for
- */
-void * _Scheduler_priority_Allocate(
-  Scheduler_Control *scheduler,
-  Thread_Control    *the_thread
-);
-
-/**
- *  @brief Frees @a the_thread->scheduler.
- *
- *  This routine frees @a the_thread->scheduler.
- *
- *  @param[in] the_thread is the thread whose scheduler specific information
- *             will be deallocated.
- */
-void _Scheduler_priority_Free(
-  Scheduler_Control *scheduler,
-  Thread_Control    *the_thread
-);
-
-/**
  *  @brief Update the scheduler priority.
  *  This routine updates @a the_thread->scheduler based on @a the_scheduler
  *  structures and thread state.
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 8c12969..b3f21c3 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -580,8 +580,6 @@ struct Thread_Control_struct {
   struct _reent                        *libc_reent;
   /** This array contains the API extension area pointers. */
   void                                 *API_Extensions[ THREAD_API_LAST + 1 ];
-  /** This field points to the user extension pointers. */
-  void                                **extensions;
 
   /** This field points to the set of per task variables. */
   rtems_task_variable_t                *task_variables;
@@ -596,6 +594,13 @@ struct Thread_Control_struct {
   Chain_Control           Key_Chain;
 
   Thread_Life_control                   Life;
+
+  /**
+   * @brief Variable length array of user extension pointers.
+   *
+   * The length is defined by the application via <rtems/confdefs.h>.
+   */
+  void                                 *extensions[ 0 ];
 };
 
 #if (CPU_PROVIDES_IDLE_THREAD_BODY == FALSE)
@@ -650,6 +655,17 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Get_executing( void )
   return executing;
 }
 
+typedef struct {
+  size_t destination_offset;
+  size_t source_offset;
+} Thread_Control_add_on;
+
+extern const Thread_Control_add_on _Thread_Control_add_ons[];
+
+extern const size_t _Thread_Control_add_on_count;
+
+extern const size_t _Thread_Control_size;
+
 /**@}*/
 
 #ifdef __cplusplus
diff --git a/cpukit/score/src/schedulercbsallocate.c b/cpukit/score/src/schedulercbsallocate.c
index b94ac9a..15c9697 100644
--- a/cpukit/score/src/schedulercbsallocate.c
+++ b/cpukit/score/src/schedulercbsallocate.c
@@ -21,24 +21,18 @@
 #include <rtems/score/schedulercbsimpl.h>
 #include <rtems/score/wkspace.h>
 
-void *_Scheduler_CBS_Allocate(
+bool _Scheduler_CBS_Allocate(
   Scheduler_Control *scheduler,
   Thread_Control    *the_thread
 )
 {
-  void *sched;
-  Scheduler_CBS_Per_thread *schinfo;
+  Scheduler_CBS_Per_thread *schinfo = the_thread->scheduler_info;
 
   (void) scheduler;
 
-  sched = _Workspace_Allocate(sizeof(Scheduler_CBS_Per_thread));
-  if ( sched ) {
-    the_thread->scheduler_info = sched;
-    schinfo = (Scheduler_CBS_Per_thread *)(the_thread->scheduler_info);
-    schinfo->edf_per_thread.thread = the_thread;
-    schinfo->edf_per_thread.queue_state = SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN;
-    schinfo->cbs_server = NULL;
-  }
+  schinfo->edf_per_thread.thread = the_thread;
+  schinfo->edf_per_thread.queue_state = SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN;
+  schinfo->cbs_server = NULL;
 
-  return sched;
+  return true;
 }
diff --git a/cpukit/score/src/schedulercbsops.c b/cpukit/score/src/schedulercbsops.c
index 6d943e3..ee4e8d5 100644
--- a/cpukit/score/src/schedulercbsops.c
+++ b/cpukit/score/src/schedulercbsops.c
@@ -26,7 +26,7 @@ const Scheduler_Operations _Scheduler_CBS_Operations = {
   .block = _Scheduler_EDF_Block,
   .unblock = _Scheduler_CBS_Unblock,
   .allocate = _Scheduler_CBS_Allocate,
-  .free = _Scheduler_EDF_Free,
+  .free = _Scheduler_default_Free,
   .update = _Scheduler_EDF_Update,
   .enqueue = _Scheduler_EDF_Enqueue,
   .enqueue_first = _Scheduler_EDF_Enqueue_first,
diff --git a/cpukit/score/src/schedulerdefaultallocatefree.c b/cpukit/score/src/schedulerdefaultallocatefree.c
index 46cbe81..8ea71a7 100644
--- a/cpukit/score/src/schedulerdefaultallocatefree.c
+++ b/cpukit/score/src/schedulerdefaultallocatefree.c
@@ -21,7 +21,7 @@
 
 #include <rtems/score/schedulerimpl.h>
 
-void *_Scheduler_default_Allocate(
+bool _Scheduler_default_Allocate(
   Scheduler_Control *scheduler,
   Thread_Control    *the_thread
 )
@@ -29,7 +29,7 @@ void *_Scheduler_default_Allocate(
   ( void ) scheduler;
   ( void ) the_thread;
 
-  return ( void * )-1; /* maybe pick an appropriate poison value */
+  return true;
 }
 
 void _Scheduler_default_Free(
diff --git a/cpukit/score/src/scheduleredfallocate.c b/cpukit/score/src/scheduleredfallocate.c
index a8c65c5..05db294 100644
--- a/cpukit/score/src/scheduleredfallocate.c
+++ b/cpukit/score/src/scheduleredfallocate.c
@@ -21,24 +21,18 @@
 #include <rtems/score/scheduleredfimpl.h>
 #include <rtems/score/wkspace.h>
 
-void *_Scheduler_EDF_Allocate(
+bool _Scheduler_EDF_Allocate(
   Scheduler_Control *scheduler,
   Thread_Control    *the_thread
 )
 {
-  void *sched;
-  Scheduler_EDF_Per_thread *schinfo;
+  Scheduler_EDF_Per_thread *schinfo = the_thread->scheduler_info;
 
   (void) scheduler;
 
-  sched = _Workspace_Allocate( sizeof(Scheduler_EDF_Per_thread) );
+  schinfo = (Scheduler_EDF_Per_thread *)(the_thread->scheduler_info);
+  schinfo->thread = the_thread;
+  schinfo->queue_state = SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN;
 
-  if ( sched ) {
-    the_thread->scheduler_info = sched;
-    schinfo = (Scheduler_EDF_Per_thread *)(the_thread->scheduler_info);
-    schinfo->thread = the_thread;
-    schinfo->queue_state = SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN;
-  }
-
-  return sched;
+  return true;
 }
diff --git a/cpukit/score/src/scheduleredffree.c b/cpukit/score/src/scheduleredffree.c
deleted file mode 100644
index a612121..0000000
--- a/cpukit/score/src/scheduleredffree.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * @file
- *
- * @brief Frees EDF Thread Information
- *
- * @ingroup ScoreScheduler
- */
-
-/*
- *  Copyright (C) 2011 Petr Benes.
- *  Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
- *
- *  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.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <rtems/score/scheduleredfimpl.h>
-#include <rtems/score/wkspace.h>
-
-void _Scheduler_EDF_Free(
-  Scheduler_Control *scheduler,
-  Thread_Control    *the_thread
-)
-{
-  (void) scheduler;
-
-  _Workspace_Free( the_thread->scheduler_info );
-}
diff --git a/cpukit/score/src/scheduleredfops.c b/cpukit/score/src/scheduleredfops.c
index 03d1827..1acfeaf 100644
--- a/cpukit/score/src/scheduleredfops.c
+++ b/cpukit/score/src/scheduleredfops.c
@@ -26,7 +26,7 @@ const Scheduler_Operations _Scheduler_EDF_Operations = {
   .block = _Scheduler_EDF_Block,
   .unblock = _Scheduler_EDF_Unblock,
   .allocate = _Scheduler_EDF_Allocate,
-  .free = _Scheduler_EDF_Free,
+  .free = _Scheduler_default_Free,
   .update = _Scheduler_EDF_Update,
   .enqueue = _Scheduler_EDF_Enqueue,
   .enqueue_first = _Scheduler_EDF_Enqueue_first,
diff --git a/cpukit/score/src/schedulerpriorityaffinitysmp.c b/cpukit/score/src/schedulerpriorityaffinitysmp.c
index 2f8fe42..b210496 100644
--- a/cpukit/score/src/schedulerpriorityaffinitysmp.c
+++ b/cpukit/score/src/schedulerpriorityaffinitysmp.c
@@ -37,12 +37,10 @@ static void * _Scheduler_priority_affinity_SMP_Allocate(
 )
 {
   Scheduler_priority_affinity_SMP_Per_thread *info =
-    _Workspace_Allocate( sizeof( *info ) );
+    the_thread->scheduler_info;
 
   info->Affinity = *_CPU_set_Default();
   info->Affinity.set = &info->Affinity.preallocated;
- 
-  the_thread->scheduler_info = info;
 
   return info;
 }
@@ -95,7 +93,7 @@ const Scheduler_Operations _Scheduler_priority_affinity_SMP_Operations = {
   .block = _Scheduler_priority_SMP_Block,
   .unblock = _Scheduler_priority_SMP_Enqueue_fifo,
   .allocate = _Scheduler_priority_affinity_SMP_Allocate,
-  .free = _Scheduler_priority_Free,
+  .free = _Scheduler_default_Free,
   .update = _Scheduler_priority_SMP_Update,
   .enqueue = _Scheduler_priority_SMP_Enqueue_fifo,
   .enqueue_first = _Scheduler_priority_SMP_Enqueue_lifo,
diff --git a/cpukit/score/src/schedulerpriorityallocate.c b/cpukit/score/src/schedulerpriorityallocate.c
deleted file mode 100644
index db362e7..0000000
--- a/cpukit/score/src/schedulerpriorityallocate.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- *  @file
- *
- *  @brief Allocate Scheduler Priority
- *  @ingroup ScoreScheduler
- */
-
-/*
- *  Copyright (C) 2010 Gedare Bloom.
- *  Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
- *
- *  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.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <rtems/score/schedulerpriorityimpl.h>
-#include <rtems/score/wkspace.h>
-
-void *_Scheduler_priority_Allocate (
-  Scheduler_Control *scheduler,
-  Thread_Control    *the_thread
-)
-{
-  Scheduler_priority_Per_thread *sched_info_of_thread =
-    _Workspace_Allocate( sizeof( *sched_info_of_thread ) );
-
-  (void) scheduler;
-
-  the_thread->scheduler_info = sched_info_of_thread;
-
-  return sched_info_of_thread;
-}
diff --git a/cpukit/score/src/schedulerpriorityfree.c b/cpukit/score/src/schedulerpriorityfree.c
deleted file mode 100644
index 5529f78..0000000
--- a/cpukit/score/src/schedulerpriorityfree.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- *  @file
- *
- *  @brief Free Scheduler Priority
- *  @ingroup ScoreScheduler
- */
-
-/*
- *  Copyright (C) 2010 Gedare Bloom.
- *  Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
- *
- *  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.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <rtems/system.h>
-#include <rtems/config.h>
-#include <rtems/score/scheduler.h>
-#include <rtems/score/schedulerpriority.h>
-#include <rtems/score/wkspace.h>
-
-void _Scheduler_priority_Free (
-  Scheduler_Control *base,
-  Thread_Control    *the_thread
-)
-{
-  (void) base;
-
-  _Workspace_Free( the_thread->scheduler_info );
-}
diff --git a/cpukit/score/src/schedulerpriorityops.c b/cpukit/score/src/schedulerpriorityops.c
index 9d16aeb..b62104e 100644
--- a/cpukit/score/src/schedulerpriorityops.c
+++ b/cpukit/score/src/schedulerpriorityops.c
@@ -25,8 +25,8 @@ const Scheduler_Operations _Scheduler_priority_Operations = {
   .yield = _Scheduler_priority_Yield,
   .block = _Scheduler_priority_Block,
   .unblock = _Scheduler_priority_Unblock,
-  .allocate = _Scheduler_priority_Allocate,
-  .free = _Scheduler_priority_Free,
+  .allocate = _Scheduler_default_Allocate,
+  .free = _Scheduler_default_Free,
   .update = _Scheduler_priority_Update,
   .enqueue = _Scheduler_priority_Enqueue,
   .enqueue_first = _Scheduler_priority_Enqueue_first,
diff --git a/cpukit/score/src/schedulerprioritysmp.c b/cpukit/score/src/schedulerprioritysmp.c
index f63cf71..27f1c35 100644
--- a/cpukit/score/src/schedulerprioritysmp.c
+++ b/cpukit/score/src/schedulerprioritysmp.c
@@ -297,8 +297,8 @@ const Scheduler_Operations _Scheduler_priority_SMP_Operations = {
   .yield = _Scheduler_priority_SMP_Yield,
   .block = _Scheduler_priority_SMP_Block,
   .unblock = _Scheduler_priority_SMP_Enqueue_fifo,
-  .allocate = _Scheduler_priority_Allocate,
-  .free = _Scheduler_priority_Free,
+  .allocate = _Scheduler_default_Allocate,
+  .free = _Scheduler_default_Free,
   .update = _Scheduler_priority_SMP_Update,
   .enqueue = _Scheduler_priority_SMP_Enqueue_fifo,
   .enqueue_first = _Scheduler_priority_SMP_Enqueue_lifo,
diff --git a/cpukit/score/src/thread.c b/cpukit/score/src/thread.c
index a77fe5f..226e63a 100644
--- a/cpukit/score/src/thread.c
+++ b/cpukit/score/src/thread.c
@@ -64,8 +64,7 @@ void _Thread_Handler_initialization(void)
     OBJECTS_INTERNAL_API,
     OBJECTS_INTERNAL_THREADS,
     _Thread_Get_maximum_internal_threads(),
-    sizeof( Thread_Control ),
-                                /* size of this object's control block */
+    _Thread_Control_size,       /* size of this object's control block */
     false,                      /* true if names for this object are strings */
     8                           /* maximum length of each object's name */
     #if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 79cbd7c..1aa4ffd 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -45,12 +45,12 @@ bool _Thread_Initialize(
   size_t     actual_stack_size = 0;
   void      *stack = NULL;
   #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
-    void    *fp_area;
+    void    *fp_area = NULL;
   #endif
-  void      *sched = NULL;
-  void      *extensions_area;
   bool       extension_status;
-  int        i;
+  size_t     i;
+  bool       scheduler_allocated = false;
+  Scheduler_Control *scheduler;
 
   /*
    * Do not use _TLS_Size here since this will lead GCC to assume that this
@@ -64,6 +64,13 @@ bool _Thread_Initialize(
   }
 #endif
 
+  for ( i = 0 ; i < _Thread_Control_add_on_count ; ++i ) {
+    const Thread_Control_add_on *add_on = &_Thread_Control_add_ons[ i ];
+
+    *(void **) ( (char *) the_thread + add_on->destination_offset ) =
+      (char *) the_thread + add_on->source_offset;
+  }
+
   /*
    *  Initialize the Ada self pointer
    */
@@ -71,20 +78,8 @@ bool _Thread_Initialize(
     the_thread->rtems_ada_self = NULL;
   #endif
 
-  /*
-   *  Zero out all the allocated memory fields
-   */
-  for ( i=0 ; i <= THREAD_API_LAST ; i++ )
-    the_thread->API_Extensions[i] = NULL;
-
-  extensions_area = NULL;
-  the_thread->libc_reent = NULL;
   the_thread->Start.tls_area = NULL;
 
-  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
-    fp_area = NULL;
-  #endif
-
   /*
    *  Allocate and Initialize the stack for this thread.
    */
@@ -153,18 +148,6 @@ bool _Thread_Initialize(
   #endif
 
   /*
-   *  Allocate the extensions area for this thread
-   */
-  if ( rtems_configuration_get_maximum_extensions() ) {
-    extensions_area = _Workspace_Allocate(
-      rtems_configuration_get_maximum_extensions() * sizeof( void * )
-    );
-    if ( !extensions_area )
-      goto failed;
-  }
-  the_thread->extensions = (void **) extensions_area;
-
-  /*
    * Clear the extensions area so extension users can determine
    * if they are linked to the thread. An extension user may
    * create the extension long after tasks have been created
@@ -214,9 +197,13 @@ bool _Thread_Initialize(
   the_thread->resource_count          = 0;
   the_thread->real_priority           = priority;
   the_thread->Start.initial_priority  = priority;
-  sched =_Scheduler_Allocate( _Scheduler_Get( the_thread ), the_thread );
-  if ( !sched )
+
+  scheduler = _Scheduler_Get( _Thread_Get_executing() );
+  scheduler_allocated = _Scheduler_Allocate( scheduler, the_thread );
+  if ( !scheduler_allocated ) {
     goto failed;
+  }
+
   _Thread_Set_priority( the_thread, priority );
 
   /*
@@ -259,21 +246,17 @@ bool _Thread_Initialize(
     return true;
 
 failed:
-  _Workspace_Free( the_thread->Start.tls_area );
-
-  _Workspace_Free( the_thread->libc_reent );
 
-  for ( i=0 ; i <= THREAD_API_LAST ; i++ )
-    _Workspace_Free( the_thread->API_Extensions[i] );
+  if ( scheduler_allocated ) {
+    _Scheduler_Free( scheduler, the_thread );
+  }
 
-  _Workspace_Free( extensions_area );
+  _Workspace_Free( the_thread->Start.tls_area );
 
   #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
     _Workspace_Free( fp_area );
   #endif
 
-   _Workspace_Free( sched );
-
    _Thread_Stack_Free( the_thread );
   return false;
 }
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index fcf9d6c..f7bfe65 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -91,8 +91,6 @@ static void _Thread_Free( Thread_Control *the_thread )
    */
   _Thread_Stack_Free( the_thread );
 
-  _Workspace_Free( the_thread->extensions );
-
   _Workspace_Free( the_thread->Start.tls_area );
 
   _Objects_Free(
-- 
1.7.7




More information about the devel mailing list