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

4.104.115
Last change on this file since cedfd802 was cedfd802, checked in by Joel Sherrill <joel.sherrill@…>, on 07/30/09 at 00:14:26

2009-07-29 Joel Sherrill <joel.sherrill@…>

  • score/src/threadinitialize.c: Rework so there is only one error exit path. This required setting every variable that contains memory allocated from the workspace to NULL early and using that assumption in the one failed exit path.
  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*
2 *  Thread Handler
3 *
4 *
5 *  COPYRIGHT (c) 1989-2008.
6 *  On-Line Applications Research Corporation (OAR).
7 *
8 *  The license and distribution terms for this file may be
9 *  found in found in the file LICENSE in this distribution or at
10 *  http://www.rtems.com/license/LICENSE.
11 *
12 *  $Id$
13 */
14
15#if HAVE_CONFIG_H
16#include "config.h"
17#endif
18
19#include <rtems/system.h>
20#include <rtems/score/apiext.h>
21#include <rtems/score/context.h>
22#include <rtems/score/interr.h>
23#include <rtems/score/isr.h>
24#include <rtems/score/object.h>
25#include <rtems/score/priority.h>
26#include <rtems/score/states.h>
27#include <rtems/score/sysstate.h>
28#include <rtems/score/thread.h>
29#include <rtems/score/threadq.h>
30#include <rtems/score/userext.h>
31#include <rtems/score/watchdog.h>
32#include <rtems/score/wkspace.h>
33
34/*PAGE
35 *
36 *  _Thread_Initialize
37 *
38 *  This routine initializes the specified the thread.  It allocates
39 *  all memory associated with this thread.  It completes by adding
40 *  the thread to the local object table so operations on this
41 *  thread id are allowed.
42 */
43
44bool _Thread_Initialize(
45  Objects_Information                  *information,
46  Thread_Control                       *the_thread,
47  void                                 *stack_area,
48  size_t                                stack_size,
49  bool                                  is_fp,
50  Priority_Control                      priority,
51  bool                                  is_preemptible,
52  Thread_CPU_budget_algorithms          budget_algorithm,
53  Thread_CPU_budget_algorithm_callout   budget_callout,
54  uint32_t                              isr_level,
55  Objects_Name                          name
56)
57{
58  size_t               actual_stack_size = 0;
59  void                *stack = NULL;
60  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
61    void              *fp_area;
62  #endif
63  void                *extensions_area;
64  bool                 extension_status;
65  int                  i;
66
67  /*
68   *  Initialize the Ada self pointer
69   */
70  #if __RTEMS_ADA__
71    the_thread->rtems_ada_self = NULL;
72  #endif
73
74  /*
75   *  Zero out all the allocated memory fields
76   */
77  for ( i=0 ; i <= THREAD_API_LAST ; i++ )
78    the_thread->API_Extensions[i] = NULL;
79
80  extensions_area = NULL;
81  the_thread->libc_reent = NULL;
82
83  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
84    fp_area = NULL;
85  #endif
86
87  /*
88   *  Allocate and Initialize the stack for this thread.
89   */
90  if ( !stack_area ) {
91    actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
92    if ( !actual_stack_size || actual_stack_size < stack_size )
93      return false;                     /* stack allocation failed */
94
95    stack = the_thread->Start.stack;
96    the_thread->Start.core_allocated_stack = true;
97  } else {
98    stack = stack_area;
99    actual_stack_size = stack_size;
100    the_thread->Start.core_allocated_stack = false;
101  }
102
103  _Stack_Initialize(
104     &the_thread->Start.Initial_stack,
105     stack,
106     actual_stack_size
107  );
108
109  /*
110   *  Allocate the floating point area for this thread
111   */
112  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
113    if ( is_fp ) {
114      fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
115      if ( !fp_area )
116        goto failed;
117      fp_area = _Context_Fp_start( fp_area, 0 );
118    }
119    the_thread->fp_context       = fp_area;
120    the_thread->Start.fp_context = fp_area;
121  #endif
122
123  /*
124   *  Initialize the thread timer
125   */
126  _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL );
127
128  #ifdef __RTEMS_STRICT_ORDER_MUTEX__
129    /* Initialize the head of chain of held mutexes */
130    _Chain_Initialize_empty(&the_thread->lock_mutex);
131  #endif
132
133  /*
134   *  Allocate the extensions area for this thread
135   */
136  if ( _Thread_Maximum_extensions ) {
137    extensions_area = _Workspace_Allocate(
138      (_Thread_Maximum_extensions + 1) * sizeof( void * )
139    );
140    if ( !extensions_area )
141      goto failed;
142  }
143  the_thread->extensions = (void **) extensions_area;
144
145  /*
146   * Clear the extensions area so extension users can determine
147   * if they are linked to the thread. An extension user may
148   * create the extension long after tasks have been created
149   * so they cannot rely on the thread create user extension
150   * call.
151   */
152  if ( the_thread->extensions ) {
153    for ( i = 0; i <= _Thread_Maximum_extensions ; i++ )
154      the_thread->extensions[i] = NULL;
155  }
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    case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
170      the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
171      break;
172    case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
173      break;
174  }
175
176  the_thread->Start.isr_level         = isr_level;
177
178  the_thread->current_state           = STATES_DORMANT;
179  the_thread->Wait.queue              = NULL;
180  the_thread->resource_count          = 0;
181  #if defined(RTEMS_ITRON_API)
182    the_thread->suspend_count         = 0;
183  #endif
184  the_thread->real_priority           = priority;
185  the_thread->Start.initial_priority  = priority;
186  _Thread_Set_priority( the_thread, priority );
187
188  /*
189   *  Initialize the CPU usage statistics
190   */
191  #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
192    _Timestamp_Set_to_zero( &the_thread->cpu_time_used );
193  #else
194    the_thread->cpu_time_used         = 0;
195  #endif
196
197  /*
198   *  Open the object
199   */
200  _Objects_Open( information, &the_thread->Object, name );
201
202  /*
203   *  We assume the Allocator Mutex is locked and dispatching is
204   *  enabled when we get here.  We want to be able to run the
205   *  user extensions with dispatching enabled.  The Allocator
206   *  Mutex provides sufficient protection to let the user extensions
207   *  run safely.
208   */
209  extension_status = _User_extensions_Thread_create( the_thread );
210  if ( extension_status )
211    return true;
212
213failed:
214  if ( the_thread->libc_reent )
215    _Workspace_Free( the_thread->libc_reent );
216
217  for ( i=0 ; i <= THREAD_API_LAST ; i++ )
218    if ( the_thread->API_Extensions[i] )
219      _Workspace_Free( the_thread->API_Extensions[i] );
220 
221  if ( extensions_area )
222    (void) _Workspace_Free( extensions_area );
223
224  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
225    if ( fp_area )
226      (void) _Workspace_Free( fp_area );
227  #endif
228
229   _Thread_Stack_Free( the_thread );
230  return false;
231
232
233}
Note: See TracBrowser for help on using the repository browser.