source: rtems/cpukit/score/src/threadinitialize.c @ 25f5730f

4.11
Last change on this file since 25f5730f was beab7329, checked in by Sebastian Huber <sebastian.huber@…>, on May 13, 2014 at 2:03:05 PM

score: Introduce scheduler nodes

Rename scheduler per-thread information into scheduler nodes using
Scheduler_Node as the base type. Use inheritance for specialized
schedulers.

Move the scheduler specific states from the thread control block into
the scheduler node structure.

Validate the SMP scheduler node state transitions in case RTEMS_DEBUG is
defined.

  • Property mode set to 100644
File size: 7.5 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/score/cpusetimpl.h>
29#include <rtems/config.h>
30
31bool _Thread_Initialize(
32  Objects_Information                  *information,
33  Thread_Control                       *the_thread,
34  const Scheduler_Control              *scheduler,
35  void                                 *stack_area,
36  size_t                                stack_size,
37  bool                                  is_fp,
38  Priority_Control                      priority,
39  bool                                  is_preemptible,
40  Thread_CPU_budget_algorithms          budget_algorithm,
41  Thread_CPU_budget_algorithm_callout   budget_callout,
42  uint32_t                              isr_level,
43  Objects_Name                          name
44)
45{
46  uintptr_t                tls_size = _TLS_Get_size();
47  size_t                   actual_stack_size = 0;
48  void                    *stack = NULL;
49  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
50    void                  *fp_area = NULL;
51  #endif
52  bool                     extension_status;
53  size_t                   i;
54  bool                     scheduler_allocated = false;
55  Per_CPU_Control         *cpu = _Per_CPU_Get_by_index( 0 );
56
57#if defined( RTEMS_SMP )
58  if ( rtems_configuration_is_smp_enabled() && !is_preemptible ) {
59    return false;
60  }
61#endif
62
63  for ( i = 0 ; i < _Thread_Control_add_on_count ; ++i ) {
64    const Thread_Control_add_on *add_on = &_Thread_Control_add_ons[ i ];
65
66    *(void **) ( (char *) the_thread + add_on->destination_offset ) =
67      (char *) the_thread + add_on->source_offset;
68  }
69
70  /*
71   *  Initialize the Ada self pointer
72   */
73  #if __RTEMS_ADA__
74    the_thread->rtems_ada_self = NULL;
75  #endif
76
77  the_thread->Start.tls_area = NULL;
78
79  /*
80   *  Allocate and Initialize the stack for this thread.
81   */
82  #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
83    actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
84    if ( !actual_stack_size || actual_stack_size < stack_size )
85      return false;                     /* stack allocation failed */
86
87    stack = the_thread->Start.stack;
88  #else
89    if ( !stack_area ) {
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      the_thread->Start.core_allocated_stack = true;
96    } else {
97      stack = stack_area;
98      actual_stack_size = stack_size;
99      the_thread->Start.core_allocated_stack = false;
100    }
101  #endif
102
103  _Stack_Initialize(
104     &the_thread->Start.Initial_stack,
105     stack,
106     actual_stack_size
107  );
108
109  /* Thread-local storage (TLS) area allocation */
110  if ( tls_size > 0 ) {
111    uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
112    uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );
113
114    the_thread->Start.tls_area =
115      _Workspace_Allocate_aligned( tls_alloc, tls_align );
116
117    if ( the_thread->Start.tls_area == NULL ) {
118      goto failed;
119    }
120  }
121
122  /*
123   *  Allocate the floating point area for this thread
124   */
125  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
126    if ( is_fp ) {
127      fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
128      if ( !fp_area )
129        goto failed;
130      fp_area = _Context_Fp_start( fp_area, 0 );
131    }
132    the_thread->fp_context       = fp_area;
133    the_thread->Start.fp_context = fp_area;
134  #endif
135
136  /*
137   *  Initialize the thread timer
138   */
139  _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL );
140
141  #ifdef __RTEMS_STRICT_ORDER_MUTEX__
142    /* Initialize the head of chain of held mutexes */
143    _Chain_Initialize_empty(&the_thread->lock_mutex);
144  #endif
145
146  /*
147   * Clear the extensions area so extension users can determine
148   * if they are linked to the thread. An extension user may
149   * create the extension long after tasks have been created
150   * so they cannot rely on the thread create user extension
151   * call.  The object index starts with one, so the first extension context is
152   * unused.
153   */
154  for ( i = 1 ; i <= rtems_configuration_get_maximum_extensions() ; ++i )
155    the_thread->extensions[ i ] = NULL;
156
157  /*
158   *  General initialization
159   */
160
161  the_thread->Start.is_preemptible   = is_preemptible;
162  the_thread->Start.budget_algorithm = budget_algorithm;
163  the_thread->Start.budget_callout   = budget_callout;
164
165  switch ( budget_algorithm ) {
166    case THREAD_CPU_BUDGET_ALGORITHM_NONE:
167    case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
168      break;
169    #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE)
170      case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
171        the_thread->cpu_time_budget =
172          rtems_configuration_get_ticks_per_timeslice();
173        break;
174    #endif
175    #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT)
176      case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
177        break;
178    #endif
179  }
180
181  the_thread->Start.isr_level         = isr_level;
182
183#if defined(RTEMS_SMP)
184  the_thread->scheduler               = scheduler;
185  _CPU_Context_Set_is_executing( &the_thread->Registers, false );
186#endif
187
188  _Thread_Debug_set_real_processor( the_thread, cpu );
189
190  /* Initialize the CPU for the non-SMP schedulers */
191  _Thread_Set_CPU( the_thread, cpu );
192
193  the_thread->current_state           = STATES_DORMANT;
194  the_thread->Wait.queue              = NULL;
195  the_thread->resource_count          = 0;
196  the_thread->real_priority           = priority;
197  the_thread->Start.initial_priority  = priority;
198
199  scheduler_allocated = _Scheduler_Allocate( scheduler, the_thread );
200  if ( !scheduler_allocated ) {
201    goto failed;
202  }
203
204  _Thread_Set_priority( the_thread, priority );
205
206  /*
207   *  Initialize the CPU usage statistics
208   */
209  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
210    _Timestamp_Set_to_zero( &the_thread->cpu_time_used );
211  #else
212    the_thread->cpu_time_used = 0;
213  #endif
214
215  /*
216   * initialize thread's key vaule node chain
217   */
218  _Chain_Initialize_empty( &the_thread->Key_Chain );
219
220  _Thread_Action_control_initialize( &the_thread->Post_switch_actions );
221
222  _Thread_Action_initialize(
223    &the_thread->Life.Action,
224    _Thread_Life_action_handler
225  );
226  the_thread->Life.state = THREAD_LIFE_NORMAL;
227  the_thread->Life.terminator = NULL;
228
229  /*
230   *  Open the object
231   */
232  _Objects_Open( information, &the_thread->Object, name );
233
234  /*
235   *  We assume the Allocator Mutex is locked and dispatching is
236   *  enabled when we get here.  We want to be able to run the
237   *  user extensions with dispatching enabled.  The Allocator
238   *  Mutex provides sufficient protection to let the user extensions
239   *  run safely.
240   */
241  extension_status = _User_extensions_Thread_create( the_thread );
242  if ( extension_status )
243    return true;
244
245failed:
246
247  if ( scheduler_allocated ) {
248    _Scheduler_Free( scheduler, the_thread );
249  }
250
251  _Workspace_Free( the_thread->Start.tls_area );
252
253  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
254    _Workspace_Free( fp_area );
255  #endif
256
257   _Thread_Stack_Free( the_thread );
258  return false;
259}
Note: See TracBrowser for help on using the repository browser.