source: rtems/cpukit/posix/src/pthread.c @ 3be0c9a

4.115
Last change on this file since 3be0c9a was 3be0c9a, checked in by Sebastian Huber <sebastian.huber@…>, on 11/22/12 at 13:51:25

score: Add and use <rtems/score/userextimpl.h>

This file contains the parts of <rtems/score/userext.h> that are only
necessary for the RTEMS implementation.

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