source: rtems/c/src/exec/posix/src/pthread.c @ 7f72217e

4.104.114.84.95
Last change on this file since 7f72217e was 7f72217e, checked in by Joel Sherrill <joel.sherrill@…>, on 05/29/96 at 21:27:26

comment clean up

  • Property mode set to 100644
File size: 16.0 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  *attrp;
542  Priority_Control       core_priority;
543  boolean                is_fp;
544  boolean                status;
545  Thread_Control        *the_thread;
546  char                  *default_name = "psx";
547
548  attrp = (attr) ? attr : &_POSIX_Threads_Default_attributes;
549
550  if ( !attrp->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( attrp->schedparam.sched_priority ) )
575    return EINVAL;
576 
577  core_priority = _POSIX_Priority_To_core( attrp->schedparam.sched_priority );
578 
579  /*
580   *  Currently all POSIX threads are floating point if the hardware
581   *  supports it.
582   */
583
584  is_fp = CPU_HARDWARE_FP;
585
586  /*
587   *  Disable dispatch for protection
588   */
589 
590  _Thread_Disable_dispatch();
591 
592  /*
593   *  Allocate the thread control block.
594   *
595   *  NOTE:  Global threads are not currently supported.
596   */
597
598  the_thread = _POSIX_Threads_Allocate();
599
600  if ( !the_thread ) {
601    _Thread_Enable_dispatch();
602    return EINVAL;
603  }
604
605  /*
606   *  Initialize the core thread for this task.
607   */
608 
609  status = _Thread_Initialize(
610    &_POSIX_Threads_Information,
611    the_thread,
612    attrp->stackaddr,
613    attrp->stacksize,
614    is_fp,
615    core_priority,
616    TRUE,                 /* preemptible */
617    TRUE,                 /* timesliced */
618    0,                    /* isr level */
619    &default_name         /* posix threads don't have a name */
620  );
621 
622  if ( !status ) {
623    _POSIX_Threads_Free( the_thread );
624    _Thread_Enable_dispatch();
625    return EINVAL;
626  }
627
628  status = _Thread_Start(
629    the_thread,
630    THREAD_START_POINTER,
631    start_routine,
632    arg,
633    0                     /* unused */
634  );
635
636  /*
637   *  _Thread_Start only fails if the thread was in the incorrect state
638   */
639
640  if ( !status ) {
641    _POSIX_Threads_Free( the_thread );
642    _Thread_Enable_dispatch();
643    return EINVAL;
644  }
645
646
647  /*
648   *  Return the id and indicate we successfully created the thread
649   */
650
651  *thread = the_thread->Object.id;
652
653 _Thread_Enable_dispatch();
654
655 return 0;
656
657}
658
659/*PAGE
660 *
661 *  16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147
662 */
663
664int pthread_join(
665  pthread_t   thread,
666  void      **value_ptr
667)
668{
669  return POSIX_NOT_IMPLEMENTED();
670}
671
672/*PAGE
673 *
674 *  16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149
675 */
676
677int pthread_detach(
678  pthread_t   thread
679)
680{
681  return POSIX_NOT_IMPLEMENTED();
682}
683
684/*PAGE
685 *
686 * 16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150
687 */
688 
689void pthread_exit(
690  void  *value_ptr
691)
692{
693  register Thread_Control *the_thread;
694
695  the_thread = _Thread_Executing;
696
697  _Thread_Disable_dispatch();
698
699  /*
700   *  XXX Will need to deal with join/detach
701   */
702
703  _Thread_Close( &_POSIX_Threads_Information, the_thread );
704 
705  _POSIX_Threads_Free( the_thread );
706
707  _Thread_Enable_dispatch();
708}
709
710/*PAGE
711 *
712 * 16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. XXX
713 */
714
715pthread_t pthread_self( void )
716{
717  return _Thread_Executing->Object.id;
718}
719
720/*PAGE
721 *
722 *  16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153
723 */
724
725int pthread_equal(
726  pthread_t  t1,
727  pthread_t  t2
728)
729{
730#ifdef RTEMS_DEBUG
731 /* XXX may want to do a "get" to make sure both are valid. */
732 /* XXX behavior is undefined if not valid pthread_t's */
733#endif
734  return _Objects_Are_ids_equal( t1, t1 );
735}
736
737/*PAGE
738 *
739 *  16.1.8 Dynamic Package Initialization
740 */
741
742int pthread_once(
743  pthread_once_t  *once_control,
744  void           (*init_routine)(void)
745)
746{
747  /* XXX: Should we implement this routine this way or make it a full */
748  /* XXX: fledged object? */
749
750  if ( !once_control || !init_routine )
751    return EINVAL;
752
753  _Thread_Disable_dispatch();
754
755  if ( !once_control->is_initialized ) {
756
757    once_control->is_initialized = TRUE;
758    once_control->init_executed = TRUE;
759    (*init_routine)();
760
761  } if ( !once_control->init_executed ) {
762
763    once_control->init_executed = TRUE;
764    (*init_routine)();
765
766  }
767 
768  _Thread_Enable_dispatch();
769
770  return 0;
771}
772
773/*PAGE
774 *
775 *  20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/D8, p. 58
776 */
777 
778int pthread_getcpuclockid(
779  pthread_t    pid,
780  clockid_t   *clock_id
781)
782{
783  return POSIX_NOT_IMPLEMENTED();
784}
785
786/*PAGE
787 *
788 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
789 */
790
791int pthread_attr_setcputime(
792  pthread_attr_t  *attr,
793  int              clock_allowed
794)
795{
796  if ( !attr || !attr->is_initialized )
797    return EINVAL;
798
799  attr->cputime_clock_allowed = clock_allowed;
800  return 0;
801}
802
803/*PAGE
804 *
805 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
806 */
807
808int pthread_attr_getcputime(
809  pthread_attr_t  *attr,
810  int             *clock_allowed
811)
812{
813  if ( !attr || !attr->is_initialized )
814    return EINVAL;
815
816  *clock_allowed = attr->cputime_clock_allowed;
817  return 0;
818}
Note: See TracBrowser for help on using the repository browser.