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

4.104.114.84.95
Last change on this file since f22ebf0 was aa08739a, checked in by Joel Sherrill <joel.sherrill@…>, on 04/08/02 at 17:02:03

2002-04-08 Chris Johns <ccj@…>

  • Per PR142, make task switch extension its own list.
  • src/pthread.c (_POSIX_Threads_User_extensions): Reflect above.
  • Property mode set to 100644
File size: 9.8 KB
Line 
1/*
2 *  $Id$
3 */
4
5#if HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9#include <assert.h>
10#include <errno.h>
11#include <pthread.h>
12#include <limits.h>
13
14#include <rtems/system.h>
15#include <rtems/score/apiext.h>
16#include <rtems/score/stack.h>
17#include <rtems/score/thread.h>
18#include <rtems/score/userext.h>
19#include <rtems/score/wkspace.h>
20#include <rtems/posix/cancel.h>
21#include <rtems/posix/pthread.h>
22#include <rtems/posix/priority.h>
23#include <rtems/posix/psignal.h>
24#include <rtems/posix/config.h>
25#include <rtems/posix/key.h>
26#include <rtems/posix/time.h>
27
28/*PAGE
29 *
30 *  The default pthreads attributes structure.
31 *
32 *  NOTE: Be careful .. if the default attribute set changes,
33 *        _POSIX_Threads_Initialize_user_threads will need to be examined.
34 *
35 */
36 
37const pthread_attr_t _POSIX_Threads_Default_attributes = {
38  TRUE,                       /* is_initialized */
39  NULL,                       /* stackaddr */
40  PTHREAD_MINIMUM_STACK_SIZE, /* stacksize */
41  PTHREAD_SCOPE_PROCESS,      /* contentionscope */
42  PTHREAD_INHERIT_SCHED,      /* inheritsched */
43  SCHED_FIFO,                 /* schedpolicy */
44  {                           /* schedparam */
45    2,                        /* sched_priority */
46    0,                        /* ss_low_priority */
47    { 0L, 0 },                /* ss_replenish_period */
48    { 0L, 0 }                 /* ss_initial_budget */
49  },
50  PTHREAD_CREATE_JOINABLE,    /* detachstate */
51  1                           /* cputime_clock_allowed */
52};
53
54/*PAGE
55 *
56 *  _POSIX_Threads_Sporadic_budget_TSR
57 */
58
59void _POSIX_Threads_Sporadic_budget_TSR(
60  Objects_Id      id,
61  void           *argument
62)
63{
64  unsigned32          ticks;
65  unsigned32          new_priority;
66  Thread_Control     *the_thread;
67  POSIX_API_Control  *api;
68
69  the_thread = argument;
70
71  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
72
73  ticks = _POSIX_Timespec_to_interval( &api->schedparam.ss_initial_budget );
74
75  if ( !ticks )
76    ticks = 1;
77
78  the_thread->cpu_time_budget = ticks;
79 
80  new_priority = _POSIX_Priority_To_core( api->ss_high_priority );
81  the_thread->real_priority = new_priority;
82
83  if ( the_thread->resource_count == 0 ||
84       the_thread->current_priority > new_priority )
85    _Thread_Change_priority( the_thread, new_priority, TRUE );
86
87  ticks = _POSIX_Timespec_to_interval( &api->schedparam.ss_replenish_period );
88
89  if ( !ticks )
90    ticks = 1;
91
92  _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
93}
94
95/*PAGE
96 *
97 *  _POSIX_Threads_Sporadic_budget_callout
98 */
99
100void _POSIX_Threads_Sporadic_budget_callout(
101  Thread_Control *the_thread
102)
103{
104  POSIX_API_Control *api;
105  unsigned32         new_priority;
106
107  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
108
109  /*
110   *  This will prevent the thread from consuming its entire "budget"
111   *  while at low priority.
112   */
113
114
115  the_thread->cpu_time_budget = 0xFFFFFFFF; /* XXX should be based on MAX_U32 */
116
117  new_priority = _POSIX_Priority_To_core( api->schedparam.ss_low_priority );
118  the_thread->real_priority = new_priority;
119
120 if ( the_thread->resource_count == 0 ||
121      the_thread->current_priority > new_priority )
122    _Thread_Change_priority( the_thread, new_priority, TRUE );
123}
124
125/*PAGE
126 *
127 *  _POSIX_Threads_Create_extension
128 *
129 *  XXX
130 */
131 
132boolean _POSIX_Threads_Create_extension(
133  Thread_Control *executing,
134  Thread_Control *created
135)
136{
137  POSIX_API_Control *api;
138  POSIX_API_Control *executing_api;
139 
140  api = _Workspace_Allocate( sizeof( POSIX_API_Control ) );
141 
142  if ( !api )
143    return FALSE;
144 
145  created->API_Extensions[ THREAD_API_POSIX ] = api;
146 
147  /* XXX check all fields are touched */
148  api->Attributes  = _POSIX_Threads_Default_attributes;
149  api->detachstate = _POSIX_Threads_Default_attributes.detachstate;
150  api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy;
151  api->schedparam  = _POSIX_Threads_Default_attributes.schedparam;
152  api->schedparam.sched_priority =
153     _POSIX_Priority_From_core( created->current_priority );
154 
155  /* 
156   *  POSIX 1003.1 1996, 18.2.2.2
157   */
158  api->cancelation_requested = 0;
159  api->cancelability_state = PTHREAD_CANCEL_ENABLE;
160  api->cancelability_type = PTHREAD_CANCEL_DEFERRED;
161  _Chain_Initialize_empty (&api->Cancellation_Handlers);
162
163  /*
164   *  If the thread is not a posix thread, then all posix signals are blocked
165   *  by default.
166   */
167
168  /* XXX use signal constants */
169  api->signals_pending = 0;
170  if ( _Objects_Get_class( created->Object.id ) == OBJECTS_POSIX_THREADS ) {
171    executing_api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
172    api->signals_blocked = api->signals_blocked;
173  } else
174    api->signals_blocked = 0xffffffff;
175
176/* XXX set signal parameters -- block all signals for non-posix threads */
177
178  _Thread_queue_Initialize(
179    &api->Join_List,
180    OBJECTS_NO_CLASS,                 /* only used for proxy operations */
181    THREAD_QUEUE_DISCIPLINE_FIFO,
182    STATES_WAITING_FOR_JOIN_AT_EXIT,
183    NULL,                             /* no extract proxy handler */
184    0
185  );
186 
187  _Watchdog_Initialize(
188    &api->Sporadic_timer,
189    _POSIX_Threads_Sporadic_budget_TSR,
190    created->Object.id,
191    created
192  );
193
194  return TRUE;
195}
196
197/*PAGE
198 *
199 *  _POSIX_Threads_Delete_extension
200 */
201 
202User_extensions_routine _POSIX_Threads_Delete_extension(
203  Thread_Control *executing,
204  Thread_Control *deleted
205)
206{
207  Thread_Control     *the_thread;
208  POSIX_API_Control  *api;
209  void              **value_ptr;
210
211  api = deleted->API_Extensions[ THREAD_API_POSIX ];
212 
213  /* XXX run cancellation handlers */
214
215  _POSIX_Keys_Run_destructors( deleted );
216
217  /*
218   *  Wakeup all the tasks which joined with this one
219   */
220 
221  value_ptr = (void **) deleted->Wait.return_argument;
222
223  while ( (the_thread = _Thread_queue_Dequeue( &api->Join_List )) )
224      *(void **)the_thread->Wait.return_argument = value_ptr;
225 
226  if ( api->schedpolicy == SCHED_SPORADIC )
227    (void) _Watchdog_Remove( &api->Sporadic_timer );
228
229  deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
230
231  (void) _Workspace_Free( api );
232}
233
234/*
235 *
236 *  _POSIX_Threads_Exitted_extension
237 */
238 
239User_extensions_routine _POSIX_Threads_Exitted_extension(
240  Thread_Control *executing
241)
242{
243  pthread_exit( executing->Wait.return_argument );
244}
245
246/*PAGE
247 *
248 *  _POSIX_Threads_Initialize_user_threads
249 *
250 *  This routine creates and starts all configured user
251 *  initialzation threads.
252 *
253 *  Input parameters: NONE
254 *
255 *  Output parameters:  NONE
256 */
257 
258void _POSIX_Threads_Initialize_user_threads( void )
259{
260  int                                 status;
261  unsigned32                          index;
262  unsigned32                          maximum;
263  posix_initialization_threads_table *user_threads;
264  pthread_t                           thread_id;
265  pthread_attr_t                      attr;
266 
267  user_threads = _POSIX_Threads_User_initialization_threads;
268  maximum      = _POSIX_Threads_Number_of_initialization_threads;
269
270  if ( !user_threads || maximum == 0 )
271    return;
272 
273  /*
274   *  Be careful .. if the default attribute set changes, this may need to.
275   *
276   *  Setting the attributes explicitly is critical, since we don't want
277   *  to inherit the idle tasks attributes.
278   */
279
280  for ( index=0 ; index < maximum ; index++ ) {
281    status = pthread_attr_init( &attr );
282    assert( !status );
283     
284    status = pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
285    assert( !status );
286
287    status = pthread_attr_setstacksize( &attr, user_threads[ index ].stack_size);
288    assert( !status );
289
290    status = pthread_create(
291      &thread_id,
292      &attr,
293      user_threads[ index ].thread_entry,
294      NULL
295    );
296    assert( !status );
297  }
298}
299
300/*PAGE
301 *
302 *  API Extension control structures
303 */
304
305API_extensions_Control _POSIX_Threads_API_extensions = {
306  { NULL, NULL },
307  NULL,                                     /* predriver */
308  _POSIX_Threads_Initialize_user_threads,   /* postdriver */
309  _POSIX_signals_Post_switch_extension,     /* post switch */
310};
311 
312User_extensions_Control _POSIX_Threads_User_extensions = {
313  { NULL, NULL },
314  { { NULL, NULL }, NULL },
315  { _POSIX_Threads_Create_extension,          /* create */
316    NULL,                                     /* start */
317    NULL,                                     /* restart */
318    _POSIX_Threads_Delete_extension,          /* delete */
319    NULL,                                     /* switch */
320    NULL,                                     /* begin */
321    _POSIX_Threads_Exitted_extension,         /* exitted */
322    NULL                                      /* fatal */
323  }
324};
325 
326/*PAGE
327 *
328 *  _POSIX_Threads_Manager_initialization
329 *
330 *  This routine initializes all threads manager related data structures.
331 *
332 *  Input parameters:
333 *    maximum_pthreads - maximum configured pthreads
334 *
335 *  Output parameters:  NONE
336 */
337 
338void _POSIX_Threads_Manager_initialization(
339  unsigned32                          maximum_pthreads,
340  unsigned32                          number_of_initialization_threads,
341  posix_initialization_threads_table *user_threads
342 
343)
344{
345  _POSIX_Threads_Number_of_initialization_threads =
346                                           number_of_initialization_threads;
347  _POSIX_Threads_User_initialization_threads = user_threads;
348
349  /*
350   *  There may not be any POSIX initialization threads configured.
351   */
352
353#if 0
354  if ( user_threads == NULL || number_of_initialization_threads == 0 )
355    _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
356#endif
357
358  _Objects_Initialize_information(
359    &_POSIX_Threads_Information,
360    OBJECTS_POSIX_THREADS,
361    FALSE,                               /* does not support global */
362    maximum_pthreads,
363    sizeof( Thread_Control ),
364    FALSE,
365    0,                                   /* length is arbitrary for now */
366    TRUE                                 /* this class is threads */
367  );
368
369  /*
370   *  Add all the extensions for this API
371   */
372 
373  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
374 
375  _API_extensions_Add( &_POSIX_Threads_API_extensions );
376 
377  /*
378   *  If we supported MP, then here we would ...
379   *       Register the MP Process Packet routine.
380   */
381 
382}
Note: See TracBrowser for help on using the repository browser.