source: rtems/cpukit/score/src/threadinitialize.c @ 95d0c98

4.115
Last change on this file since 95d0c98 was 95d0c98, checked in by Sebastian Huber <sebastian.huber@…>, on 02/24/14 at 09:13:32

score: Fix thread TLS area initialization

Do not use _TLS_Size here since this will lead GCC to assume that this
symbol is not 0 and the later > 0 test will be optimized away.

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Initialize Thread
5 *  @ingroup ScoreThread
6 */
7/*
8 *  COPYRIGHT (c) 1989-2011.
9 *  On-Line Applications Research Corporation (OAR).
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.rtems.com/license/LICENSE.
14 */
15
16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <rtems/score/threadimpl.h>
21#include <rtems/score/schedulerimpl.h>
22#include <rtems/score/stackimpl.h>
23#include <rtems/score/tls.h>
24#include <rtems/score/userextimpl.h>
25#include <rtems/score/watchdogimpl.h>
26#include <rtems/score/wkspace.h>
27#include <rtems/config.h>
28
29bool _Thread_Initialize(
30  Objects_Information                  *information,
31  Thread_Control                       *the_thread,
32  void                                 *stack_area,
33  size_t                                stack_size,
34  bool                                  is_fp,
35  Priority_Control                      priority,
36  bool                                  is_preemptible,
37  Thread_CPU_budget_algorithms          budget_algorithm,
38  Thread_CPU_budget_algorithm_callout   budget_callout,
39  uint32_t                              isr_level,
40  Objects_Name                          name
41)
42{
43  size_t     actual_stack_size = 0;
44  void      *stack = NULL;
45  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
46    void    *fp_area;
47  #endif
48  void      *sched = NULL;
49  void      *extensions_area;
50  bool       extension_status;
51  int        i;
52
53  /*
54   * Do not use _TLS_Size here since this will lead GCC to assume that this
55   * symbol is not 0 and the later > 0 test will be optimized away.
56   */
57  uintptr_t  tls_size = (uintptr_t) _TLS_BSS_end - (uintptr_t) _TLS_Data_begin;
58
59#if defined( RTEMS_SMP )
60  if ( rtems_configuration_is_smp_enabled() && !is_preemptible ) {
61    return false;
62  }
63#endif
64
65  /*
66   *  Initialize the Ada self pointer
67   */
68  #if __RTEMS_ADA__
69    the_thread->rtems_ada_self = NULL;
70  #endif
71
72  /*
73   *  Zero out all the allocated memory fields
74   */
75  for ( i=0 ; i <= THREAD_API_LAST ; i++ )
76    the_thread->API_Extensions[i] = NULL;
77
78  extensions_area = NULL;
79  the_thread->libc_reent = NULL;
80  the_thread->Start.tls_area = NULL;
81
82  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
83    fp_area = NULL;
84  #endif
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  /* Thread-local storage (TLS) area allocation */
117  if ( tls_size > 0 ) {
118    uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
119    uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );
120
121    the_thread->Start.tls_area =
122      _Workspace_Allocate_aligned( tls_alloc, tls_align );
123
124    if ( the_thread->Start.tls_area == NULL ) {
125      goto failed;
126    }
127  }
128
129  /*
130   *  Allocate the floating point area for this thread
131   */
132  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
133    if ( is_fp ) {
134      fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
135      if ( !fp_area )
136        goto failed;
137      fp_area = _Context_Fp_start( fp_area, 0 );
138    }
139    the_thread->fp_context       = fp_area;
140    the_thread->Start.fp_context = fp_area;
141  #endif
142
143  /*
144   *  Initialize the thread timer
145   */
146  _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL );
147
148  #ifdef __RTEMS_STRICT_ORDER_MUTEX__
149    /* Initialize the head of chain of held mutexes */
150    _Chain_Initialize_empty(&the_thread->lock_mutex);
151  #endif
152
153  /*
154   *  Allocate the extensions area for this thread
155   */
156  if ( _Thread_Maximum_extensions ) {
157    extensions_area = _Workspace_Allocate(
158      (_Thread_Maximum_extensions + 1) * sizeof( void * )
159    );
160    if ( !extensions_area )
161      goto failed;
162  }
163  the_thread->extensions = (void **) extensions_area;
164
165  /*
166   * Clear the extensions area so extension users can determine
167   * if they are linked to the thread. An extension user may
168   * create the extension long after tasks have been created
169   * so they cannot rely on the thread create user extension
170   * call.
171   */
172  if ( the_thread->extensions ) {
173    for ( i = 0; i <= _Thread_Maximum_extensions ; i++ )
174      the_thread->extensions[i] = NULL;
175  }
176
177  /*
178   *  General initialization
179   */
180
181  the_thread->Start.is_preemptible   = is_preemptible;
182  the_thread->Start.budget_algorithm = budget_algorithm;
183  the_thread->Start.budget_callout   = budget_callout;
184
185  switch ( budget_algorithm ) {
186    case THREAD_CPU_BUDGET_ALGORITHM_NONE:
187    case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
188      break;
189    #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE)
190      case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
191        the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
192        break;
193    #endif
194    #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT)
195      case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
196        break;
197    #endif
198  }
199
200  the_thread->Start.isr_level         = isr_level;
201
202#if defined(RTEMS_SMP)
203  the_thread->is_scheduled            = false;
204  the_thread->is_in_the_air           = false;
205  the_thread->is_executing            = false;
206
207  /* Initialize the cpu field for the non-SMP schedulers */
208  the_thread->cpu                     = _Per_CPU_Get_by_index( 0 );
209#endif
210
211  the_thread->current_state           = STATES_DORMANT;
212  the_thread->Wait.queue              = NULL;
213  the_thread->resource_count          = 0;
214  the_thread->real_priority           = priority;
215  the_thread->Start.initial_priority  = priority;
216  sched =_Scheduler_Allocate( the_thread );
217  if ( !sched )
218    goto failed;
219  _Thread_Set_priority( the_thread, priority );
220
221  /*
222   *  Initialize the CPU usage statistics
223   */
224  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
225    _Timestamp_Set_to_zero( &the_thread->cpu_time_used );
226  #else
227    the_thread->cpu_time_used = 0;
228  #endif
229
230  /*
231   *  Open the object
232   */
233  _Objects_Open( information, &the_thread->Object, name );
234
235  /*
236   *  We assume the Allocator Mutex is locked and dispatching is
237   *  enabled when we get here.  We want to be able to run the
238   *  user extensions with dispatching enabled.  The Allocator
239   *  Mutex provides sufficient protection to let the user extensions
240   *  run safely.
241   */
242  extension_status = _User_extensions_Thread_create( the_thread );
243  if ( extension_status )
244    return true;
245
246failed:
247  _Workspace_Free( the_thread->Start.tls_area );
248
249  _Workspace_Free( the_thread->libc_reent );
250
251  for ( i=0 ; i <= THREAD_API_LAST ; i++ )
252    _Workspace_Free( the_thread->API_Extensions[i] );
253
254  _Workspace_Free( extensions_area );
255
256  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
257    _Workspace_Free( fp_area );
258  #endif
259
260   _Workspace_Free( sched );
261
262   _Thread_Stack_Free( the_thread );
263  return false;
264}
Note: See TracBrowser for help on using the repository browser.