source: rtems/cpukit/posix/src/pthread.c @ 188c82b

4.104.114.84.95
Last change on this file since 188c82b was df49c60, checked in by Joel Sherrill <joel.sherrill@…>, on 06/12/00 at 15:00:15

Merged from 4.5.0-beta3a

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