source: rtems/cpukit/posix/src/pthread.c @ 6c7caa1a

4.115
Last change on this file since 6c7caa1a was 6c7caa1a, checked in by Sebastian Huber <sebastian.huber@…>, on 05/28/14 at 11:37:54

score: Add and use _Thread_Owns_resources()

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