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

5
Last change on this file since ef1a985f was ef1a985f, checked in by Sebastian Huber <sebastian.huber@…>, on 12/11/15 at 09:47:22

Optional POSIX Threads initialization

Update #2408.

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