source: rtems/cpukit/posix/src/pthread.c @ 426eb35

4.10
Last change on this file since 426eb35 was 426eb35, checked in by Joel Sherrill <joel.sherrill@…>, on 07/31/11 at 22:40:43

2011-07-31 Joel Sherrill <joel.sherrilL@…>

PR 1855/cpukit

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