source: rtems/cpukit/posix/src/pthread.c @ 29aed671

4.11
Last change on this file since 29aed671 was 29aed671, checked in by Ralf Corsepius <ralf.corsepius@…>, on Dec 3, 2011 at 3:54:30 AM

2011-12-03 Ralf Corsépius <ralf.corsepius@…>

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