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

4.104.114.84.95
Last change on this file since f845e96e was f845e96e, checked in by Joel Sherrill <joel.sherrill@…>, on 07/05/02 at 18:13:18

2002-07-05 Joel Sherrill <joel@…>

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