source: rtems/cpukit/score/src/threadinitialize.c @ 21275b58

Last change on this file since 21275b58 was 21275b58, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 22, 2018 at 6:14:51 PM

score: Static Objects_Information initialization

Statically allocate the objects information together with the initial
set of objects either via <rtems/confdefs.h>. Provide default object
informations with zero objects via librtemscpu.a. This greatly
simplifies the workspace size estimate. RTEMS applications which do not
use the unlimited objects option are easier to debug since all objects
reside now in statically allocated objects of the right types.

Close #3621.

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Initialize Thread
5 *
6 *  @ingroup ScoreThread
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/score/threadimpl.h>
22#include <rtems/score/schedulerimpl.h>
23#include <rtems/score/stackimpl.h>
24#include <rtems/score/tls.h>
25#include <rtems/score/userextimpl.h>
26#include <rtems/score/watchdogimpl.h>
27#include <rtems/score/wkspace.h>
28#include <rtems/config.h>
29
30bool _Thread_Initialize(
31  Thread_Information                   *information,
32  Thread_Control                       *the_thread,
33  const Scheduler_Control              *scheduler,
34  void                                 *stack_area,
35  size_t                                stack_size,
36  bool                                  is_fp,
37  Priority_Control                      priority,
38  bool                                  is_preemptible,
39  Thread_CPU_budget_algorithms          budget_algorithm,
40  Thread_CPU_budget_algorithm_callout   budget_callout,
41  uint32_t                              isr_level,
42  Objects_Name                          name
43)
44{
45  uintptr_t                tls_size = _TLS_Get_size();
46  size_t                   actual_stack_size = 0;
47  void                    *stack = NULL;
48  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
49    void                  *fp_area = NULL;
50  #endif
51  bool                     extension_status;
52  size_t                   i;
53  Scheduler_Node          *scheduler_node;
54#if defined(RTEMS_SMP)
55  Scheduler_Node          *scheduler_node_for_index;
56  const Scheduler_Control *scheduler_for_index;
57#endif
58  size_t                   scheduler_index;
59  Per_CPU_Control         *cpu = _Per_CPU_Get_by_index( 0 );
60
61#if defined( RTEMS_SMP )
62  if ( rtems_configuration_is_smp_enabled() ) {
63    if ( !is_preemptible ) {
64      return false;
65    }
66
67    if ( isr_level != 0 ) {
68      return false;
69    }
70  }
71#endif
72
73  memset(
74    &the_thread->Join_queue,
75    0,
76    information->Objects.object_size - offsetof( Thread_Control, Join_queue )
77  );
78
79  for ( i = 0 ; i < _Thread_Control_add_on_count ; ++i ) {
80    const Thread_Control_add_on *add_on = &_Thread_Control_add_ons[ i ];
81
82    *(void **) ( (char *) the_thread + add_on->destination_offset ) =
83      (char *) the_thread + add_on->source_offset;
84  }
85
86  /*
87   *  Allocate and Initialize the stack for this thread.
88   */
89  #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
90    actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
91    if ( !actual_stack_size || actual_stack_size < stack_size )
92      return false;                     /* stack allocation failed */
93
94    stack = the_thread->Start.stack;
95  #else
96    if ( !stack_area ) {
97      actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
98      if ( !actual_stack_size || actual_stack_size < stack_size )
99        return false;                     /* stack allocation failed */
100
101      stack = the_thread->Start.stack;
102      the_thread->Start.core_allocated_stack = true;
103    } else {
104      stack = stack_area;
105      actual_stack_size = stack_size;
106      the_thread->Start.core_allocated_stack = false;
107    }
108  #endif
109
110  _Stack_Initialize(
111     &the_thread->Start.Initial_stack,
112     stack,
113     actual_stack_size
114  );
115
116  scheduler_index = 0;
117
118  /* Thread-local storage (TLS) area allocation */
119  if ( tls_size > 0 ) {
120    uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
121    uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );
122
123    the_thread->Start.tls_area =
124      _Workspace_Allocate_aligned( tls_alloc, tls_align );
125
126    if ( the_thread->Start.tls_area == NULL ) {
127      goto failed;
128    }
129  }
130
131  /*
132   *  Allocate the floating point area for this thread
133   */
134  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
135    if ( is_fp ) {
136      fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
137      if ( !fp_area )
138        goto failed;
139    }
140    the_thread->fp_context       = fp_area;
141    the_thread->Start.fp_context = fp_area;
142  #endif
143
144  /*
145   *  Get thread queue heads
146   */
147  the_thread->Wait.spare_heads = _Freechain_Get(
148    &information->Thread_queue_heads.Free,
149    _Workspace_Allocate,
150    _Objects_Extend_size( &information->Objects ),
151    _Thread_queue_Heads_size
152  );
153  if ( the_thread->Wait.spare_heads == NULL ) {
154    goto failed;
155  }
156  _Thread_queue_Heads_initialize( the_thread->Wait.spare_heads );
157
158  /*
159   *  General initialization
160   */
161
162  the_thread->is_fp                  = is_fp;
163  the_thread->Start.isr_level        = isr_level;
164  the_thread->Start.is_preemptible   = is_preemptible;
165  the_thread->Start.budget_algorithm = budget_algorithm;
166  the_thread->Start.budget_callout   = budget_callout;
167
168  _Thread_Timer_initialize( &the_thread->Timer, cpu );
169
170  switch ( budget_algorithm ) {
171    case THREAD_CPU_BUDGET_ALGORITHM_NONE:
172    case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
173      break;
174    #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE)
175      case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
176        the_thread->cpu_time_budget =
177          rtems_configuration_get_ticks_per_timeslice();
178        break;
179    #endif
180    #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT)
181      case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
182        break;
183    #endif
184  }
185
186#if defined(RTEMS_SMP)
187  scheduler_node = NULL;
188  scheduler_node_for_index = the_thread->Scheduler.nodes;
189  scheduler_for_index = &_Scheduler_Table[ 0 ];
190
191  while ( scheduler_index < _Scheduler_Count ) {
192    Priority_Control priority_for_index;
193
194    if ( scheduler_for_index == scheduler ) {
195      priority_for_index = priority;
196      scheduler_node = scheduler_node_for_index;
197    } else {
198      /*
199       * Use the idle thread priority for the non-home scheduler instances by
200       * default.
201       */
202      priority_for_index = _Scheduler_Map_priority(
203        scheduler_for_index,
204        scheduler_for_index->maximum_priority
205      );
206    }
207
208    _Scheduler_Node_initialize(
209      scheduler_for_index,
210      scheduler_node_for_index,
211      the_thread,
212      priority_for_index
213    );
214    scheduler_node_for_index = (Scheduler_Node *)
215      ( (uintptr_t) scheduler_node_for_index + _Scheduler_Node_size );
216    ++scheduler_for_index;
217    ++scheduler_index;
218  }
219
220  _Assert( scheduler_node != NULL );
221  _Chain_Initialize_one(
222    &the_thread->Scheduler.Wait_nodes,
223    &scheduler_node->Thread.Wait_node
224  );
225  _Chain_Initialize_one(
226    &the_thread->Scheduler.Scheduler_nodes,
227    &scheduler_node->Thread.Scheduler_node.Chain
228  );
229#else
230  scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
231  _Scheduler_Node_initialize(
232    scheduler,
233    scheduler_node,
234    the_thread,
235    priority
236  );
237  scheduler_index = 1;
238#endif
239
240  _Priority_Node_initialize( &the_thread->Real_priority, priority );
241  _Priority_Initialize_one(
242    &scheduler_node->Wait.Priority,
243    &the_thread->Real_priority
244  );
245
246#if defined(RTEMS_SMP)
247  RTEMS_STATIC_ASSERT( THREAD_SCHEDULER_BLOCKED == 0, Scheduler_state );
248  the_thread->Scheduler.home_scheduler = scheduler;
249  _ISR_lock_Initialize( &the_thread->Scheduler.Lock, "Thread Scheduler" );
250  _Processor_mask_Assign(
251    &the_thread->Scheduler.Affinity,
252    _SMP_Get_online_processors()
253   );
254  _ISR_lock_Initialize( &the_thread->Wait.Lock.Default, "Thread Wait Default" );
255  _Thread_queue_Gate_open( &the_thread->Wait.Lock.Tranquilizer );
256  _RBTree_Initialize_node( &the_thread->Wait.Link.Registry_node );
257  _SMP_lock_Stats_initialize( &the_thread->Potpourri_stats, "Thread Potpourri" );
258  _SMP_lock_Stats_initialize( &the_thread->Join_queue.Lock_stats, "Thread State" );
259#endif
260
261  /* Initialize the CPU for the non-SMP schedulers */
262  _Thread_Set_CPU( the_thread, cpu );
263
264  the_thread->current_state           = STATES_DORMANT;
265  the_thread->Wait.operations         = &_Thread_queue_Operations_default;
266  the_thread->Start.initial_priority  = priority;
267
268  RTEMS_STATIC_ASSERT( THREAD_WAIT_FLAGS_INITIAL == 0, Wait_flags );
269
270  /* POSIX Keys */
271  _RBTree_Initialize_empty( &the_thread->Keys.Key_value_pairs );
272  _ISR_lock_Initialize( &the_thread->Keys.Lock, "POSIX Key Value Pairs" );
273
274  _Thread_Action_control_initialize( &the_thread->Post_switch_actions );
275
276  /*
277   *  Open the object
278   */
279  _Objects_Open( &information->Objects, &the_thread->Object, name );
280
281  /*
282   *  We assume the Allocator Mutex is locked and dispatching is
283   *  enabled when we get here.  We want to be able to run the
284   *  user extensions with dispatching enabled.  The Allocator
285   *  Mutex provides sufficient protection to let the user extensions
286   *  run safely.
287   */
288  extension_status = _User_extensions_Thread_create( the_thread );
289  if ( extension_status )
290    return true;
291
292failed:
293
294#if defined(RTEMS_SMP)
295  while ( scheduler_index > 0 ) {
296    scheduler_node_for_index = (Scheduler_Node *)
297      ( (uintptr_t) scheduler_node_for_index - _Scheduler_Node_size );
298    --scheduler_for_index;
299    --scheduler_index;
300    _Scheduler_Node_destroy( scheduler_for_index, scheduler_node_for_index );
301  }
302#else
303  if ( scheduler_index > 0 ) {
304    _Scheduler_Node_destroy( scheduler, scheduler_node );
305  }
306#endif
307
308  _Workspace_Free( the_thread->Start.tls_area );
309
310  _Freechain_Put(
311    &information->Thread_queue_heads.Free,
312    the_thread->Wait.spare_heads
313  );
314
315  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
316    _Workspace_Free( fp_area );
317  #endif
318
319   _Thread_Stack_Free( the_thread );
320  return false;
321}
Note: See TracBrowser for help on using the repository browser.