source: rtems/c/src/exec/posix/src/pthread.c @ 3c465878

4.104.114.84.95
Last change on this file since 3c465878 was 3c465878, checked in by Joel Sherrill <joel.sherrill@…>, on 07/01/02 at 22:33:47

2002-07-01 Joel Sherrill <joel@…>

  • Mega patch merge to change the format of the object IDs to loosen the dependency between the SCORE and the various APIs. There was considerable work to simplify the object name management and it appears that the name_table field is no longer needed. This patch also includes the addition of the internal mutex which is currently only used to protect some types of allocation and deallocation. This significantly can reduce context switch latency under certain circumstances. In particular, some heap/region operations were O(n) and had dispatching disabled. This should help enormously. With this merge, the patch is not as clean as it should be. In particular, the documentation has not been modified to reflect the new object ID layout, the IDs in the test screens are not updated, and _Objects_Get_information needs to be a real routine not inlined. As part of this patch a lot of MP code for thread/proxy blocking was made conditional and cleaned up.
  • include/rtems/posix/key.h, src/cond.c, src/condinit.c, src/intr.c, src/key.c, src/keycreate.c, src/keydelete.c, src/killinfo.c, src/mqueue.c, src/mqueuecreatesupp.c, src/mutex.c, src/mutexinit.c, src/psignal.c, src/pthread.c, src/semaphore.c, src/semaphorecreatesupp.c: Modified as part of above.
  • Property mode set to 100644
File size: 10.0 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_API( created->Object.id ) == OBJECTS_POSIX_API &&
171       _Objects_Get_class( created->Object.id ) == 1 ) {
172    executing_api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
173    api->signals_blocked = api->signals_blocked;
174  } else
175    api->signals_blocked = 0xffffffff;
176
177  _Thread_queue_Initialize(
178    &api->Join_List,
179    THREAD_QUEUE_DISCIPLINE_FIFO,
180    STATES_WAITING_FOR_JOIN_AT_EXIT,
181    0
182  );
183 
184  _Watchdog_Initialize(
185    &api->Sporadic_timer,
186    _POSIX_Threads_Sporadic_budget_TSR,
187    created->Object.id,
188    created
189  );
190
191  return TRUE;
192}
193
194/*PAGE
195 *
196 *  _POSIX_Threads_Delete_extension
197 */
198 
199User_extensions_routine _POSIX_Threads_Delete_extension(
200  Thread_Control *executing,
201  Thread_Control *deleted
202)
203{
204  Thread_Control     *the_thread;
205  POSIX_API_Control  *api;
206  void              **value_ptr;
207
208  api = deleted->API_Extensions[ THREAD_API_POSIX ];
209 
210  /* XXX run cancellation handlers */
211
212  _POSIX_Keys_Run_destructors( deleted );
213
214  /*
215   *  Wakeup all the tasks which joined with this one
216   */
217 
218  value_ptr = (void **) deleted->Wait.return_argument;
219
220  while ( (the_thread = _Thread_queue_Dequeue( &api->Join_List )) )
221      *(void **)the_thread->Wait.return_argument = value_ptr;
222 
223  if ( api->schedpolicy == SCHED_SPORADIC )
224    (void) _Watchdog_Remove( &api->Sporadic_timer );
225
226  deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
227
228  (void) _Workspace_Free( api );
229}
230
231/*
232 *
233 *  _POSIX_Threads_Exitted_extension
234 */
235 
236User_extensions_routine _POSIX_Threads_Exitted_extension(
237  Thread_Control *executing
238)
239{
240  pthread_exit( executing->Wait.return_argument );
241}
242
243/*PAGE
244 *
245 *  _POSIX_Threads_Initialize_user_threads
246 *
247 *  This routine creates and starts all configured user
248 *  initialzation threads.
249 *
250 *  Input parameters: NONE
251 *
252 *  Output parameters:  NONE
253 */
254 
255void _POSIX_Threads_Initialize_user_threads( void )
256{
257  int                                 status;
258  unsigned32                          index;
259  unsigned32                          maximum;
260  posix_initialization_threads_table *user_threads;
261  pthread_t                           thread_id;
262  pthread_attr_t                      attr;
263 
264  user_threads = _POSIX_Threads_User_initialization_threads;
265  maximum      = _POSIX_Threads_Number_of_initialization_threads;
266
267  if ( !user_threads || maximum == 0 )
268    return;
269 
270  /*
271   *  Be careful .. if the default attribute set changes, this may need to.
272   *
273   *  Setting the attributes explicitly is critical, since we don't want
274   *  to inherit the idle tasks attributes.
275   */
276
277  for ( index=0 ; index < maximum ; index++ ) {
278    status = pthread_attr_init( &attr );
279    assert( !status );
280     
281    status = pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
282    assert( !status );
283
284    status = pthread_attr_setstacksize( &attr, user_threads[ index ].stack_size);
285    assert( !status );
286
287    status = pthread_create(
288      &thread_id,
289      &attr,
290      user_threads[ index ].thread_entry,
291      NULL
292    );
293    assert( !status );
294  }
295}
296
297/*PAGE
298 *
299 *  API Extension control structures
300 */
301
302API_extensions_Control _POSIX_Threads_API_extensions = {
303  { NULL, NULL },
304  NULL,                                     /* predriver */
305  _POSIX_Threads_Initialize_user_threads,   /* postdriver */
306  _POSIX_signals_Post_switch_extension,     /* post switch */
307};
308 
309User_extensions_Control _POSIX_Threads_User_extensions = {
310  { NULL, NULL },
311  { { NULL, NULL }, NULL },
312  { _POSIX_Threads_Create_extension,          /* create */
313    NULL,                                     /* start */
314    NULL,                                     /* restart */
315    _POSIX_Threads_Delete_extension,          /* delete */
316    NULL,                                     /* switch */
317    NULL,                                     /* begin */
318    _POSIX_Threads_Exitted_extension,         /* exitted */
319    NULL                                      /* fatal */
320  }
321};
322 
323/*PAGE
324 *
325 *  _POSIX_Threads_Manager_initialization
326 *
327 *  This routine initializes all threads manager related data structures.
328 *
329 *  Input parameters:
330 *    maximum_pthreads - maximum configured pthreads
331 *
332 *  Output parameters:  NONE
333 */
334 
335void _POSIX_Threads_Manager_initialization(
336  unsigned32                          maximum_pthreads,
337  unsigned32                          number_of_initialization_threads,
338  posix_initialization_threads_table *user_threads
339 
340)
341{
342  _POSIX_Threads_Number_of_initialization_threads =
343                                           number_of_initialization_threads;
344  _POSIX_Threads_User_initialization_threads = user_threads;
345
346  /*
347   *  There may not be any POSIX initialization threads configured.
348   */
349
350#if 0
351  if ( user_threads == NULL || number_of_initialization_threads == 0 )
352    _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
353#endif
354
355  _Objects_Initialize_information(
356    &_POSIX_Threads_Information, /* object information table */
357    OBJECTS_POSIX_API,           /* object API */
358    OBJECTS_POSIX_THREADS,       /* object class */
359    maximum_pthreads,            /* maximum objects of this class */
360    sizeof( Thread_Control ),
361                                 /* size of this object's control block */
362    FALSE,                       /* TRUE if names for this object are strings */
363    0                            /* maximum length of each object's name */
364#if defined(RTEMS_MULTIPROCESSING)
365    ,
366    FALSE,                       /* TRUE if this is a global object class */
367    NULL                         /* Proxy extraction support callout */
368#endif
369  );
370
371  /*
372   *  Add all the extensions for this API
373   */
374 
375  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
376 
377  _API_extensions_Add( &_POSIX_Threads_API_extensions );
378 
379  /*
380   *  If we supported MP, then here we would ...
381   *       Register the MP Process Packet routine.
382   */
383 
384}
Note: See TracBrowser for help on using the repository browser.