source: rtems/c/src/exec/posix/src/pthread.c @ ece8c9a

4.104.114.84.95
Last change on this file since ece8c9a was ece8c9a, checked in by Joel Sherrill <joel.sherrill@…>, on 05/29/96 at 19:28:01

first cut at pthread_create

  • Property mode set to 100644
File size: 15.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/config.h>
19
20/*PAGE
21 *
22 *  The default pthreads attributes structure.
23 */
24 
25const pthread_attr_t _POSIX_Threads_Default_attributes = {
26  TRUE,                    /* is_initialized */
27  0,                       /* stackaddr */
28  STACK_MINIMUM_SIZE,      /* stacksize */
29  PTHREAD_SCOPE_PROCESS,   /* contentionscope */
30  PTHREAD_INHERIT_SCHED,   /* inheritsched */
31  SCHED_FIFO,              /* schedpolicy */
32  {                        /* schedparam */
33    128,                   /* sched_priority */
34    0,                     /* ss_low_priority */
35    { 0L, 0 },             /* ss_replenish_period */
36    { 0L, 0 }              /* ss_initial_budget */
37  },
38  PTHREAD_CREATE_DETACHED, /* detachstate */
39  1                        /* cputime_clock_allowed */
40};
41
42/*PAGE
43 *
44 *  _POSIX_Threads_Create_extension
45 *
46 *  XXX
47 */
48 
49boolean _POSIX_Threads_Create_extension(
50  Thread_Control *executing,
51  Thread_Control *created
52)
53{
54  POSIX_API_Control *api;
55 
56  api = _Workspace_Allocate( sizeof( POSIX_API_Control ) );
57 
58  if ( !api )
59    return FALSE;
60 
61  created->API_Extensions[ THREAD_API_POSIX ] = api;
62 
63  /* XXX something should go here */
64
65  return TRUE;
66}
67 
68/*PAGE
69 *
70 *  _POSIX_Threads_Delete_extension
71 *
72 *  XXX
73 */
74 
75User_extensions_routine _POSIX_Threads_Delete_extension(
76  Thread_Control *executing,
77  Thread_Control *deleted
78)
79{
80  (void) _Workspace_Free( deleted->API_Extensions[ THREAD_API_POSIX ] );
81 
82  deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
83}
84
85/*PAGE
86 *
87 *  _POSIX_Threads_Initialize_user_tasks
88 *
89 *  This routine creates and starts all configured user
90 *  initialzation threads.
91 *
92 *  Input parameters: NONE
93 *
94 *  Output parameters:  NONE
95 */
96 
97void _POSIX_Threads_Initialize_user_tasks( void )
98{
99  int                               status;
100  unsigned32                        index;
101  unsigned32                        maximum;
102  posix_initialization_tasks_table *user_tasks;
103  pthread_t                         thread_id;
104 
105  /*
106   *  NOTE:  This is slightly different from the Ada implementation.
107   */
108 
109  user_tasks = _POSIX_Threads_User_initialization_tasks;
110  maximum    = _POSIX_Threads_Number_of_initialization_tasks;
111
112  if ( !user_tasks || maximum == 0 )
113    return;
114 
115  for ( index=0 ; index < maximum ; index++ ) {
116    status = pthread_create(&thread_id,  NULL, user_tasks[ index ].entry, NULL);
117    assert( !status );
118  }
119}
120
121API_extensions_Control _POSIX_Threads_API_extensions = {
122  { NULL, NULL },
123  NULL,                                     /* predriver */
124  _POSIX_Threads_Initialize_user_tasks,     /* postdriver */
125  NULL,                                     /* post switch */
126};
127 
128User_extensions_Control _POSIX_Threads_User_extensions = {
129  { NULL, NULL },
130  { _POSIX_Threads_Create_extension,          /* create */
131    NULL,                                     /* start */
132    NULL,                                     /* restart */
133    _POSIX_Threads_Delete_extension,          /* delete */
134    NULL,                                     /* switch */
135    NULL,                                     /* begin */
136    NULL,                                     /* exitted */
137    NULL                                      /* fatal */
138  }
139};
140 
141/*PAGE
142 *
143 *  _POSIX_Threads_Manager_initialization
144 *
145 *  This routine initializes all threads manager related data structures.
146 *
147 *  Input parameters:
148 *    maximum_pthreads - maximum configured pthreads
149 *
150 *  Output parameters:  NONE
151 */
152 
153void _POSIX_Threads_Manager_initialization(
154  unsigned32                        maximum_pthreads,
155  unsigned32                        number_of_initialization_tasks,
156  posix_initialization_tasks_table *user_tasks
157 
158)
159{
160  _POSIX_Threads_Number_of_initialization_tasks =
161                                                 number_of_initialization_tasks;
162  _POSIX_Threads_User_initialization_tasks = user_tasks;
163
164  /*
165   *  There may not be any POSIX initialization threads configured.
166   */
167
168#if 0
169  if ( user_tasks == NULL || number_of_initialization_tasks == 0 )
170    _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
171#endif
172
173  _Objects_Initialize_information(
174    &_POSIX_Threads_Information,
175    OBJECTS_POSIX_THREADS,
176    FALSE,                               /* does not support global */
177    maximum_pthreads,
178    sizeof( POSIX_Threads_Control ),
179    TRUE,
180    5,                                   /* length is arbitrary for now */
181    TRUE                                 /* this class is threads */
182  );
183
184  /*
185   *  Add all the extensions for this API
186   */
187 
188  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
189 
190  _API_extensions_Add( &_POSIX_Threads_API_extensions );
191 
192  /*
193   *  If we supported MP, then here we would ...
194   *       Register the MP Process Packet routine.
195   */
196 
197}
198
199/*PAGE
200 *
201 *  3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
202 *
203 *  RTEMS does not support processes, so we fall under this and do not
204 *  provide this routine:
205 *
206 *  "Either the implementation shall support the pthread_atfork() function
207 *   as described above or the pthread_atfork() funciton shall not be
208 *   provided."
209 */
210
211/*PAGE
212 *
213 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
214 */
215
216int pthread_attr_setscope(
217  pthread_attr_t  *attr,
218  int              contentionscope
219)
220{
221  if ( !attr || !attr->is_initialized )
222    return EINVAL;
223
224  attr->contentionscope = contentionscope;
225  return 0;
226}
227
228/*PAGE
229 *
230 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
231 */
232
233int pthread_attr_getscope(
234  const pthread_attr_t  *attr,
235  int                   *contentionscope
236)
237{
238  if ( !attr || !attr->is_initialized )
239    return EINVAL;
240
241  *contentionscope = attr->contentionscope;
242  return 0;
243}
244
245/*PAGE
246 *
247 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
248 */
249
250int pthread_attr_setinheritsched(
251  pthread_attr_t  *attr,
252  int              inheritsched
253)
254{
255  if ( !attr || !attr->is_initialized )
256    return EINVAL;
257
258  attr->inheritsched = inheritsched;
259  return 0;
260}
261
262/*PAGE
263 *
264 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
265 */
266
267int pthread_attr_getinheritsched(
268  const pthread_attr_t  *attr,
269  int                   *inheritsched
270)
271{
272  if ( !attr || !attr->is_initialized )
273    return EINVAL;
274
275  *inheritsched = attr->inheritsched;
276  return 0;
277}
278
279/*PAGE
280 *
281 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
282 */
283
284int pthread_attr_setschedpolicy(
285  pthread_attr_t  *attr,
286  int              policy
287)
288{
289  if ( !attr || !attr->is_initialized )
290    return EINVAL;
291
292  attr->schedpolicy = policy;
293  return 0;
294}
295
296/*PAGE
297 *
298 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
299 */
300
301int pthread_attr_getschedpolicy(
302  const pthread_attr_t  *attr,
303  int                   *policy
304)
305{
306  if ( !attr || !attr->is_initialized )
307    return EINVAL;
308
309  *policy = attr->schedpolicy;
310  return 0;
311}
312
313/*PAGE
314 *
315 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
316 */
317
318int pthread_attr_setschedparam(
319  pthread_attr_t            *attr,
320  const struct sched_param  *param
321)
322{
323  if ( !attr || !attr->is_initialized )
324    return EINVAL;
325
326  attr->schedparam = *param;
327  return 0;
328}
329
330/*PAGE
331 *
332 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
333 */
334
335int pthread_attr_getschedparam(
336  const pthread_attr_t   *attr,
337  struct sched_param     *param
338)
339{
340  if ( !attr || !attr->is_initialized )
341    return EINVAL;
342
343  *param = attr->schedparam;
344  return 0;
345}
346
347/*PAGE
348 *
349 *  13.5.2 Dynamic Thread Scheduling Parameters Access,
350 *         P1003.1c/Draft 10, p. 124
351 */
352
353int pthread_getschedparam(
354  pthread_t           thread,
355  int                *policy,
356  struct sched_param *param
357)
358{
359  pthread_attr_t *attr;   /* XXX: really need to get this from the thread */
360
361  if ( !policy || !param  )
362    return EINVAL;
363
364  *policy = attr->schedpolicy;
365  *param  = attr->schedparam;
366  return 0;
367}
368
369/*PAGE
370 *
371 *  13.5.2 Dynamic Thread Scheduling Parameters Access,
372 *         P1003.1c/Draft 10, p. 124
373 */
374
375int pthread_setschedparam(
376  pthread_t           thread,
377  int                 policy,
378  struct sched_param *param
379)
380{
381  /* XXX need to reschedule after doing this to the thread */
382  pthread_attr_t *attr;   /* XXX: really need to get this from the thread */
383
384  if ( !param )
385    return EINVAL;
386
387  attr->schedpolicy = policy;
388  attr->schedparam  = *param;
389  return 0;
390}
391
392/*PAGE
393 *
394 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
395 */
396
397int pthread_attr_init(
398  pthread_attr_t  *attr
399)
400{
401  if ( !attr )
402    return EINVAL;
403 
404  *attr = _POSIX_Threads_Default_attributes;
405  return 0;
406}
407
408/*PAGE
409 *
410 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
411 */
412
413int pthread_attr_destroy(
414  pthread_attr_t  *attr
415)
416{
417  if ( !attr || !attr->is_initialized )
418    return EINVAL;
419 
420  attr->is_initialized = FALSE;
421  return 0;
422}
423 
424/*PAGE
425 *
426 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
427 */
428
429int pthread_attr_getstacksize(
430  const pthread_attr_t  *attr,
431  size_t                *stacksize
432)
433{
434  if ( !attr || !attr->is_initialized )
435    return EINVAL;
436
437  *stacksize = attr->stacksize;
438  return 0;
439}
440 
441/*PAGE
442 *
443 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
444 */
445
446int pthread_attr_setstacksize(
447  pthread_attr_t  *attr,
448  size_t           stacksize
449)
450{
451  if ( !attr || !attr->is_initialized )
452    return EINVAL;
453
454  if ( stacksize < STACK_MINIMUM_SIZE )
455    attr->stacksize = STACK_MINIMUM_SIZE;
456  else
457    attr->stacksize = stacksize;
458  return 0;
459}
460 
461/*PAGE
462 *
463 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
464 */
465
466int pthread_attr_getstackaddr(
467  const pthread_attr_t   *attr,
468  void                  **stackaddr
469)
470{
471  if ( !attr || !attr->is_initialized )
472    return EINVAL;
473
474  *stackaddr = attr->stackaddr;
475  return 0;
476}
477 
478/*PAGE
479 *
480 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
481 */
482
483int pthread_attr_setstackaddr(
484  pthread_attr_t  *attr,
485  void            *stackaddr
486)
487{
488  if ( !attr || !attr->is_initialized )
489    return EINVAL;
490
491  attr->stackaddr = stackaddr;
492  return 0;
493}
494 
495/*PAGE
496 *
497 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
498 */
499
500int pthread_attr_getdetachstate(
501  const pthread_attr_t  *attr,
502  int                   *detachstate
503)
504{
505  if ( !attr || !attr->is_initialized )
506    return EINVAL;
507
508  *detachstate = attr->detachstate;
509  return 0;
510}
511 
512/*PAGE
513 *
514 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
515 */
516
517int pthread_attr_setdetachstate(
518  pthread_attr_t  *attr,
519  int              detachstate
520)
521{
522  if ( !attr || !attr->is_initialized )
523    return EINVAL;
524
525  attr->detachstate = detachstate;
526  return 0;
527}
528
529/*PAGE
530 *
531 *  16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
532 */
533
534int pthread_create(
535  pthread_t              *thread,
536  const pthread_attr_t   *attr,
537  void                 *(*start_routine)( void * ),
538  void                   *arg
539)
540{
541  const pthread_attr_t  *local_attr;
542  Priority_Control       core_priority;
543  boolean                is_fp;
544  boolean                status;
545  Thread_Control        *the_thread;
546  char                  *default_name = "psx";
547
548  local_attr = (attr) ? attr : &_POSIX_Threads_Default_attributes;
549
550  if ( !local_attr->is_initialized )
551    return EINVAL;
552
553  /*
554   *  Core Thread Initialize insures we get the minimum amount of
555   *  stack space.
556   */
557
558#if 0
559  int contentionscope;
560  int inheritsched;
561  int schedpolicy;
562  struct sched_param schedparam;
563
564#if defined(_POSIX_THREAD_CPUTIME)
565  int  cputime_clock_allowed;  /* see time.h */
566#endif
567  int  detachstate;
568#endif
569
570  /*
571   *  Validate the RTEMS API priority and convert it to the core priority range.
572   */
573 
574  if ( !_POSIX_Priority_Is_valid( attr->schedparam.sched_priority ) )
575    return EINVAL;
576 
577  core_priority = _POSIX_Priority_To_core( attr->schedparam.sched_priority );
578 
579  /*
580   *  Currently all POSIX threads are floating point.
581   */
582
583  is_fp = TRUE;
584
585  /*
586   *  Disable dispatch for protection
587   */
588 
589  _Thread_Disable_dispatch();
590 
591  /*
592   *  Allocate the thread control block.
593   *
594   *  NOTE:  Global threads are not currently supported.
595   */
596
597  the_thread = _POSIX_Threads_Allocate();
598
599  if ( !the_thread ) {
600    _Thread_Enable_dispatch();
601    return EINVAL;
602  }
603
604  /*
605   *  Initialize the core thread for this task.
606   */
607 
608  status = _Thread_Initialize(
609    &_POSIX_Threads_Information,
610    the_thread,
611    attr->stackaddr,
612    attr->stacksize,
613    is_fp,
614    core_priority,
615    TRUE,                 /* preemptible */
616    TRUE,                 /* timesliced */
617    0,                    /* isr level */
618    &default_name         /* posix threads don't have a name */
619  );
620 
621  if ( !status ) {
622    _POSIX_Threads_Free( the_thread );
623    _Thread_Enable_dispatch();
624    return EINVAL;
625  }
626
627  *thread = the_thread->Object.id;
628
629 _Thread_Enable_dispatch();
630
631 return 0;
632
633}
634
635/*PAGE
636 *
637 *  16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147
638 */
639
640int pthread_join(
641  pthread_t   thread,
642  void      **value_ptr
643)
644{
645  return POSIX_NOT_IMPLEMENTED();
646}
647
648/*PAGE
649 *
650 *  16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149
651 */
652
653int pthread_detach(
654  pthread_t   thread
655)
656{
657  return POSIX_NOT_IMPLEMENTED();
658}
659
660/*PAGE
661 *
662 * 16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150
663 */
664 
665void pthread_exit(
666  void  *value_ptr
667)
668{
669  POSIX_NOT_IMPLEMENTED();
670}
671
672/*PAGE
673 *
674 * 16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. XXX
675 */
676
677pthread_t pthread_self( void )
678{
679  return _Thread_Executing->Object.id;
680}
681
682/*PAGE
683 *
684 *  16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153
685 */
686
687int pthread_equal(
688  pthread_t  t1,
689  pthread_t  t2
690)
691{
692#ifdef RTEMS_DEBUG
693 /* XXX may want to do a "get" to make sure both are valid. */
694 /* XXX behavior is undefined if not valid pthread_t's */
695#endif
696  return _Objects_Are_ids_equal( t1, t1 );
697}
698
699/*PAGE
700 *
701 *  16.1.8 Dynamic Package Initialization
702 */
703
704int pthread_once(
705  pthread_once_t  *once_control,
706  void           (*init_routine)(void)
707)
708{
709  /* XXX: Should we implement this routine this way or make it a full */
710  /* XXX: fledged object? */
711
712  if ( !once_control || !init_routine )
713    return EINVAL;
714
715  _Thread_Disable_dispatch();
716
717  if ( !once_control->is_initialized ) {
718
719    once_control->is_initialized = TRUE;
720    once_control->init_executed = TRUE;
721    (*init_routine)();
722
723  } if ( !once_control->init_executed ) {
724
725    once_control->init_executed = TRUE;
726    (*init_routine)();
727
728  }
729 
730  _Thread_Enable_dispatch();
731
732  return 0;
733}
734
735/*PAGE
736 *
737 *  20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/D8, p. 58
738 */
739 
740int pthread_getcpuclockid(
741  pthread_t    pid,
742  clockid_t   *clock_id
743)
744{
745  return POSIX_NOT_IMPLEMENTED();
746}
747
748/*PAGE
749 *
750 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
751 */
752
753int pthread_attr_setcputime(
754  pthread_attr_t  *attr,
755  int              clock_allowed
756)
757{
758  if ( !attr || !attr->is_initialized )
759    return EINVAL;
760
761  attr->cputime_clock_allowed = clock_allowed;
762  return 0;
763}
764
765/*PAGE
766 *
767 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
768 */
769
770int pthread_attr_getcputime(
771  pthread_attr_t  *attr,
772  int             *clock_allowed
773)
774{
775  if ( !attr || !attr->is_initialized )
776    return EINVAL;
777
778  *clock_allowed = attr->cputime_clock_allowed;
779  return 0;
780}
Note: See TracBrowser for help on using the repository browser.