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

5
Last change on this file since f05eeb2 was f05eeb2, checked in by Sebastian Huber <sebastian.huber@…>, on 04/19/16 at 11:39:00

score: Simplify _Objects_Initialize_information()

Remove unused supports_global parameter. Convert
_Objects_Initialize_information() to a macro to avoid use of
RTEMS_MULTIPROCESSING define for each caller.

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