source: rtems/cpukit/posix/src/pthread.c @ 5d65d0dd

5
Last change on this file since 5d65d0dd was 5d65d0dd, checked in by Sebastian Huber <sebastian.huber@…>, on 06/15/16 at 06:50:29

posix: Use _POSIX_Threads_Sporadic_timer_insert()

  • Property mode set to 100644
File size: 9.1 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/wkspace.h>
35#include <rtems/posix/pthreadimpl.h>
36#include <rtems/posix/priorityimpl.h>
37#include <rtems/posix/psignalimpl.h>
38#include <rtems/posix/config.h>
39#include <rtems/posix/keyimpl.h>
40#include <rtems/score/cpusetimpl.h>
41#include <rtems/score/assert.h>
42
43Thread_Information _POSIX_Threads_Information;
44
45/*
46 *  The default pthreads attributes structure.
47 *
48 *  NOTE: Be careful .. if the default attribute set changes,
49 *        _POSIX_Threads_Initialize_user_threads will need to be examined.
50 */
51pthread_attr_t _POSIX_Threads_Default_attributes = {
52  .is_initialized  = true,                       /* is_initialized */
53  .stackaddr       = NULL,                       /* stackaddr */
54  .stacksize       = 0,                          /* stacksize -- will be adjusted to minimum */
55  .contentionscope = PTHREAD_SCOPE_PROCESS,      /* contentionscope */
56  .inheritsched    = PTHREAD_INHERIT_SCHED,      /* inheritsched */
57  .schedpolicy     = SCHED_FIFO,                 /* schedpolicy */
58  .schedparam      =
59  {                           /* schedparam */
60    2,                        /* sched_priority */
61    #if defined(_POSIX_SPORADIC_SERVER) || \
62        defined(_POSIX_THREAD_SPORADIC_SERVER)
63      0,                        /* sched_ss_low_priority */
64      { 0L, 0 },                /* sched_ss_repl_period */
65      { 0L, 0 },                /* sched_ss_init_budget */
66      0                         /* sched_ss_max_repl */
67    #endif
68  },
69
70  #if HAVE_DECL_PTHREAD_ATTR_SETGUARDSIZE
71    .guardsize = 0,                            /* guardsize */
72  #endif
73  #if defined(_POSIX_THREAD_CPUTIME)
74    .cputime_clock_allowed = 1,                        /* cputime_clock_allowed */
75  #endif
76  .detachstate             = PTHREAD_CREATE_JOINABLE,    /* detachstate */
77  #if defined(__RTEMS_HAVE_SYS_CPUSET_H__)
78    .affinitysetsize         = 0,
79    .affinityset             = NULL,
80    .affinitysetpreallocated = {{0x0}}
81  #endif
82};
83
84static bool _POSIX_Threads_Sporadic_budget_TSR_filter(
85  Thread_Control   *the_thread,
86  Priority_Control *new_priority,
87  void             *arg
88)
89{
90  the_thread->real_priority = *new_priority;
91
92  /*
93   * If holding a resource, then do not change it.
94   *
95   * If this would make them less important, then do not change it.
96   */
97  return !_Thread_Owns_resources( the_thread ) &&
98    _Thread_Priority_less_than( the_thread->current_priority, *new_priority );
99}
100
101/*
102 *  _POSIX_Threads_Sporadic_budget_TSR
103 */
104void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog )
105{
106  POSIX_API_Control  *api;
107  Thread_Control     *the_thread;
108  ISR_lock_Context    lock_context;
109  Priority_Control    new_priority;
110
111  api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic_timer );
112  the_thread = api->thread;
113
114  _Thread_State_acquire( the_thread, &lock_context );
115
116  the_thread->cpu_time_budget =
117    _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget );
118
119  _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
120  _POSIX_Threads_Sporadic_timer_insert( api );
121
122  new_priority = _POSIX_Priority_To_core( api->schedparam.sched_priority );
123
124  _Thread_State_release( the_thread, &lock_context );
125
126  _Thread_Change_priority(
127    the_thread,
128    new_priority,
129    NULL,
130    _POSIX_Threads_Sporadic_budget_TSR_filter,
131    true
132  );
133}
134
135static bool _POSIX_Threads_Sporadic_budget_callout_filter(
136  Thread_Control   *the_thread,
137  Priority_Control *new_priority,
138  void             *arg
139)
140{
141  the_thread->real_priority = *new_priority;
142
143  /*
144   * If holding a resource, then do not change it.
145   *
146   * Make sure we are actually lowering it. If they have lowered it
147   * to logically lower than sched_ss_low_priority, then we do not want to
148   * change it.
149   */
150  return !_Thread_Owns_resources( the_thread ) &&
151    _Thread_Priority_less_than( *new_priority, the_thread->current_priority );
152}
153
154/*
155 *  _POSIX_Threads_Sporadic_budget_callout
156 */
157void _POSIX_Threads_Sporadic_budget_callout(
158  Thread_Control *the_thread
159)
160{
161  POSIX_API_Control *api;
162
163  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
164
165  /*
166   *  This will prevent the thread from consuming its entire "budget"
167   *  while at low priority.
168   */
169  the_thread->cpu_time_budget = UINT32_MAX;
170
171  _Thread_Change_priority(
172    the_thread,
173    _POSIX_Priority_To_core( api->schedparam.sched_ss_low_priority ),
174    NULL,
175    _POSIX_Threads_Sporadic_budget_callout_filter,
176    true
177  );
178}
179
180/*
181 *  _POSIX_Threads_Create_extension
182 *
183 *  This method is invoked for each thread created.
184 */
185
186static bool _POSIX_Threads_Create_extension(
187  Thread_Control *executing RTEMS_UNUSED,
188  Thread_Control *created
189)
190{
191  POSIX_API_Control *api;
192  POSIX_API_Control *executing_api;
193
194  api = created->API_Extensions[ THREAD_API_POSIX ];
195
196  /* XXX check all fields are touched */
197  api->thread = created;
198  _POSIX_Threads_Initialize_attributes( &api->Attributes );
199  api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy;
200  api->schedparam  = _POSIX_Threads_Default_attributes.schedparam;
201  api->schedparam.sched_priority =
202     _POSIX_Priority_From_core( created->current_priority );
203
204  /*
205   *  If the thread is not a posix thread, then all posix signals are blocked
206   *  by default.
207   *
208   *  The check for class == 1 is debug.  Should never really happen.
209   */
210  RTEMS_STATIC_ASSERT( SIGNAL_EMPTY_MASK == 0, signals_pending );
211  if ( _Objects_Get_API( created->Object.id ) == OBJECTS_POSIX_API
212       #if defined(RTEMS_DEBUG)
213         && _Objects_Get_class( created->Object.id ) == 1
214       #endif
215  ) {
216    executing_api = _Thread_Get_executing()->API_Extensions[ THREAD_API_POSIX ];
217    api->signals_unblocked = executing_api->signals_unblocked;
218  }
219
220  _Watchdog_Preinitialize( &api->Sporadic_timer, _Per_CPU_Get_by_index( 0 ) );
221  _Watchdog_Initialize(
222    &api->Sporadic_timer,
223    _POSIX_Threads_Sporadic_budget_TSR
224  );
225
226  return true;
227}
228
229static void _POSIX_Threads_Terminate_extension( Thread_Control *executing )
230{
231  POSIX_API_Control *api;
232  ISR_lock_Context   lock_context;
233
234  api = executing->API_Extensions[ THREAD_API_POSIX ];
235
236  _Thread_State_acquire( executing, &lock_context );
237
238  if ( api->schedpolicy == SCHED_SPORADIC ) {
239    _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
240  }
241
242  _Thread_State_release( executing, &lock_context );
243}
244
245/*
246 *  _POSIX_Threads_Exitted_extension
247 *
248 *  This method is invoked each time a thread exits.
249 */
250static void _POSIX_Threads_Exitted_extension(
251  Thread_Control *executing
252)
253{
254  /*
255   *  If the executing thread was not created with the POSIX API, then this
256   *  API do not get to define its exit behavior.
257   */
258  if ( _Objects_Get_API( executing->Object.id ) == OBJECTS_POSIX_API )
259    pthread_exit( executing->Wait.return_argument );
260}
261
262User_extensions_Control _POSIX_Threads_User_extensions = {
263  .Callouts = {
264    .thread_create    = _POSIX_Threads_Create_extension,
265    .thread_exitted   = _POSIX_Threads_Exitted_extension,
266    .thread_terminate = _POSIX_Threads_Terminate_extension
267  }
268};
269
270/*
271 *  _POSIX_Threads_Manager_initialization
272 *
273 *  This routine initializes all threads manager related data structures.
274 */
275static void _POSIX_Threads_Manager_initialization(void)
276{
277  #if defined(RTEMS_SMP) && defined(__RTEMS_HAVE_SYS_CPUSET_H__)
278    const CPU_set_Control *affinity;
279    pthread_attr_t *attr;
280
281    /* Initialize default attribute. */
282    attr = &_POSIX_Threads_Default_attributes;
283
284    /*  Initialize the affinity to be the default cpu set for the system */
285    affinity = _CPU_set_Default();
286    _Assert( affinity->setsize == sizeof( attr->affinitysetpreallocated ) );
287    attr->affinityset             = &attr->affinitysetpreallocated;
288    attr->affinitysetsize         = affinity->setsize;
289    CPU_COPY( attr->affinityset, affinity->set );
290  #endif
291
292  _Thread_Initialize_information(
293    &_POSIX_Threads_Information, /* object information table */
294    OBJECTS_POSIX_API,           /* object API */
295    OBJECTS_POSIX_THREADS,       /* object class */
296    Configuration_POSIX_API.maximum_threads,
297                                 /* maximum objects of this class */
298    true,                        /* true if names for this object are strings */
299    _POSIX_PATH_MAX              /* maximum length of each object's name */
300  );
301
302  /*
303   *  Add all the extensions for this API
304   */
305  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
306
307  /*
308   *  If we supported MP, then here we would ...
309   *       Register the MP Process Packet routine.
310   */
311}
312
313RTEMS_SYSINIT_ITEM(
314  _POSIX_Threads_Manager_initialization,
315  RTEMS_SYSINIT_POSIX_THREADS,
316  RTEMS_SYSINIT_ORDER_MIDDLE
317);
Note: See TracBrowser for help on using the repository browser.