source: rtems/c/src/exec/posix/src/pthread.c @ 2df1974

4.104.114.84.95
Last change on this file since 2df1974 was 2df1974, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 15, 1999 at 6:58:27 PM

Added include of rtems/posix/cancel.h.

  • Property mode set to 100644
File size: 9.3 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   *  If the thread is not a posix thread, then all posix signals are blocked
153   *  by default.
154   */
155
156  /* XXX use signal constants */
157  api->signals_pending = 0;
158  if ( _Objects_Get_class( created->Object.id ) == OBJECTS_POSIX_THREADS ) {
159    executing_api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
160    api->signals_blocked = api->signals_blocked;
161  } else
162    api->signals_blocked = 0xffffffff;
163
164/* XXX set signal parameters -- block all signals for non-posix threads */
165
166  _Thread_queue_Initialize(
167    &api->Join_List,
168    OBJECTS_NO_CLASS,                 /* only used for proxy operations */
169    THREAD_QUEUE_DISCIPLINE_FIFO,
170    STATES_WAITING_FOR_JOIN_AT_EXIT,
171    NULL,                             /* no extract proxy handler */
172    0
173  );
174 
175  _Watchdog_Initialize(
176    &api->Sporadic_timer,
177    _POSIX_Threads_Sporadic_budget_TSR,
178    created->Object.id,
179    created
180  );
181
182  return TRUE;
183}
184
185/*PAGE
186 *
187 *  _POSIX_Threads_Delete_extension
188 */
189 
190User_extensions_routine _POSIX_Threads_Delete_extension(
191  Thread_Control *executing,
192  Thread_Control *deleted
193)
194{
195  Thread_Control     *the_thread;
196  POSIX_API_Control  *api;
197  void              **value_ptr;
198
199  api = deleted->API_Extensions[ THREAD_API_POSIX ];
200 
201  /* XXX run cancellation handlers */
202
203  _POSIX_Keys_Run_destructors( deleted );
204
205  /*
206   *  Wakeup all the tasks which joined with this one
207   */
208 
209  value_ptr = (void **) deleted->Wait.return_argument;
210
211  while ( (the_thread = _Thread_queue_Dequeue( &api->Join_List )) )
212      *(void **)the_thread->Wait.return_argument = value_ptr;
213 
214  if ( api->schedpolicy == SCHED_SPORADIC )
215    (void) _Watchdog_Remove( &api->Sporadic_timer );
216
217  deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
218
219  (void) _Workspace_Free( api );
220}
221
222/*PAGE
223 *
224 *  _POSIX_Threads_Initialize_user_threads
225 *
226 *  This routine creates and starts all configured user
227 *  initialzation threads.
228 *
229 *  Input parameters: NONE
230 *
231 *  Output parameters:  NONE
232 */
233 
234void _POSIX_Threads_Initialize_user_threads( void )
235{
236  int                                 status;
237  unsigned32                          index;
238  unsigned32                          maximum;
239  posix_initialization_threads_table *user_threads;
240  pthread_t                           thread_id;
241  pthread_attr_t                      attr;
242 
243  user_threads = _POSIX_Threads_User_initialization_threads;
244  maximum      = _POSIX_Threads_Number_of_initialization_threads;
245
246  if ( !user_threads || maximum == 0 )
247    return;
248 
249  /*
250   *  Be careful .. if the default attribute set changes, this may need to.
251   *
252   *  Setting the attributes explicitly is critical, since we don't want
253   *  to inherit the idle tasks attributes.
254   */
255
256  for ( index=0 ; index < maximum ; index++ ) {
257    status = pthread_attr_init( &attr );
258    assert( !status );
259     
260    status = pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
261    assert( !status );
262
263    status = pthread_attr_setstacksize( &attr, PTHREAD_MINIMUM_STACK_SIZE * 2 );
264    assert( !status );
265
266    status = pthread_create(
267      &thread_id,
268      &attr,
269      user_threads[ index ].thread_entry,
270      NULL
271    );
272    assert( !status );
273  }
274}
275
276/*PAGE
277 *
278 *  API Extension control structures
279 */
280
281API_extensions_Control _POSIX_Threads_API_extensions = {
282  { NULL, NULL },
283  NULL,                                     /* predriver */
284  _POSIX_Threads_Initialize_user_threads,   /* postdriver */
285  _POSIX_signals_Post_switch_extension,     /* post switch */
286};
287 
288User_extensions_Control _POSIX_Threads_User_extensions = {
289  { NULL, NULL },
290  { _POSIX_Threads_Create_extension,          /* create */
291    NULL,                                     /* start */
292    NULL,                                     /* restart */
293    _POSIX_Threads_Delete_extension,          /* delete */
294    NULL,                                     /* switch */
295    NULL,                                     /* begin */
296    NULL,                                     /* exitted */
297    NULL                                      /* fatal */
298  }
299};
300 
301/*PAGE
302 *
303 *  _POSIX_Threads_Manager_initialization
304 *
305 *  This routine initializes all threads manager related data structures.
306 *
307 *  Input parameters:
308 *    maximum_pthreads - maximum configured pthreads
309 *
310 *  Output parameters:  NONE
311 */
312 
313void _POSIX_Threads_Manager_initialization(
314  unsigned32                          maximum_pthreads,
315  unsigned32                          number_of_initialization_threads,
316  posix_initialization_threads_table *user_threads
317 
318)
319{
320  _POSIX_Threads_Number_of_initialization_threads = 
321                                           number_of_initialization_threads;
322  _POSIX_Threads_User_initialization_threads = user_threads;
323
324  /*
325   *  There may not be any POSIX initialization threads configured.
326   */
327
328#if 0
329  if ( user_threads == NULL || number_of_initialization_threads == 0 )
330    _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
331#endif
332
333  _Objects_Initialize_information(
334    &_POSIX_Threads_Information,
335    OBJECTS_POSIX_THREADS,
336    FALSE,                               /* does not support global */
337    maximum_pthreads,
338    sizeof( Thread_Control ),
339    TRUE,
340    5,                                   /* length is arbitrary for now */
341    TRUE                                 /* this class is threads */
342  );
343
344  /*
345   *  Add all the extensions for this API
346   */
347 
348  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
349 
350  _API_extensions_Add( &_POSIX_Threads_API_extensions );
351 
352  /*
353   *  If we supported MP, then here we would ...
354   *       Register the MP Process Packet routine.
355   */
356 
357}
Note: See TracBrowser for help on using the repository browser.