source: rtems/cpukit/posix/src/pthread.c @ ecf0f4c

4.104.114.95
Last change on this file since ecf0f4c was ecf0f4c, checked in by Joel Sherrill <joel.sherrill@…>, on 06/13/08 at 15:06:32

2008-06-13 Joel Sherrill <joel.sherrill@…>

  • posix/include/rtems/posix/pthread.h, posix/src/pthread.c, posix/src/pthreadcreate.c, rtems/include/rtems.h, rtems/src/attr.c, sapi/include/confdefs.h, sapi/include/rtems/config.h, score/inline/rtems/score/stack.inl, score/src/isr.c, score/src/mpci.c, score/src/threadcreateidle.c, score/src/threadinitialize.c, score/src/threadstackallocate.c: Add ability for application to configure minimum stack size. Add RTEMS_CONFIGURED_MINIMUM_STACK_SIZE constant so user can clearly indicate they want the configured as opposed to the recommended minimum stack size.
  • Property mode set to 100644
File size: 9.6 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2008.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 *
9 *  $Id$
10 */
11
12#if HAVE_CONFIG_H
13#include "config.h"
14#endif
15
16#include <assert.h>
17#include <errno.h>
18#include <pthread.h>
19#include <limits.h>
20
21#include <rtems/system.h>
22#include <rtems/score/apiext.h>
23#include <rtems/score/stack.h>
24#include <rtems/score/thread.h>
25#include <rtems/score/userext.h>
26#include <rtems/score/wkspace.h>
27#include <rtems/posix/cancel.h>
28#include <rtems/posix/pthread.h>
29#include <rtems/posix/priority.h>
30#include <rtems/posix/psignal.h>
31#include <rtems/posix/config.h>
32#include <rtems/posix/key.h>
33#include <rtems/posix/time.h>
34
35/*PAGE
36 *
37 *  The default pthreads attributes structure.
38 *
39 *  NOTE: Be careful .. if the default attribute set changes,
40 *        _POSIX_Threads_Initialize_user_threads will need to be examined.
41 *
42 */
43
44const pthread_attr_t _POSIX_Threads_Default_attributes = {
45  TRUE,                       /* is_initialized */
46  NULL,                       /* stackaddr */
47  0,                          /* stacksize -- will be adjusted to minimum */
48  PTHREAD_SCOPE_PROCESS,      /* contentionscope */
49  PTHREAD_INHERIT_SCHED,      /* inheritsched */
50  SCHED_FIFO,                 /* schedpolicy */
51  {                           /* schedparam */
52    2,                        /* sched_priority */
53    0,                        /* ss_low_priority */
54    { 0L, 0 },                /* ss_replenish_period */
55    { 0L, 0 }                 /* ss_initial_budget */
56  },
57  PTHREAD_CREATE_JOINABLE,    /* detachstate */
58  1                           /* cputime_clock_allowed */
59};
60
61/*PAGE
62 *
63 *  _POSIX_Threads_Sporadic_budget_TSR
64 */
65
66void _POSIX_Threads_Sporadic_budget_TSR(
67  Objects_Id      id,
68  void           *argument
69)
70{
71  uint32_t            ticks;
72  uint32_t            new_priority;
73  Thread_Control     *the_thread;
74  POSIX_API_Control  *api;
75
76  the_thread = argument;
77
78  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
79
80  ticks = _Timespec_To_ticks( &api->schedparam.ss_initial_budget );
81
82  if ( !ticks )
83    ticks = 1;
84
85  the_thread->cpu_time_budget = ticks;
86
87  new_priority = _POSIX_Priority_To_core( api->ss_high_priority );
88  the_thread->real_priority = new_priority;
89
90  if ( the_thread->resource_count == 0 ||
91       the_thread->current_priority > new_priority )
92    _Thread_Change_priority( the_thread, new_priority, TRUE );
93
94  ticks = _Timespec_To_ticks( &api->schedparam.ss_replenish_period );
95
96  if ( !ticks )
97    ticks = 1;
98
99  _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
100}
101
102/*PAGE
103 *
104 *  _POSIX_Threads_Sporadic_budget_callout
105 */
106
107void _POSIX_Threads_Sporadic_budget_callout(
108  Thread_Control *the_thread
109)
110{
111  POSIX_API_Control *api;
112  uint32_t           new_priority;
113
114  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
115
116  /*
117   *  This will prevent the thread from consuming its entire "budget"
118   *  while at low priority.
119   */
120
121
122  the_thread->cpu_time_budget = 0xFFFFFFFF; /* XXX should be based on MAX_U32 */
123
124  new_priority = _POSIX_Priority_To_core( api->schedparam.ss_low_priority );
125  the_thread->real_priority = new_priority;
126
127 if ( the_thread->resource_count == 0 ||
128      the_thread->current_priority > new_priority )
129    _Thread_Change_priority( the_thread, new_priority, TRUE );
130}
131
132/*PAGE
133 *
134 *  _POSIX_Threads_Create_extension
135 *
136 *  XXX
137 */
138
139boolean _POSIX_Threads_Create_extension(
140  Thread_Control *executing,
141  Thread_Control *created
142)
143{
144  POSIX_API_Control *api;
145  POSIX_API_Control *executing_api;
146
147  api = _Workspace_Allocate( sizeof( POSIX_API_Control ) );
148
149  if ( !api )
150    return FALSE;
151
152  created->API_Extensions[ THREAD_API_POSIX ] = api;
153
154  /* XXX check all fields are touched */
155  api->Attributes  = _POSIX_Threads_Default_attributes;
156  api->detachstate = _POSIX_Threads_Default_attributes.detachstate;
157  api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy;
158  api->schedparam  = _POSIX_Threads_Default_attributes.schedparam;
159  api->schedparam.sched_priority =
160     _POSIX_Priority_From_core( created->current_priority );
161
162  /*
163   *  POSIX 1003.1 1996, 18.2.2.2
164   */
165  api->cancelation_requested = 0;
166  api->cancelability_state = PTHREAD_CANCEL_ENABLE;
167  api->cancelability_type = PTHREAD_CANCEL_DEFERRED;
168  _Chain_Initialize_empty (&api->Cancellation_Handlers);
169
170  /*
171   *  If the thread is not a posix thread, then all posix signals are blocked
172   *  by default.
173   */
174
175  /* XXX use signal constants */
176  api->signals_pending = 0;
177  if ( _Objects_Get_API( created->Object.id ) == OBJECTS_POSIX_API &&
178       _Objects_Get_class( created->Object.id ) == 1 ) {
179    executing_api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
180    api->signals_blocked = executing_api->signals_blocked;
181  } else {
182    api->signals_blocked = 0xffffffff;
183  }
184
185  _Thread_queue_Initialize(
186    &api->Join_List,
187    THREAD_QUEUE_DISCIPLINE_FIFO,
188    STATES_WAITING_FOR_JOIN_AT_EXIT,
189    0
190  );
191
192  _Watchdog_Initialize(
193    &api->Sporadic_timer,
194    _POSIX_Threads_Sporadic_budget_TSR,
195    created->Object.id,
196    created
197  );
198
199  return TRUE;
200}
201
202/*PAGE
203 *
204 *  _POSIX_Threads_Delete_extension
205 */
206
207User_extensions_routine _POSIX_Threads_Delete_extension(
208  Thread_Control *executing,
209  Thread_Control *deleted
210)
211{
212  Thread_Control     *the_thread;
213  POSIX_API_Control  *api;
214  void              **value_ptr;
215
216  api = deleted->API_Extensions[ THREAD_API_POSIX ];
217
218  /*
219   *  Run the POSIX cancellation handlers
220   */
221  _POSIX_Threads_cancel_run( deleted );
222
223  /*
224   *  Run all the key destructors
225   */
226  _POSIX_Keys_Run_destructors( deleted );
227
228  /*
229   *  Wakeup all the tasks which joined with this one
230   */
231  value_ptr = (void **) deleted->Wait.return_argument;
232
233  while ( (the_thread = _Thread_queue_Dequeue( &api->Join_List )) )
234      *(void **)the_thread->Wait.return_argument = value_ptr;
235
236  if ( api->schedpolicy == SCHED_SPORADIC )
237    (void) _Watchdog_Remove( &api->Sporadic_timer );
238
239  deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
240
241  (void) _Workspace_Free( api );
242}
243
244/*
245 *
246 *  _POSIX_Threads_Exitted_extension
247 */
248
249User_extensions_routine _POSIX_Threads_Exitted_extension(
250  Thread_Control *executing
251)
252{
253  /*
254   *  If the executing thread was not created with the POSIX API, then this
255   *  API do not get to define its exit behavior.
256   */
257  if ( _Objects_Get_API( executing->Object.id ) == OBJECTS_POSIX_API )
258    pthread_exit( executing->Wait.return_argument );
259}
260
261/*PAGE
262 *
263 *  _POSIX_Threads_Initialize_user_threads
264 *
265 *  This routine creates and starts all configured user
266 *  initialzation threads.
267 *
268 *  Input parameters: NONE
269 *
270 *  Output parameters:  NONE
271 */
272
273void _POSIX_Threads_Initialize_user_threads( void )
274{
275  extern void (*_POSIX_Threads_Initialize_user_threads_p)(void);
276  if ( _POSIX_Threads_Initialize_user_threads_p )
277    (*_POSIX_Threads_Initialize_user_threads_p)();
278}
279
280/*PAGE
281 *
282 *  API Extension control structures
283 */
284
285API_extensions_Control _POSIX_Threads_API_extensions = {
286  { NULL, NULL },
287  NULL,                                     /* predriver */
288  _POSIX_Threads_Initialize_user_threads,   /* postdriver */
289  _POSIX_signals_Post_switch_extension,     /* post switch */
290};
291
292User_extensions_Control _POSIX_Threads_User_extensions = {
293  { NULL, NULL },
294  { { NULL, NULL }, NULL },
295  { _POSIX_Threads_Create_extension,          /* create */
296    NULL,                                     /* start */
297    NULL,                                     /* restart */
298    _POSIX_Threads_Delete_extension,          /* delete */
299    NULL,                                     /* switch */
300    NULL,                                     /* begin */
301    _POSIX_Threads_Exitted_extension,         /* exitted */
302    NULL                                      /* fatal */
303  }
304};
305
306/*PAGE
307 *
308 *  _POSIX_Threads_Manager_initialization
309 *
310 *  This routine initializes all threads manager related data structures.
311 *
312 *  Input parameters:
313 *    maximum_pthreads - maximum configured pthreads
314 *
315 *  Output parameters:  NONE
316 */
317
318void _POSIX_Threads_Manager_initialization(
319  uint32_t                            maximum_pthreads,
320  uint32_t                            number_of_initialization_threads,
321  posix_initialization_threads_table *user_threads
322
323)
324{
325  _POSIX_Threads_Number_of_initialization_threads =
326                                           number_of_initialization_threads;
327  _POSIX_Threads_User_initialization_threads = user_threads;
328
329  /*
330   *  There may not be any POSIX initialization threads configured.
331   */
332
333#if 0
334  if ( user_threads == NULL || number_of_initialization_threads == 0 )
335    _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
336#endif
337
338  _Objects_Initialize_information(
339    &_POSIX_Threads_Information, /* object information table */
340    OBJECTS_POSIX_API,           /* object API */
341    OBJECTS_POSIX_THREADS,       /* object class */
342    maximum_pthreads,            /* maximum objects of this class */
343    sizeof( Thread_Control ),
344                                 /* size of this object's control block */
345    TRUE,                        /* TRUE if names for this object are strings */
346    _POSIX_PATH_MAX             /* maximum length of each object's name */
347#if defined(RTEMS_MULTIPROCESSING)
348    ,
349    FALSE,                       /* TRUE if this is a global object class */
350    NULL                         /* Proxy extraction support callout */
351#endif
352  );
353
354  /*
355   *  Add all the extensions for this API
356   */
357
358  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
359
360  _API_extensions_Add( &_POSIX_Threads_API_extensions );
361
362
363  /*
364   *  If we supported MP, then here we would ...
365   *       Register the MP Process Packet routine.
366   */
367
368}
Note: See TracBrowser for help on using the repository browser.