source: rtems/cpukit/posix/src/pthread.c @ 412dbff6

4.104.114.84.95
Last change on this file since 412dbff6 was 412dbff6, checked in by Joel Sherrill <joel.sherrill@…>, on 04/05/07 at 21:17:27

2007-04-05 Joel Sherrill <joel@…>

  • posix/Makefile.am, posix/include/rtems/posix/time.h, posix/src/adjtime.c, posix/src/alarm.c, posix/src/clockgetres.c, posix/src/condtimedwait.c, posix/src/mqueuetimedreceive.c, posix/src/mqueuetimedsend.c, posix/src/mutextimedlock.c, posix/src/nanosleep.c, posix/src/posixtimespecabsolutetimeout.c, posix/src/pthread.c, posix/src/pthreadcreate.c, posix/src/pthreadsetschedparam.c, posix/src/ptimer1.c, posix/src/sched.c, posix/src/semtimedwait.c, posix/src/sigtimedwait.c, posix/src/ualarm.c, rtems/src/clocktodtoseconds.c, score/Makefile.am, score/preinstall.am, score/include/rtems/score/tod.h, score/inline/rtems/score/tod.inl, score/src/coretod.c, score/src/coretodget.c, score/src/coretodgetuptime.c, score/src/coretodset.c, score/src/coretodtickle.c: Provide timespec manipulation routines in the SuperCore?. Use them everywhere possible. This lead to significant cleanup in the API routines and eliminated some of the same code from the POSIX API. At this point, the SuperCore? keeps time in POSIX timespec format properly from 1970. You just cannot set it before 1988 in keeping with RTEMS traditional behavior.
  • score/include/rtems/score/timespec.h, score/src/timespecaddto.c, score/src/timespecfromticks.c, score/src/timespecisvalid.c, score/src/timespeclessthan.c, score/src/timespecsubtract.c, score/src/timespectoticks.c: New files.
  • posix/src/posixintervaltotimespec.c, posix/src/posixtimespecsubtract.c, posix/src/posixtimespectointerval.c: Removed.
  • Property mode set to 100644
File size: 10.4 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2007.
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  PTHREAD_MINIMUM_STACK_SIZE, /* stacksize */
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 = api->signals_blocked;
181  } else
182    api->signals_blocked = 0xffffffff;
183
184  _Thread_queue_Initialize(
185    &api->Join_List,
186    THREAD_QUEUE_DISCIPLINE_FIFO,
187    STATES_WAITING_FOR_JOIN_AT_EXIT,
188    0
189  );
190
191  _Watchdog_Initialize(
192    &api->Sporadic_timer,
193    _POSIX_Threads_Sporadic_budget_TSR,
194    created->Object.id,
195    created
196  );
197
198  return TRUE;
199}
200
201/*PAGE
202 *
203 *  _POSIX_Threads_Delete_extension
204 */
205
206User_extensions_routine _POSIX_Threads_Delete_extension(
207  Thread_Control *executing,
208  Thread_Control *deleted
209)
210{
211  Thread_Control     *the_thread;
212  POSIX_API_Control  *api;
213  void              **value_ptr;
214
215  api = deleted->API_Extensions[ THREAD_API_POSIX ];
216
217  /*
218   *  Run the POSIX cancellation handlers
219   */
220
221  _POSIX_Keys_Run_destructors( deleted );
222
223  /*
224   *  Wakeup all the tasks which joined with this one
225   */
226
227  value_ptr = (void **) deleted->Wait.return_argument;
228
229  while ( (the_thread = _Thread_queue_Dequeue( &api->Join_List )) )
230      *(void **)the_thread->Wait.return_argument = value_ptr;
231
232  if ( api->schedpolicy == SCHED_SPORADIC )
233    (void) _Watchdog_Remove( &api->Sporadic_timer );
234
235  deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
236
237  (void) _Workspace_Free( api );
238}
239
240/*
241 *
242 *  _POSIX_Threads_Exitted_extension
243 */
244
245User_extensions_routine _POSIX_Threads_Exitted_extension(
246  Thread_Control *executing
247)
248{
249  /*
250   *  If the executing thread was not created with the POSIX API, then this
251   *  API do not get to define its exit behavior.
252   */
253  if ( _Objects_Get_API( executing->Object.id ) == OBJECTS_POSIX_API )
254    pthread_exit( executing->Wait.return_argument );
255}
256
257/*PAGE
258 *
259 *  _POSIX_Threads_Initialize_user_threads
260 *
261 *  This routine creates and starts all configured user
262 *  initialzation threads.
263 *
264 *  Input parameters: NONE
265 *
266 *  Output parameters:  NONE
267 */
268
269void _POSIX_Threads_Initialize_user_threads( void )
270{
271  int                                 status;
272  uint32_t                            index;
273  uint32_t                            maximum;
274  posix_initialization_threads_table *user_threads;
275  pthread_t                           thread_id;
276  pthread_attr_t                      attr;
277
278  user_threads = _POSIX_Threads_User_initialization_threads;
279  maximum      = _POSIX_Threads_Number_of_initialization_threads;
280
281  if ( !user_threads || maximum == 0 )
282    return;
283
284  /*
285   *  Be careful .. if the default attribute set changes, this may need to.
286   *
287   *  Setting the attributes explicitly is critical, since we don't want
288   *  to inherit the idle tasks attributes.
289   */
290
291  for ( index=0 ; index < maximum ; index++ ) {
292    status = pthread_attr_init( &attr );
293    assert( !status );
294
295    status = pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
296    assert( !status );
297
298    status = pthread_attr_setstacksize( &attr, user_threads[ index ].stack_size);
299    assert( !status );
300
301    status = pthread_create(
302      &thread_id,
303      &attr,
304      user_threads[ index ].thread_entry,
305      NULL
306    );
307    assert( !status );
308  }
309}
310
311/*PAGE
312 *
313 *  API Extension control structures
314 */
315
316API_extensions_Control _POSIX_Threads_API_extensions = {
317  { NULL, NULL },
318  NULL,                                     /* predriver */
319  _POSIX_Threads_Initialize_user_threads,   /* postdriver */
320  _POSIX_signals_Post_switch_extension,     /* post switch */
321};
322
323User_extensions_Control _POSIX_Threads_User_extensions = {
324  { NULL, NULL },
325  { { NULL, NULL }, NULL },
326  { _POSIX_Threads_Create_extension,          /* create */
327    NULL,                                     /* start */
328    NULL,                                     /* restart */
329    _POSIX_Threads_Delete_extension,          /* delete */
330    NULL,                                     /* switch */
331    NULL,                                     /* begin */
332    _POSIX_Threads_Exitted_extension,         /* exitted */
333    NULL                                      /* fatal */
334  }
335};
336
337/*PAGE
338 *
339 *  _POSIX_Threads_Manager_initialization
340 *
341 *  This routine initializes all threads manager related data structures.
342 *
343 *  Input parameters:
344 *    maximum_pthreads - maximum configured pthreads
345 *
346 *  Output parameters:  NONE
347 */
348
349void _POSIX_Threads_Manager_initialization(
350  uint32_t                            maximum_pthreads,
351  uint32_t                            number_of_initialization_threads,
352  posix_initialization_threads_table *user_threads
353
354)
355{
356  _POSIX_Threads_Number_of_initialization_threads =
357                                           number_of_initialization_threads;
358  _POSIX_Threads_User_initialization_threads = user_threads;
359
360  /*
361   *  There may not be any POSIX initialization threads configured.
362   */
363
364#if 0
365  if ( user_threads == NULL || number_of_initialization_threads == 0 )
366    _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
367#endif
368
369  _Objects_Initialize_information(
370    &_POSIX_Threads_Information, /* object information table */
371    OBJECTS_POSIX_API,           /* object API */
372    OBJECTS_POSIX_THREADS,       /* object class */
373    maximum_pthreads,            /* maximum objects of this class */
374    sizeof( Thread_Control ),
375                                 /* size of this object's control block */
376    FALSE,                       /* TRUE if names for this object are strings */
377    0                            /* maximum length of each object's name */
378#if defined(RTEMS_MULTIPROCESSING)
379    ,
380    FALSE,                       /* TRUE if this is a global object class */
381    NULL                         /* Proxy extraction support callout */
382#endif
383  );
384
385  /*
386   *  Add all the extensions for this API
387   */
388
389  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
390
391  _API_extensions_Add( &_POSIX_Threads_API_extensions );
392
393
394  /*
395   *  If we supported MP, then here we would ...
396   *       Register the MP Process Packet routine.
397   */
398
399}
Note: See TracBrowser for help on using the repository browser.