source: rtems/cpukit/posix/src/pthread.c @ 290d2b79

4.104.115
Last change on this file since 290d2b79 was 290d2b79, checked in by Joel Sherrill <joel.sherrill@…>, on 06/29/09 at 23:19:28

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

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