source: rtems/cpukit/rtems/src/tasks.c @ 69aa3349

4.11
Last change on this file since 69aa3349 was 69aa3349, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 8, 2014 at 7:42:29 AM

score: Simplify thread control initialization

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

This helps also to avoid heap fragementation and reduces the per thread
memory due to a reduced heap allocation overhead.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief RTEMS Task API Extensions
5 *  @ingroup ClassicTasks
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2014.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/system.h>
22#include <rtems/config.h>
23#include <rtems/rtems/asrimpl.h>
24#include <rtems/rtems/eventimpl.h>
25#include <rtems/rtems/signalimpl.h>
26#include <rtems/rtems/status.h>
27#include <rtems/rtems/support.h>
28#include <rtems/rtems/modes.h>
29#include <rtems/rtems/tasksimpl.h>
30#include <rtems/posix/keyimpl.h>
31#include <rtems/score/stack.h>
32#include <rtems/score/threadimpl.h>
33#include <rtems/score/userextimpl.h>
34#include <rtems/score/wkspace.h>
35#include <rtems/score/apiext.h>
36
37/*
38 *  _RTEMS_tasks_Create_extension
39 *
40 *  This routine is an extension routine that is invoked as part
41 *  of creating any type of task or thread in the system.  If the
42 *  task is created via another API, then this routine is invoked
43 *  and this API given the opportunity to initialize its extension
44 *  area.
45 */
46
47static bool _RTEMS_tasks_Create_extension(
48  Thread_Control *executing,
49  Thread_Control *created
50)
51{
52  RTEMS_API_Control *api;
53  size_t             i;
54
55  api = created->API_Extensions[ THREAD_API_RTEMS ];
56
57  _Event_Initialize( &api->Event );
58  _Event_Initialize( &api->System_event );
59  _ASR_Initialize( &api->Signal );
60  _Thread_Action_initialize( &api->Signal_action, _Signal_Action_handler );
61#if !defined(RTEMS_SMP)
62  created->task_variables = NULL;
63#endif
64
65  if ( rtems_configuration_get_notepads_enabled() ) {
66    for (i=0; i < RTEMS_NUMBER_NOTEPADS; i++)
67      api->Notepads[i] = 0;
68  }
69
70  return true;
71}
72
73/*
74 *  _RTEMS_tasks_Start_extension
75 *
76 *  This extension routine is invoked when a task is started for the
77 *  first time.
78 */
79
80static void _RTEMS_tasks_Start_extension(
81  Thread_Control *executing,
82  Thread_Control *started
83)
84{
85  RTEMS_API_Control *api;
86
87  api = started->API_Extensions[ THREAD_API_RTEMS ];
88
89  _Event_Initialize( &api->Event );
90  _Event_Initialize( &api->System_event );
91}
92
93static void _RTEMS_tasks_Terminate_extension(
94  Thread_Control *executing
95)
96{
97
98  /*
99   *  Free per task variable memory
100   *
101   *  Per Task Variables are only enabled in uniprocessor configurations
102   */
103  #if !defined(RTEMS_SMP)
104    do { 
105      rtems_task_variable_t *tvp, *next;
106
107      tvp = executing->task_variables;
108      executing->task_variables = NULL;
109      while (tvp) {
110        next = (rtems_task_variable_t *)tvp->next;
111        _RTEMS_Tasks_Invoke_task_variable_dtor( executing, tvp );
112        tvp = next;
113      }
114    } while (0);
115  #endif
116
117  /*
118   *  Run all the key destructors
119   */
120  _POSIX_Keys_Run_destructors( executing );
121}
122
123#if !defined(RTEMS_SMP)
124/*
125 *  _RTEMS_tasks_Switch_extension
126 *
127 *  This extension routine is invoked at each context switch.
128 *
129 *  @note Since this only needs to address per-task variables, it is
130 *        disabled entirely for SMP configurations.
131 */
132static void _RTEMS_tasks_Switch_extension(
133  Thread_Control *executing,
134  Thread_Control *heir
135)
136{
137  rtems_task_variable_t *tvp;
138
139  /*
140   *  Per Task Variables are only enabled in uniprocessor configurations
141   */
142
143  tvp = executing->task_variables;
144  while (tvp) {
145    tvp->tval = *tvp->ptr;
146    *tvp->ptr = tvp->gval;
147    tvp = (rtems_task_variable_t *)tvp->next;
148  }
149
150  tvp = heir->task_variables;
151  while (tvp) {
152    tvp->gval = *tvp->ptr;
153    *tvp->ptr = tvp->tval;
154    tvp = (rtems_task_variable_t *)tvp->next;
155  }
156}
157#define RTEMS_TASKS_SWITCH_EXTENSION _RTEMS_tasks_Switch_extension
158#else
159#define RTEMS_TASKS_SWITCH_EXTENSION NULL
160#endif
161
162API_extensions_Control _RTEMS_tasks_API_extensions = {
163  #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
164    .predriver_hook = NULL,
165  #endif
166  .postdriver_hook = _RTEMS_tasks_Initialize_user_tasks
167};
168
169User_extensions_Control _RTEMS_tasks_User_extensions = {
170  { NULL, NULL },
171  { { NULL, NULL }, RTEMS_TASKS_SWITCH_EXTENSION },
172  { _RTEMS_tasks_Create_extension,            /* create */
173    _RTEMS_tasks_Start_extension,             /* start */
174    _RTEMS_tasks_Start_extension,             /* restart */
175    NULL,                                     /* delete */
176    RTEMS_TASKS_SWITCH_EXTENSION,             /* switch */
177    NULL,                                     /* begin */
178    NULL,                                     /* exitted */
179    NULL,                                     /* fatal */
180    _RTEMS_tasks_Terminate_extension          /* terminate */
181  }
182};
183
184void _RTEMS_tasks_Manager_initialization(void)
185{
186  _Objects_Initialize_information(
187    &_RTEMS_tasks_Information, /* object information table */
188    OBJECTS_CLASSIC_API,       /* object API */
189    OBJECTS_RTEMS_TASKS,       /* object class */
190    Configuration_RTEMS_API.maximum_tasks,
191                               /* maximum objects of this class */
192    _Thread_Control_size,      /* size of this object's control block */
193    false,                     /* true if the name is a string */
194    RTEMS_MAXIMUM_NAME_LENGTH  /* maximum length of an object name */
195#if defined(RTEMS_MULTIPROCESSING)
196    ,
197    true,                      /* true if this is a global object class */
198    NULL                       /* Proxy extraction support callout */
199#endif
200  );
201
202  /*
203   *  Add all the extensions for this API
204   */
205
206  _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions );
207
208  _API_extensions_Add( &_RTEMS_tasks_API_extensions );
209
210  /*
211   *  Register the MP Process Packet routine.
212   */
213
214#if defined(RTEMS_MULTIPROCESSING)
215  _MPCI_Register_packet_processor(
216    MP_PACKET_TASKS,
217    _RTEMS_tasks_MP_Process_packet
218  );
219#endif
220
221}
222
223void _RTEMS_tasks_Initialize_user_tasks( void )
224{
225  if ( _RTEMS_tasks_Initialize_user_tasks_p )
226    (*_RTEMS_tasks_Initialize_user_tasks_p)();
227}
Note: See TracBrowser for help on using the repository browser.