source: rtems/cpukit/rtems/src/taskconstruct.c @ 3972085

Last change on this file since 3972085 was 3972085, checked in by Sebastian Huber <sebastian.huber@…>, on 10/13/20 at 11:47:06

Remove *_Is_null() inline functions

Simply compare the values against NULL.

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ClassicTasks
5 *
6 * @brief RTEMS Task Create from Config
7 */
8
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>
28#include <rtems/score/schedulerimpl.h>
29#include <rtems/score/stackimpl.h>
30#include <rtems/score/threadimpl.h>
31#include <rtems/score/userextimpl.h>
32#include <rtems/sysinit.h>
33
34#include <string.h>
35
36static 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
73rtems_status_code rtems_task_construct(
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
81rtems_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 =
144    _Thread_Scheduler_get_home( _Thread_Get_executing() );
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 ) {
175    _Objects_Allocator_unlock();
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 ( the_global_object == NULL ) {
184      _RTEMS_tasks_Free( the_thread );
185      _Objects_Allocator_unlock();
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(
201      &_RTEMS_tasks_Information,
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 );
217    _Objects_Allocator_unlock();
218    return status;
219  }
220
221  api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
222  asr = &api->Signal;
223
224  asr->is_enabled = !_Modes_Is_asr_disabled( config->initial_modes );
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(
233      &_RTEMS_tasks_Information.Objects,
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
248  _Objects_Allocator_unlock();
249  return RTEMS_SUCCESSFUL;
250}
251
252static 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)
266static void _RTEMS_tasks_Terminate_extension( Thread_Control *executing )
267{
268  if ( executing->is_global ) {
269    _Objects_MP_Close(
270      &_RTEMS_tasks_Information.Objects,
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
282static 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
292static void _RTEMS_tasks_Manager_initialization( void )
293{
294  _Thread_Initialize_information( &_RTEMS_tasks_Information );
295  _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions );
296}
297
298RTEMS_SYSINIT_ITEM(
299  _RTEMS_tasks_Manager_initialization,
300  RTEMS_SYSINIT_CLASSIC_TASKS,
301  RTEMS_SYSINIT_ORDER_MIDDLE
302);
Note: See TracBrowser for help on using the repository browser.