source: rtems/cpukit/posix/src/pthread.c @ 2ad250e

4.115
Last change on this file since 2ad250e was 2ad250e, checked in by Sebastian Huber <sebastian.huber@…>, on 08/06/13 at 12:46:24

posix: Create key implementation header

Move implementation specific parts of key.h and key.inl into new header
file keyimpl.h. The key.h contains now only the application visible
API.

  • Property mode set to 100644
File size: 10.5 KB
RevLine 
[eb08acf]1/**
2 * @file
3 *
4 * @brief Private Support Information for POSIX Threads
5 * @ingroup POSIX_PTHREADS Private Threads
6 */
7
[8165b48f]8/*
[3bacb250]9 *  COPYRIGHT (c) 1989-2010.
[412dbff6]10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
[5e9b32b]15 */
16
[f42b726]17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
[5e9b32b]21#include <errno.h>
22#include <pthread.h>
23#include <limits.h>
24
[f4719d5a]25#include <rtems/system.h>
[309e2f6]26#include <rtems/config.h>
[5a18e04]27#include <rtems/score/apiext.h>
[5e9b32b]28#include <rtems/score/stack.h>
[5618c37a]29#include <rtems/score/threadimpl.h>
[a112364]30#include <rtems/score/threadqimpl.h>
[3be0c9a]31#include <rtems/score/userextimpl.h>
[4b48ece0]32#include <rtems/score/watchdogimpl.h>
[5a18e04]33#include <rtems/score/wkspace.h>
[2df1974]34#include <rtems/posix/cancel.h>
[0c5317d]35#include <rtems/posix/pthreadimpl.h>
[97552c98]36#include <rtems/posix/priorityimpl.h>
[f9340ed7]37#include <rtems/posix/psignalimpl.h>
[5a18e04]38#include <rtems/posix/config.h>
[2ad250e]39#include <rtems/posix/keyimpl.h>
[624133c]40#include <rtems/posix/time.h>
[c16bcc0]41#include <rtems/score/timespec.h>
[5e9b32b]42
[a1f0ca28]43/*
[5e9b32b]44 *  The default pthreads attributes structure.
[65c421f]45 *
[874297f3]46 *  NOTE: Be careful .. if the default attribute set changes,
[65c421f]47 *        _POSIX_Threads_Initialize_user_threads will need to be examined.
[5e9b32b]48 */
49const pthread_attr_t _POSIX_Threads_Default_attributes = {
[b1dbfd7]50  true,                       /* is_initialized */
[0b710dbb]51  NULL,                       /* stackaddr */
[ecf0f4c]52  0,                          /* stacksize -- will be adjusted to minimum */
[0b710dbb]53  PTHREAD_SCOPE_PROCESS,      /* contentionscope */
[65c421f]54  PTHREAD_INHERIT_SCHED,      /* inheritsched */
[0b710dbb]55  SCHED_FIFO,                 /* schedpolicy */
56  {                           /* schedparam */
57    2,                        /* sched_priority */
[85e0a22]58    #if defined(_POSIX_SPORADIC_SERVER) || \
59        defined(_POSIX_THREAD_SPORADIC_SERVER)
60      0,                        /* sched_ss_low_priority */
61      { 0L, 0 },                /* sched_ss_repl_period */
[29aed671]62      { 0L, 0 },                /* sched_ss_init_budget */
63      0                         /* sched_ss_max_repl */
[85e0a22]64    #endif
[5e9b32b]65  },
[21dd3ab8]66  #if HAVE_DECL_PTHREAD_ATTR_SETGUARDSIZE
67    0,                        /* guardsize */
68  #endif
[85e0a22]69  #if defined(_POSIX_THREAD_CPUTIME)
70    1,                        /* cputime_clock_allowed */
71  #endif
[0b710dbb]72  PTHREAD_CREATE_JOINABLE,    /* detachstate */
[5e9b32b]73};
74
[a1f0ca28]75/*
[65a5c1b]76 *  _POSIX_Threads_Sporadic_budget_TSR
77 */
78void _POSIX_Threads_Sporadic_budget_TSR(
[92f4671]79  Objects_Id      id __attribute__((unused)),
[65a5c1b]80  void           *argument
81)
82{
[39cefdd]83  uint32_t            ticks;
84  uint32_t            new_priority;
[65a5c1b]85  Thread_Control     *the_thread;
86  POSIX_API_Control  *api;
87
88  the_thread = argument;
89
90  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
91
[770db69]92  /* ticks is guaranteed to be at least one */
[3bacb250]93  ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget );
[65a5c1b]94
[2014063]95  the_thread->cpu_time_budget = ticks;
[874297f3]96
[3bacb250]97  new_priority = _POSIX_Priority_To_core( api->schedparam.sched_priority );
[2014063]98  the_thread->real_priority = new_priority;
99
[a1f0ca28]100  /*
101   *  If holding a resource, then do not change it.
102   */
103  #if 0
104    printk( "TSR %d %d %d\n", the_thread->resource_count,
105        the_thread->current_priority, new_priority );
106  #endif
107  if ( the_thread->resource_count == 0 ) {
108    /*
109     *  If this would make them less important, then do not change it.
110     */
111    if ( the_thread->current_priority > new_priority ) {
112      _Thread_Change_priority( the_thread, new_priority, true );
113      #if 0
114        printk( "raise priority\n" );
115      #endif
116    }
117  }
[2014063]118
[770db69]119  /* ticks is guaranteed to be at least one */
[3bacb250]120  ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period );
[2014063]121
122  _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
[65a5c1b]123}
124
[a1f0ca28]125/*
[65a5c1b]126 *  _POSIX_Threads_Sporadic_budget_callout
127 */
128void _POSIX_Threads_Sporadic_budget_callout(
129  Thread_Control *the_thread
130)
131{
[2014063]132  POSIX_API_Control *api;
[39cefdd]133  uint32_t           new_priority;
[65a5c1b]134
[2014063]135  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
[65a5c1b]136
[2014063]137  /*
138   *  This will prevent the thread from consuming its entire "budget"
139   *  while at low priority.
140   */
141  the_thread->cpu_time_budget = 0xFFFFFFFF; /* XXX should be based on MAX_U32 */
142
[3bacb250]143  new_priority = _POSIX_Priority_To_core(api->schedparam.sched_ss_low_priority);
[2014063]144  the_thread->real_priority = new_priority;
145
[a1f0ca28]146  /*
147   *  If holding a resource, then do not change it.
148   */
149  #if 0
150    printk( "callout %d %d %d\n", the_thread->resource_count,
151        the_thread->current_priority, new_priority );
152  #endif
153  if ( the_thread->resource_count == 0 ) {
154    /*
155     *  Make sure we are actually lowering it. If they have lowered it
[3bacb250]156     *  to logically lower than sched_ss_low_priority, then we do not want to
[a1f0ca28]157     *  change it.
158     */
159    if ( the_thread->current_priority < new_priority ) {
160      _Thread_Change_priority( the_thread, new_priority, true );
161      #if 0
162        printk( "lower priority\n" );
163      #endif
164    }
165  }
[65a5c1b]166}
167
[a1f0ca28]168/*
[5a18e04]169 *  _POSIX_Threads_Create_extension
170 *
[a1f0ca28]171 *  This method is invoked for each thread created.
[5a18e04]172 */
[874297f3]173
[29aed671]174static bool _POSIX_Threads_Create_extension(
[92f4671]175  Thread_Control *executing __attribute__((unused)),
[5a18e04]176  Thread_Control *created
177)
178{
179  POSIX_API_Control *api;
[65c421f]180  POSIX_API_Control *executing_api;
[874297f3]181
[5a18e04]182  api = _Workspace_Allocate( sizeof( POSIX_API_Control ) );
[874297f3]183
[5a18e04]184  if ( !api )
[f8437c8]185    return false;
[874297f3]186
[5a18e04]187  created->API_Extensions[ THREAD_API_POSIX ] = api;
[874297f3]188
[b85649c4]189  /* XXX check all fields are touched */
[895efd9]190  api->Attributes  = _POSIX_Threads_Default_attributes;
191  api->detachstate = _POSIX_Threads_Default_attributes.detachstate;
192  api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy;
193  api->schedparam  = _POSIX_Threads_Default_attributes.schedparam;
[874297f3]194  api->schedparam.sched_priority =
[895efd9]195     _POSIX_Priority_From_core( created->current_priority );
[874297f3]196
197  /*
[b6c868e]198   *  POSIX 1003.1 1996, 18.2.2.2
199   */
200  api->cancelation_requested = 0;
201  api->cancelability_state = PTHREAD_CANCEL_ENABLE;
202  api->cancelability_type = PTHREAD_CANCEL_DEFERRED;
203  _Chain_Initialize_empty (&api->Cancellation_Handlers);
204
[b85649c4]205  /*
206   *  If the thread is not a posix thread, then all posix signals are blocked
207   *  by default.
[2212a2ad]208   *
209   *  The check for class == 1 is debug.  Should never really happen.
[b85649c4]210   */
211
212  /* XXX use signal constants */
213  api->signals_pending = 0;
[2212a2ad]214  if ( _Objects_Get_API( created->Object.id ) == OBJECTS_POSIX_API
215       #if defined(RTEMS_DEBUG)
[a1f0ca28]216         && _Objects_Get_class( created->Object.id ) == 1
[2212a2ad]217       #endif
218  ) {
[65c421f]219    executing_api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
[7349e6d0]220    api->signals_blocked = executing_api->signals_blocked;
221  } else {
[b85649c4]222    api->signals_blocked = 0xffffffff;
[7349e6d0]223  }
[b85649c4]224
[895efd9]225  _Thread_queue_Initialize(
226    &api->Join_List,
227    THREAD_QUEUE_DISCIPLINE_FIFO,
[f05af6b7]228    STATES_WAITING_FOR_JOIN_AT_EXIT | STATES_INTERRUPTIBLE_BY_SIGNAL,
[895efd9]229    0
230  );
[874297f3]231
[895efd9]232  _Watchdog_Initialize(
233    &api->Sporadic_timer,
234    _POSIX_Threads_Sporadic_budget_TSR,
235    created->Object.id,
236    created
237  );
[5a18e04]238
[b5c9064]239  /** initialize thread's key vaule node chain */
240  _Chain_Initialize_empty( &api->Key_Chain );
241
[f8437c8]242  return true;
[5a18e04]243}
[895efd9]244
[a1f0ca28]245/*
[5a18e04]246 *  _POSIX_Threads_Delete_extension
[a1f0ca28]247 *
248 *  This method is invoked for each thread deleted.
[5a18e04]249 */
[29aed671]250static void _POSIX_Threads_Delete_extension(
[92f4671]251  Thread_Control *executing __attribute__((unused)),
[5a18e04]252  Thread_Control *deleted
253)
254{
[895efd9]255  Thread_Control     *the_thread;
256  POSIX_API_Control  *api;
257  void              **value_ptr;
258
[a61f1a46]259  api = deleted->API_Extensions[ THREAD_API_POSIX ];
[874297f3]260
[f845e96e]261  /*
262   *  Run the POSIX cancellation handlers
263   */
[345fc11]264  _POSIX_Threads_cancel_run( deleted );
[895efd9]265
[345fc11]266  /*
267   *  Run all the key destructors
268   */
[895efd9]269  _POSIX_Keys_Run_destructors( deleted );
270
271  /*
272   *  Wakeup all the tasks which joined with this one
273   */
274  value_ptr = (void **) deleted->Wait.return_argument;
275
276  while ( (the_thread = _Thread_queue_Dequeue( &api->Join_List )) )
277      *(void **)the_thread->Wait.return_argument = value_ptr;
[874297f3]278
[895efd9]279  if ( api->schedpolicy == SCHED_SPORADIC )
280    (void) _Watchdog_Remove( &api->Sporadic_timer );
[a61f1a46]281
282  deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
283
[a0323a9f]284  _Workspace_Free( api );
[5a18e04]285}
286
[260b0c2]287/*
288 *  _POSIX_Threads_Exitted_extension
[a1f0ca28]289 *
290 *  This method is invoked each time a thread exits.
[260b0c2]291 */
[29aed671]292static void _POSIX_Threads_Exitted_extension(
[260b0c2]293  Thread_Control *executing
294)
295{
[092fe28e]296  /*
297   *  If the executing thread was not created with the POSIX API, then this
298   *  API do not get to define its exit behavior.
299   */
300  if ( _Objects_Get_API( executing->Object.id ) == OBJECTS_POSIX_API )
301    pthread_exit( executing->Wait.return_argument );
[260b0c2]302}
303
[a1f0ca28]304/*
[dd32d883]305 *  _POSIX_Threads_Initialize_user_threads
[5a18e04]306 *
307 *  This routine creates and starts all configured user
[76f1677]308 *  initialization threads.
[5a18e04]309 */
[29aed671]310static void _POSIX_Threads_Initialize_user_threads( void )
[5a18e04]311{
[0ab34c90]312  if ( _POSIX_Threads_Initialize_user_threads_p )
313    (*_POSIX_Threads_Initialize_user_threads_p)();
[5a18e04]314}
315
[a1f0ca28]316/*
[22b4b2e]317 *  API Extension control structures
318 */
[5a18e04]319API_extensions_Control _POSIX_Threads_API_extensions = {
[27b961a]320  #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
[04b5d17]321    .predriver_hook = NULL,
[27b961a]322  #endif
[04b5d17]323  .postdriver_hook = _POSIX_Threads_Initialize_user_threads
324};
325
[5a18e04]326User_extensions_Control _POSIX_Threads_User_extensions = {
327  { NULL, NULL },
[aa08739a]328  { { NULL, NULL }, NULL },
[5a18e04]329  { _POSIX_Threads_Create_extension,          /* create */
330    NULL,                                     /* start */
331    NULL,                                     /* restart */
332    _POSIX_Threads_Delete_extension,          /* delete */
333    NULL,                                     /* switch */
334    NULL,                                     /* begin */
[260b0c2]335    _POSIX_Threads_Exitted_extension,         /* exitted */
[5a18e04]336    NULL                                      /* fatal */
337  }
338};
[874297f3]339
[a1f0ca28]340/*
[5e9b32b]341 *  _POSIX_Threads_Manager_initialization
342 *
343 *  This routine initializes all threads manager related data structures.
344 */
[309e2f6]345void _POSIX_Threads_Manager_initialization(void)
[5e9b32b]346{
347  _Objects_Initialize_information(
[3c465878]348    &_POSIX_Threads_Information, /* object information table */
349    OBJECTS_POSIX_API,           /* object API */
350    OBJECTS_POSIX_THREADS,       /* object class */
[309e2f6]351    Configuration_POSIX_API.maximum_threads,
352                                 /* maximum objects of this class */
[e811d68]353    sizeof( Thread_Control ),
[3c465878]354                                 /* size of this object's control block */
[b1dbfd7]355    true,                        /* true if names for this object are strings */
[309e2f6]356    _POSIX_PATH_MAX              /* maximum length of each object's name */
[3c465878]357#if defined(RTEMS_MULTIPROCESSING)
358    ,
[b1dbfd7]359    false,                       /* true if this is a global object class */
[3c465878]360    NULL                         /* Proxy extraction support callout */
361#endif
[5e9b32b]362  );
[5a18e04]363
[613cff6]364  /*
365   *  Add all the extensions for this API
366   */
367  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
[f845e96e]368
[613cff6]369  _API_extensions_Add( &_POSIX_Threads_API_extensions );
[f845e96e]370
[613cff6]371  /*
372   *  If we supported MP, then here we would ...
373   *       Register the MP Process Packet routine.
374   */
[5e9b32b]375}
Note: See TracBrowser for help on using the repository browser.