source: rtems/cpukit/score/src/threadinitialize.c @ bbd6d27a

5
Last change on this file since bbd6d27a was 16832b0, checked in by Sebastian Huber <sebastian.huber@…>, on 03/29/16 at 10:06:55

score: Fix multiprocessing thread proxies

We must provide thread queue heads for the thread wait information for
each thread proxy (thread queue heads were introduced by
d7665823b208daefb6855591d808e1f3075cedcb). The thread proxy must be
allocated before the enqueue operation.

  • Property mode set to 100644
File size: 7.8 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/resourceimpl.h>
23#include <rtems/score/schedulerimpl.h>
24#include <rtems/score/stackimpl.h>
25#include <rtems/score/tls.h>
26#include <rtems/score/userextimpl.h>
27#include <rtems/score/watchdogimpl.h>
28#include <rtems/score/wkspace.h>
29#include <rtems/score/cpusetimpl.h>
30#include <rtems/config.h>
31
32bool _Thread_Initialize(
33  Thread_Information                   *information,
34  Thread_Control                       *the_thread,
35  const Scheduler_Control              *scheduler,
36  void                                 *stack_area,
37  size_t                                stack_size,
38  bool                                  is_fp,
39  Priority_Control                      priority,
40  bool                                  is_preemptible,
41  Thread_CPU_budget_algorithms          budget_algorithm,
42  Thread_CPU_budget_algorithm_callout   budget_callout,
43  uint32_t                              isr_level,
44  Objects_Name                          name
45)
46{
47  uintptr_t                tls_size = _TLS_Get_size();
48  size_t                   actual_stack_size = 0;
49  void                    *stack = NULL;
50  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
51    void                  *fp_area = NULL;
52  #endif
53  bool                     extension_status;
54  size_t                   i;
55  bool                     scheduler_node_initialized = false;
56  Per_CPU_Control         *cpu = _Per_CPU_Get_by_index( 0 );
57
58#if defined( RTEMS_SMP )
59  if ( rtems_configuration_is_smp_enabled() && !is_preemptible ) {
60    return false;
61  }
62#endif
63
64  memset(
65    &the_thread->current_state,
66    0,
67    information->Objects.size - offsetof( Thread_Control, current_state )
68  );
69
70  for ( i = 0 ; i < _Thread_Control_add_on_count ; ++i ) {
71    const Thread_Control_add_on *add_on = &_Thread_Control_add_ons[ i ];
72
73    *(void **) ( (char *) the_thread + add_on->destination_offset ) =
74      (char *) the_thread + add_on->source_offset;
75  }
76
77  /*
78   *  Allocate and Initialize the stack for this thread.
79   */
80  #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
81    actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
82    if ( !actual_stack_size || actual_stack_size < stack_size )
83      return false;                     /* stack allocation failed */
84
85    stack = the_thread->Start.stack;
86  #else
87    if ( !stack_area ) {
88      actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
89      if ( !actual_stack_size || actual_stack_size < stack_size )
90        return false;                     /* stack allocation failed */
91
92      stack = the_thread->Start.stack;
93      the_thread->Start.core_allocated_stack = true;
94    } else {
95      stack = stack_area;
96      actual_stack_size = stack_size;
97      the_thread->Start.core_allocated_stack = false;
98    }
99  #endif
100
101  _Stack_Initialize(
102     &the_thread->Start.Initial_stack,
103     stack,
104     actual_stack_size
105  );
106
107  /* Thread-local storage (TLS) area allocation */
108  if ( tls_size > 0 ) {
109    uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
110    uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );
111
112    the_thread->Start.tls_area =
113      _Workspace_Allocate_aligned( tls_alloc, tls_align );
114
115    if ( the_thread->Start.tls_area == NULL ) {
116      goto failed;
117    }
118  }
119
120  /*
121   *  Allocate the floating point area for this thread
122   */
123  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
124    if ( is_fp ) {
125      fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
126      if ( !fp_area )
127        goto failed;
128      fp_area = _Context_Fp_start( fp_area, 0 );
129    }
130    the_thread->fp_context       = fp_area;
131    the_thread->Start.fp_context = fp_area;
132  #endif
133
134  /*
135   *  Get thread queue heads
136   */
137  the_thread->Wait.spare_heads = _Freechain_Get(
138    &information->Free_thread_queue_heads,
139    _Workspace_Allocate,
140    _Objects_Extend_size( &information->Objects ),
141    THREAD_QUEUE_HEADS_SIZE( _Scheduler_Count )
142  );
143  if ( the_thread->Wait.spare_heads == NULL ) {
144    goto failed;
145  }
146  _Thread_queue_Heads_initialize( the_thread->Wait.spare_heads );
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   *  General initialization
155   */
156
157  the_thread->is_fp                  = is_fp;
158  the_thread->Start.isr_level        = isr_level;
159  the_thread->Start.is_preemptible   = is_preemptible;
160  the_thread->Start.budget_algorithm = budget_algorithm;
161  the_thread->Start.budget_callout   = budget_callout;
162
163  _Thread_Timer_initialize( &the_thread->Timer, cpu );
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#if defined(RTEMS_SMP)
182  RTEMS_STATIC_ASSERT( THREAD_SCHEDULER_BLOCKED == 0, Scheduler_state );
183  the_thread->Scheduler.own_control = scheduler;
184  the_thread->Scheduler.control = scheduler;
185  the_thread->Scheduler.own_node = the_thread->Scheduler.node;
186  _Resource_Node_initialize( &the_thread->Resource_node );
187  the_thread->Lock.current = &the_thread->Lock.Default;
188  _SMP_ticket_lock_Initialize( &the_thread->Lock.Default );
189  _SMP_lock_Stats_initialize( &the_thread->Lock.Stats, "Thread Lock" );
190  _SMP_lock_Stats_initialize( &the_thread->Potpourri_stats, "Thread Potpourri" );
191#endif
192
193  _Thread_Debug_set_real_processor( the_thread, cpu );
194
195  /* Initialize the CPU for the non-SMP schedulers */
196  _Thread_Set_CPU( the_thread, cpu );
197
198  the_thread->current_state           = STATES_DORMANT;
199  the_thread->Wait.operations         = &_Thread_queue_Operations_default;
200  the_thread->current_priority        = priority;
201  the_thread->real_priority           = priority;
202  the_thread->Start.initial_priority  = priority;
203
204  RTEMS_STATIC_ASSERT( THREAD_WAIT_FLAGS_INITIAL == 0, Wait_flags );
205
206  _Scheduler_Node_initialize( scheduler, the_thread );
207  scheduler_node_initialized = true;
208
209  _Scheduler_Update_priority( the_thread, priority );
210
211  /* POSIX Keys */
212  _RBTree_Initialize_empty( &the_thread->Keys.Key_value_pairs );
213  _ISR_lock_Initialize( &the_thread->Keys.Lock, "POSIX Key Value Pairs" );
214
215  _Thread_Action_control_initialize( &the_thread->Post_switch_actions );
216
217  RTEMS_STATIC_ASSERT( THREAD_LIFE_NORMAL == 0, Life_state );
218
219  /*
220   *  Open the object
221   */
222  _Objects_Open( &information->Objects, &the_thread->Object, name );
223
224  /*
225   *  We assume the Allocator Mutex is locked and dispatching is
226   *  enabled when we get here.  We want to be able to run the
227   *  user extensions with dispatching enabled.  The Allocator
228   *  Mutex provides sufficient protection to let the user extensions
229   *  run safely.
230   */
231  extension_status = _User_extensions_Thread_create( the_thread );
232  if ( extension_status )
233    return true;
234
235failed:
236
237  if ( scheduler_node_initialized ) {
238    _Scheduler_Node_destroy( scheduler, the_thread );
239  }
240
241  _Workspace_Free( the_thread->Start.tls_area );
242
243  _Freechain_Put(
244    &information->Free_thread_queue_heads,
245    the_thread->Wait.spare_heads
246  );
247
248  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
249    _Workspace_Free( fp_area );
250  #endif
251
252   _Thread_Stack_Free( the_thread );
253  return false;
254}
Note: See TracBrowser for help on using the repository browser.