OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [exec/] [posix/] [src/] [pthread.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 158 chris
/*
2 208 chris
 *  $Id: pthread.c,v 1.2 2001-09-27 11:59:17 chris Exp $
3 158 chris
 */
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
 
33
const 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
 
55
void _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
 
96
void _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
 
128
boolean _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
 
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
 
198
User_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
 
235
User_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
 
254
void _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
 
301
API_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
 
308
User_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
 
333
void _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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.