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
RevLine 
[5a58b1e]1/**
2 *  @file
[05df0a8]3 *
[5a58b1e]4 *  @brief Initialize Thread
5 *  @ingroup ScoreThread
6 */
7/*
[010192d]8 *  COPYRIGHT (c) 1989-2011.
[05df0a8]9 *  On-Line Applications Research Corporation (OAR).
10 *
11 *  The license and distribution terms for this file may be
[dcf3687]12 *  found in the file LICENSE in this distribution or at
[dd687d97]13 *  http://www.rtems.com/license/LICENSE.
[05df0a8]14 */
15
[a8eed23]16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
[5618c37a]20#include <rtems/score/threadimpl.h>
[c6e21ee1]21#include <rtems/score/schedulerimpl.h>
[218286bc]22#include <rtems/score/stackimpl.h>
[022851a]23#include <rtems/score/tls.h>
[3be0c9a]24#include <rtems/score/userextimpl.h>
[4b48ece0]25#include <rtems/score/watchdogimpl.h>
[05df0a8]26#include <rtems/score/wkspace.h>
[5618c37a]27#include <rtems/config.h>
[05df0a8]28
[484a769]29bool _Thread_Initialize(
[05df0a8]30  Objects_Information                  *information,
31  Thread_Control                       *the_thread,
32  void                                 *stack_area,
[728a0bd3]33  size_t                                stack_size,
[484a769]34  bool                                  is_fp,
[05df0a8]35  Priority_Control                      priority,
[484a769]36  bool                                  is_preemptible,
[05df0a8]37  Thread_CPU_budget_algorithms          budget_algorithm,
38  Thread_CPU_budget_algorithm_callout   budget_callout,
[3127180]39  uint32_t                              isr_level,
[05df0a8]40  Objects_Name                          name
41)
42{
[95d0c98]43  size_t     actual_stack_size = 0;
44  void      *stack = NULL;
[cedfd802]45  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
[95d0c98]46    void    *fp_area;
[cedfd802]47  #endif
[95d0c98]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;
[05df0a8]58
[05e82bd7]59#if defined( RTEMS_SMP )
60  if ( rtems_configuration_is_smp_enabled() && !is_preemptible ) {
61    return false;
62  }
63#endif
64
[05df0a8]65  /*
66   *  Initialize the Ada self pointer
67   */
[cedfd802]68  #if __RTEMS_ADA__
69    the_thread->rtems_ada_self = NULL;
70  #endif
[05df0a8]71
72  /*
[cedfd802]73   *  Zero out all the allocated memory fields
[05df0a8]74   */
[cedfd802]75  for ( i=0 ; i <= THREAD_API_LAST ; i++ )
76    the_thread->API_Extensions[i] = NULL;
[05df0a8]77
[cedfd802]78  extensions_area = NULL;
79  the_thread->libc_reent = NULL;
[022851a]80  the_thread->Start.tls_area = NULL;
[05df0a8]81
[cedfd802]82  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
83    fp_area = NULL;
84  #endif
[ecf0f4c]85
[cedfd802]86  /*
87   *  Allocate and Initialize the stack for this thread.
88   */
[bacf79e]89  #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
[464ec0d]90    actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
[8a4a349e]91    if ( !actual_stack_size || actual_stack_size < stack_size )
[aae7f1a1]92      return false;                     /* stack allocation failed */
[05df0a8]93
94    stack = the_thread->Start.stack;
[bacf79e]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
[05df0a8]109
110  _Stack_Initialize(
111     &the_thread->Start.Initial_stack,
112     stack,
113     actual_stack_size
114  );
115
[022851a]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
[05df0a8]129  /*
130   *  Allocate the floating point area for this thread
131   */
[cedfd802]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 );
[05df0a8]138    }
[cedfd802]139    the_thread->fp_context       = fp_area;
140    the_thread->Start.fp_context = fp_area;
141  #endif
[05df0a8]142
[bdffb59]143  /*
144   *  Initialize the thread timer
145   */
146  _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL );
147
[cedfd802]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
[05279b84]152
[05df0a8]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    );
[cedfd802]160    if ( !extensions_area )
161      goto failed;
162  }
[05df0a8]163  the_thread->extensions = (void **) extensions_area;
164
[f918e74]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 ) {
[cedfd802]173    for ( i = 0; i <= _Thread_Maximum_extensions ; i++ )
[f918e74]174      the_thread->extensions[i] = NULL;
175  }
176
[05df0a8]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;
[f94e76ba]184
185  switch ( budget_algorithm ) {
186    case THREAD_CPU_BUDGET_ALGORITHM_NONE:
187    case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
188      break;
[442eac69]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
[f94e76ba]198  }
199
[c3330a8]200  the_thread->Start.isr_level         = isr_level;
201
[a936aa49]202#if defined(RTEMS_SMP)
203  the_thread->is_scheduled            = false;
[aea4a91]204  the_thread->is_in_the_air           = false;
[a936aa49]205  the_thread->is_executing            = false;
[d5ef7ae2]206
207  /* Initialize the cpu field for the non-SMP schedulers */
208  the_thread->cpu                     = _Per_CPU_Get_by_index( 0 );
[a936aa49]209#endif
210
[c3330a8]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;
[108c4b0]216  sched =_Scheduler_Allocate( the_thread );
[0faa9dad]217  if ( !sched )
218    goto failed;
[c3330a8]219  _Thread_Set_priority( the_thread, priority );
[05df0a8]220
[c3330a8]221  /*
222   *  Initialize the CPU usage statistics
223   */
[c6f7e060]224  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
[c16bcc0]225    _Timestamp_Set_to_zero( &the_thread->cpu_time_used );
[c3330a8]226  #else
[c6f7e060]227    the_thread->cpu_time_used = 0;
[c3330a8]228  #endif
[05df0a8]229
230  /*
231   *  Open the object
232   */
233  _Objects_Open( information, &the_thread->Object, name );
234
235  /*
[5088d97]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
[28352fae]238   *  user extensions with dispatching enabled.  The Allocator
[5088d97]239   *  Mutex provides sufficient protection to let the user extensions
240   *  run safely.
[05df0a8]241   */
[5088d97]242  extension_status = _User_extensions_Thread_create( the_thread );
[cedfd802]243  if ( extension_status )
244    return true;
[05df0a8]245
[cedfd802]246failed:
[022851a]247  _Workspace_Free( the_thread->Start.tls_area );
248
[a0323a9f]249  _Workspace_Free( the_thread->libc_reent );
[05df0a8]250
[cedfd802]251  for ( i=0 ; i <= THREAD_API_LAST ; i++ )
[a0323a9f]252    _Workspace_Free( the_thread->API_Extensions[i] );
[28352fae]253
[a0323a9f]254  _Workspace_Free( extensions_area );
[05df0a8]255
[cedfd802]256  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
[a0323a9f]257    _Workspace_Free( fp_area );
[cedfd802]258  #endif
[05df0a8]259
[a0323a9f]260   _Workspace_Free( sched );
[0faa9dad]261
[cedfd802]262   _Thread_Stack_Free( the_thread );
263  return false;
[05df0a8]264}
Note: See TracBrowser for help on using the repository browser.