RTEMS
taskconstruct.c
Go to the documentation of this file.
1 
9 /*
10  * COPYRIGHT (c) 1989-2014,2016.
11  * On-Line Applications Research Corporation (OAR).
12  *
13  * The license and distribution terms for this file may be
14  * found in the file LICENSE in this distribution or at
15  * http://www.rtems.org/license/LICENSE.
16  */
17 
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 
22 #include <rtems/rtems/tasksimpl.h>
23 #include <rtems/rtems/attrimpl.h>
24 #include <rtems/rtems/eventimpl.h>
25 #include <rtems/rtems/modesimpl.h>
26 #include <rtems/rtems/support.h>
27 #include <rtems/score/apimutex.h>
29 #include <rtems/score/stackimpl.h>
30 #include <rtems/score/threadimpl.h>
32 #include <rtems/sysinit.h>
33 
34 #include <string.h>
35 
36 static rtems_status_code _RTEMS_tasks_Prepare_user_stack(
37  Thread_Configuration *thread_config,
38  const rtems_task_config *config
39 )
40 {
41  size_t size;
42 
43  size = _TLS_Get_allocation_size();
44 
45  if ( config->maximum_thread_local_storage_size < size ) {
46  return RTEMS_INVALID_SIZE;
47  }
48 
49 #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
50  if ( thread_config->is_fp ) {
51  size += CONTEXT_FP_SIZE;
52  }
53 #endif
54 
55  size += _Stack_Minimum();
56 
57  if ( config->storage_size < size ) {
58  return RTEMS_INVALID_SIZE;
59  }
60 
61  thread_config->stack_size = config->storage_size;
62  thread_config->stack_area = config->storage_area;
63 
64  if ( config->storage_free != NULL ) {
65  thread_config->stack_free = config->storage_free;
66  } else {
67  thread_config->stack_free = _Stack_Free_nothing;
68  }
69 
70  return RTEMS_SUCCESSFUL;
71 }
72 
74  const rtems_task_config *config,
75  rtems_id *id
76 )
77 {
78  return _RTEMS_tasks_Create( config, id, _RTEMS_tasks_Prepare_user_stack );
79 }
80 
81 rtems_status_code _RTEMS_tasks_Create(
82  const rtems_task_config *config,
83  rtems_id *id,
84  RTEMS_tasks_Prepare_stack prepare_stack
85 )
86 {
87  Thread_Control *the_thread;
88  Thread_Configuration thread_config;
89 #if defined(RTEMS_MULTIPROCESSING)
90  Objects_MP_Control *the_global_object = NULL;
91  bool is_global;
92 #endif
93  rtems_status_code status;
94  rtems_attribute attributes;
95  bool valid;
96  RTEMS_API_Control *api;
97  ASR_Information *asr;
98 
99  if ( !rtems_is_name_valid( config->name ) ) {
100  return RTEMS_INVALID_NAME;
101  }
102 
103  if ( id == NULL ) {
104  return RTEMS_INVALID_ADDRESS;
105  }
106 
107  /*
108  * Core Thread Initialize insures we get the minimum amount of
109  * stack space.
110  */
111 
112  /*
113  * Fix the attribute set to match the attributes which
114  * this processor (1) requires and (2) is able to support.
115  * First add in the required flags for attributes
116  * Typically this might include FP if the platform
117  * or application required all tasks to be fp aware.
118  * Then turn off the requested bits which are not supported.
119  */
120 
121  attributes = _Attributes_Set( config->attributes, ATTRIBUTES_REQUIRED );
122  attributes = _Attributes_Clear( attributes, ATTRIBUTES_NOT_SUPPORTED );
123 
124  memset( &thread_config, 0, sizeof( thread_config ) );
125  thread_config.budget_algorithm = _Modes_Is_timeslice( config->initial_modes ) ?
126  THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE
127  : THREAD_CPU_BUDGET_ALGORITHM_NONE,
128  thread_config.isr_level = _Modes_Get_interrupt_level( config->initial_modes );
129  thread_config.name.name_u32 = config->name;
130  thread_config.is_fp = _Attributes_Is_floating_point( attributes );
131  thread_config.is_preemptible = _Modes_Is_preempt( config->initial_modes );
132 
133  /*
134  * Validate the RTEMS API priority and convert it to the core priority range.
135  */
136 
137  if ( !_Attributes_Is_system_task( attributes ) ) {
138  if ( config->initial_priority == PRIORITY_MINIMUM ) {
139  return RTEMS_INVALID_PRIORITY;
140  }
141  }
142 
143  thread_config.scheduler =
145 
146  thread_config.priority = _RTEMS_Priority_To_core(
147  thread_config.scheduler,
148  config->initial_priority,
149  &valid
150  );
151  if ( !valid ) {
152  return RTEMS_INVALID_PRIORITY;
153  }
154 
155 #if defined(RTEMS_MULTIPROCESSING)
156  if ( !_System_state_Is_multiprocessing ) {
157  attributes = _Attributes_Clear( attributes, RTEMS_GLOBAL );
158  }
159 
160  is_global = _Attributes_Is_global( attributes );
161 #endif
162 
163  /*
164  * Allocate the thread control block and -- if the task is global --
165  * allocate a global object control block.
166  *
167  * NOTE: This routine does not use the combined allocate and open
168  * global object routine (_Objects_MP_Allocate_and_open) because
169  * this results in a lack of control over when memory is allocated
170  * and can be freed in the event of an error.
171  */
172  the_thread = _RTEMS_tasks_Allocate();
173 
174  if ( !the_thread ) {
176  return RTEMS_TOO_MANY;
177  }
178 
179 #if defined(RTEMS_MULTIPROCESSING)
180  if ( is_global ) {
181  the_global_object = _Objects_MP_Allocate_global_object();
182 
183  if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
184  _RTEMS_tasks_Free( the_thread );
186  return RTEMS_TOO_MANY;
187  }
188  }
189 #endif
190 
191  status = ( *prepare_stack )( &thread_config, config );
192 
193  /*
194  * Initialize the core thread for this task.
195  */
196 
197  if ( status == RTEMS_SUCCESSFUL ) {
198  bool ok;
199 
200  ok = _Thread_Initialize(
202  the_thread,
203  &thread_config
204  );
205 
206  if ( !ok ) {
207  status = RTEMS_UNSATISFIED;
208  }
209  }
210 
211  if ( status != RTEMS_SUCCESSFUL ) {
212 #if defined(RTEMS_MULTIPROCESSING)
213  if ( is_global )
214  _Objects_MP_Free_global_object( the_global_object );
215 #endif
216  _RTEMS_tasks_Free( the_thread );
218  return status;
219  }
220 
221  api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
222  asr = &api->Signal;
223 
225 
226  *id = the_thread->Object.id;
227 
228 #if defined(RTEMS_MULTIPROCESSING)
229  the_thread->is_global = is_global;
230  if ( is_global ) {
231 
232  _Objects_MP_Open(
234  the_global_object,
235  config->name,
236  the_thread->Object.id
237  );
238 
239  _RTEMS_tasks_MP_Send_process_packet(
240  RTEMS_TASKS_MP_ANNOUNCE_CREATE,
241  the_thread->Object.id,
242  config->name
243  );
244 
245  }
246 #endif
247 
249  return RTEMS_SUCCESSFUL;
250 }
251 
252 static void _RTEMS_tasks_Start_extension(
253  Thread_Control *executing,
254  Thread_Control *started
255 )
256 {
257  RTEMS_API_Control *api;
258 
259  api = started->API_Extensions[ THREAD_API_RTEMS ];
260 
261  _Event_Initialize( &api->Event );
262  _Event_Initialize( &api->System_event );
263 }
264 
265 #if defined(RTEMS_MULTIPROCESSING)
266 static void _RTEMS_tasks_Terminate_extension( Thread_Control *executing )
267 {
268  if ( executing->is_global ) {
269  _Objects_MP_Close(
271  executing->Object.id
272  );
273  _RTEMS_tasks_MP_Send_process_packet(
274  RTEMS_TASKS_MP_ANNOUNCE_DELETE,
275  executing->Object.id,
276  0 /* Not used */
277  );
278  }
279 }
280 #endif
281 
282 static User_extensions_Control _RTEMS_tasks_User_extensions = {
283  .Callouts = {
284 #if defined(RTEMS_MULTIPROCESSING)
285  .thread_terminate = _RTEMS_tasks_Terminate_extension,
286 #endif
287  .thread_start = _RTEMS_tasks_Start_extension,
288  .thread_restart = _RTEMS_tasks_Start_extension
289  }
290 };
291 
292 static void _RTEMS_tasks_Manager_initialization( void )
293 {
295  _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions );
296 }
297 
298 RTEMS_SYSINIT_ITEM(
299  _RTEMS_tasks_Manager_initialization,
300  RTEMS_SYSINIT_CLASSIC_TASKS,
301  RTEMS_SYSINIT_ORDER_MIDDLE
302 );
This status code indicates you have attempted to create too many instances of a particular object cla...
Definition: status.h:112
uint32_t name_u32
Definition: object.h:68
static __inline__ void _Objects_Allocator_unlock(void)
Unlocks the object allocator mutex.
Definition: objectimpl.h:846
This header file defines support services of the API.
Thread_CPU_budget_algorithms budget_algorithm
The thread&#39;s budget algorithm.
Definition: threadimpl.h:161
uintptr_t _TLS_Get_allocation_size(void)
Return the TLS area allocation size.
Definition: tlsallocsize.c:38
static __inline__ Priority_Control _RTEMS_Priority_To_core(const Scheduler_Control *scheduler, rtems_task_priority priority, bool *valid)
Converts the RTEMS API priority to the corresponding SuperCore priority and validates it...
Definition: tasksimpl.h:96
#define ATTRIBUTES_REQUIRED
Definition: attrimpl.h:49
rtems_mode initial_modes
This member defines the initial modes of the task.
Definition: tasks.h:207
This status code indicates that an invalid thread priority was provided.
Definition: status.h:189
#define CONTEXT_FP_SIZE
Size of floating point context area.
Definition: context.h:52
RTEMS_INLINE_ROUTINE bool _Attributes_Is_floating_point(rtems_attribute attribute_set)
Checks if the floating point attribute is enabled in the attribute_set.
Definition: attrimpl.h:90
static __inline__ const Scheduler_Control * _Thread_Scheduler_get_home(const Thread_Control *the_thread)
Gets the home scheduler of the thread.
Definition: threadimpl.h:1419
static __inline__ bool _Modes_Is_asr_disabled(rtems_mode mode_set)
Checks if mode_set says that Asynchronous Signal Processing is disabled.
Definition: modesimpl.h:55
#define PRIORITY_MINIMUM
The highest (most important) thread priority value.
Definition: priority.h:75
static __inline__ uint32_t _Stack_Minimum(void)
Returns the minimum stack size.
Definition: stackimpl.h:67
Classic Modes Implementation.
static __inline__ void _RTEMS_tasks_Free(Thread_Control *the_task)
Frees a task control block.
Definition: tasksimpl.h:72
void _Stack_Free_nothing(void *stack_area)
This function does nothing.
Inlined Routines Associated with the Manipulation of the Scheduler.
This status code indicates that the request was not satisfied.
Definition: status.h:154
static bool rtems_is_name_valid(rtems_status_code name)
Returns true, if the specified object name is valid, otherwise returns false.
Definition: support.h:126
rtems_name name
This member defines the name of the task.
Definition: tasks.h:138
RTEMS_INLINE_ROUTINE bool _Attributes_Is_system_task(rtems_attribute attribute_set)
Checks if the system task attribute is enabled in the attribute_set.
Definition: attrimpl.h:249
Event_Control System_event
Definition: tasksdata.h:45
User Extension Handler API.
Objects_Information Objects
The object information.
Definition: thread.h:1004
This structure defines the configuration of a task constructed by rtems_task_construct().
Definition: tasks.h:134
RTEMS_INLINE_ROUTINE rtems_attribute _Attributes_Set(rtems_attribute new_attributes, rtems_attribute attribute_set)
Sets the requested new_attributes in the attribute_set passed in.
Definition: attrimpl.h:60
bool _Thread_Initialize(Thread_Information *information, Thread_Control *the_thread, const Thread_Configuration *config)
Initializes thread.
Thread_Information _RTEMS_tasks_Information
static __inline__ struct _Thread_Control * _Thread_Get_executing(void)
Returns the thread control block of the executing thread.
Definition: percpu.h:878
Event_Control Event
Definition: tasksdata.h:43
Classic Event Manager Implementation.
Inlined Routines from the Stack Handler.
Objects_Name name
Name of the object for the thread.
Definition: threadimpl.h:171
void(* storage_free)(void *)
This member defines the optional handler to free the task storage area.
Definition: tasks.h:202
bool is_enabled
Definition: asrdata.h:38
This status code indicates successful completion.
Definition: status.h:86
ASR_Information Signal
Definition: tasksdata.h:47
Priority_Control priority
The new thread&#39;s priority.
Definition: threadimpl.h:156
static __inline__ bool _Modes_Is_timeslice(rtems_mode mode_set)
Checks if mode_set indicates that timeslicing is enabled.
Definition: modesimpl.h:81
rtems_status_code
This enumeration provides status codes for directives of the Classic API.
Definition: status.h:82
const struct _Scheduler_Control * scheduler
The scheduler control instance for the thread.
Definition: threadimpl.h:134
The configuration of a new thread to initialize.
Definition: threadimpl.h:130
Objects_Control Object
Definition: thread.h:727
API Mutex Handler API.
size_t stack_size
The size of the stack area in bytes.
Definition: threadimpl.h:144
static __inline__ ISR_Level _Modes_Get_interrupt_level(rtems_mode mode_set)
Gets the interrupt level portion of the mode_set.
Definition: modesimpl.h:93
#define ATTRIBUTES_NOT_SUPPORTED
Definition: attrimpl.h:42
rtems_task_priority initial_priority
This member defines the initial priority of the task.
Definition: tasks.h:143
This status code indicates that a specified address was invalid.
Definition: status.h:133
uint32_t rtems_attribute
This type is used to represent Classic API attributes.
Definition: attr.h:91
void * API_Extensions[THREAD_API_LAST+1]
Definition: thread.h:840
Classic Attributes Implementation.
Objects_Id rtems_id
Values of this type identify an RTEMS object.
Definition: types.h:99
bool is_fp
Indicates whether the thread needs a floating-point area.
Definition: threadimpl.h:181
void * stack_area
The starting address of the stack area.
Definition: threadimpl.h:139
RTEMS_INLINE_ROUTINE rtems_attribute _Attributes_Clear(rtems_attribute attribute_set, rtems_attribute mask)
Clears the requested new_attributes in the attribute_set passed in.
Definition: attrimpl.h:75
Inlined Routines from the Thread Handler.
bool is_preemptible
Indicates whether the new thread is preemptible.
Definition: threadimpl.h:186
Manages each user extension set.
Definition: userextdata.h:50
rtems_status_code rtems_task_construct(const rtems_task_config *config, rtems_id *id)
Constructs a task from the specified the task configuration.
Definition: taskconstruct.c:73
static __inline__ bool _Modes_Is_preempt(rtems_mode mode_set)
Checks if mode_set indicates that preemption is enabled.
Definition: modesimpl.h:68
static __inline__ void _User_extensions_Add_API_set(User_extensions_Control *extension)
Adds a user extension.
Definition: userextimpl.h:104
rtems_attribute attributes
This member defines the attributes of the task.
Definition: tasks.h:212
This status code indicates that an object name was invalid.
Definition: status.h:101
uint32_t isr_level
The thread&#39;s initial ISR level.
Definition: threadimpl.h:176
#define RTEMS_GLOBAL
This attribute constant indicates that the Classic API object shall be a global resource in a multipr...
Definition: attr.h:173
size_t maximum_thread_local_storage_size
This member defines the maximum thread-local storage size supported by the task storage area...
Definition: tasks.h:190
size_t storage_size
This member defines size of the task storage area in bytes.
Definition: tasks.h:165
void(* stack_free)(void *)
This member contains the handler to free the stack.
Definition: threadimpl.h:151
void * storage_area
This member shall point to the task storage area begin.
Definition: tasks.h:157
This status code indicates that a specified size was invalid.
Definition: status.h:128
void _Thread_Initialize_information(Thread_Information *information)
Initializes the thread information.
Definition: thread.c:46
Classic Tasks Manager Implementation.
Objects_Id id
Definition: objectdata.h:43