source: rtems/cpukit/posix/src/pthread.c @ 03598b1

4.104.114.84.95
Last change on this file since 03598b1 was 03598b1, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 25, 1999 at 11:20:52 PM

Split most of POSIX Threads Manager into multiple files.

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