source: rtems/cpukit/posix/src/pthread.c @ e72d995a

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

moved sleep() from psignal.c to unistd.c

implemented sigemptyset() sigfillset(), sigaddset(), sigdelset(), and
sigismember().

added checks for valid attribute values to some of the pthread_attr_t sets.

  • Property mode set to 100644
File size: 16.7 KB
RevLine 
[8165b48f]1/*
[eb5a7e07]2 *  $Id$
[5e9b32b]3 */
4
[613cff6]5#include <assert.h>
[5e9b32b]6#include <errno.h>
7#include <pthread.h>
8#include <limits.h>
9
[f4719d5a]10#include <rtems/system.h>
[5a18e04]11#include <rtems/score/apiext.h>
[5e9b32b]12#include <rtems/score/stack.h>
13#include <rtems/score/thread.h>
[5a18e04]14#include <rtems/score/userext.h>
15#include <rtems/score/wkspace.h>
[5e9b32b]16#include <rtems/posix/pthread.h>
[ece8c9a]17#include <rtems/posix/priority.h>
[5a18e04]18#include <rtems/posix/config.h>
[5e9b32b]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
[5a18e04]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 *
[dd32d883]87 *  _POSIX_Threads_Initialize_user_threads
[5a18e04]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 
[dd32d883]97void _POSIX_Threads_Initialize_user_threads( void )
[5a18e04]98{
[dd32d883]99  int                                 status;
100  unsigned32                          index;
101  unsigned32                          maximum;
102  posix_initialization_threads_table *user_threads;
103  pthread_t                           thread_id;
104 
105  user_threads = _POSIX_Threads_User_initialization_threads;
106  maximum      = _POSIX_Threads_Number_of_initialization_threads;
[613cff6]107
[dd32d883]108  if ( !user_threads || maximum == 0 )
[613cff6]109    return;
[5a18e04]110 
111  for ( index=0 ; index < maximum ; index++ ) {
[dd32d883]112    status = pthread_create(
113      &thread_id,
114      NULL,
115      user_threads[ index ].entry,
116      NULL
117    );
[613cff6]118    assert( !status );
[5a18e04]119  }
120}
121
122API_extensions_Control _POSIX_Threads_API_extensions = {
123  { NULL, NULL },
124  NULL,                                     /* predriver */
[dd32d883]125  _POSIX_Threads_Initialize_user_threads,   /* postdriver */
[5a18e04]126  NULL,                                     /* post switch */
127};
128 
129User_extensions_Control _POSIX_Threads_User_extensions = {
130  { NULL, NULL },
131  { _POSIX_Threads_Create_extension,          /* create */
132    NULL,                                     /* start */
133    NULL,                                     /* restart */
134    _POSIX_Threads_Delete_extension,          /* delete */
135    NULL,                                     /* switch */
136    NULL,                                     /* begin */
137    NULL,                                     /* exitted */
138    NULL                                      /* fatal */
139  }
140};
141 
[5e9b32b]142/*PAGE
143 *
144 *  _POSIX_Threads_Manager_initialization
145 *
146 *  This routine initializes all threads manager related data structures.
147 *
148 *  Input parameters:
149 *    maximum_pthreads - maximum configured pthreads
150 *
151 *  Output parameters:  NONE
152 */
153 
154void _POSIX_Threads_Manager_initialization(
[dd32d883]155  unsigned32                          maximum_pthreads,
156  unsigned32                          number_of_initialization_threads,
157  posix_initialization_threads_table *user_threads
[5a18e04]158 
[5e9b32b]159)
160{
[dd32d883]161  _POSIX_Threads_Number_of_initialization_threads =
162                                           number_of_initialization_threads;
163  _POSIX_Threads_User_initialization_threads = user_threads;
[5a18e04]164
[974ff40]165  /*
166   *  There may not be any POSIX initialization threads configured.
167   */
168
169#if 0
[dd32d883]170  if ( user_threads == NULL || number_of_initialization_threads == 0 )
[5a18e04]171    _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
[974ff40]172#endif
[5a18e04]173
[5e9b32b]174  _Objects_Initialize_information(
175    &_POSIX_Threads_Information,
176    OBJECTS_POSIX_THREADS,
[ece8c9a]177    FALSE,                               /* does not support global */
[5e9b32b]178    maximum_pthreads,
179    sizeof( POSIX_Threads_Control ),
180    TRUE,
[ece8c9a]181    5,                                   /* length is arbitrary for now */
182    TRUE                                 /* this class is threads */
[5e9b32b]183  );
[5a18e04]184
[613cff6]185  /*
186   *  Add all the extensions for this API
187   */
188 
189  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
190 
191  _API_extensions_Add( &_POSIX_Threads_API_extensions );
192 
193  /*
194   *  If we supported MP, then here we would ...
195   *       Register the MP Process Packet routine.
196   */
197 
[5e9b32b]198}
199
200/*PAGE
201 *
202 *  3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
[568ebf3]203 *
204 *  RTEMS does not support processes, so we fall under this and do not
205 *  provide this routine:
206 *
207 *  "Either the implementation shall support the pthread_atfork() function
208 *   as described above or the pthread_atfork() funciton shall not be
209 *   provided."
[5e9b32b]210 */
211
212/*PAGE
213 *
214 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
215 */
216
217int pthread_attr_setscope(
218  pthread_attr_t  *attr,
219  int              contentionscope
220)
221{
222  if ( !attr || !attr->is_initialized )
223    return EINVAL;
224
[e72d995a]225  switch ( contentionscope ) {
226    case PTHREAD_SCOPE_PROCESS:
227    case PTHREAD_SCOPE_SYSTEM:
228      break;
229    default:
230      return EINVAL;
231  }
232
[5e9b32b]233  attr->contentionscope = contentionscope;
234  return 0;
235}
236
237/*PAGE
238 *
239 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
240 */
241
242int pthread_attr_getscope(
243  const pthread_attr_t  *attr,
244  int                   *contentionscope
245)
246{
247  if ( !attr || !attr->is_initialized )
248    return EINVAL;
249
250  *contentionscope = attr->contentionscope;
251  return 0;
252}
253
254/*PAGE
255 *
256 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
257 */
258
259int pthread_attr_setinheritsched(
260  pthread_attr_t  *attr,
261  int              inheritsched
262)
263{
264  if ( !attr || !attr->is_initialized )
265    return EINVAL;
266
[e72d995a]267  switch ( inheritsched ) {
268    case PTHREAD_INHERIT_SCHED:
269    case PTHREAD_EXPLICIT_SCHED:
270      break;
271    default:
272      return EINVAL;
273  }
274
[5e9b32b]275  attr->inheritsched = 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_getinheritsched(
285  const pthread_attr_t  *attr,
286  int                   *inheritsched
287)
288{
289  if ( !attr || !attr->is_initialized )
290    return EINVAL;
291
292  *inheritsched = attr->inheritsched;
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_setschedpolicy(
302  pthread_attr_t  *attr,
303  int              policy
304)
305{
306  if ( !attr || !attr->is_initialized )
307    return EINVAL;
308
309  attr->schedpolicy = policy;
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_getschedpolicy(
319  const pthread_attr_t  *attr,
320  int                   *policy
321)
322{
323  if ( !attr || !attr->is_initialized )
324    return EINVAL;
325
326  *policy = attr->schedpolicy;
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_setschedparam(
336  pthread_attr_t            *attr,
[f4719d5a]337  const struct sched_param  *param
[5e9b32b]338)
339{
340  if ( !attr || !attr->is_initialized )
341    return EINVAL;
342
[f4719d5a]343  attr->schedparam = *param;
[5e9b32b]344  return 0;
345}
346
347/*PAGE
348 *
349 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
350 */
351
352int pthread_attr_getschedparam(
353  const pthread_attr_t   *attr,
354  struct sched_param     *param
355)
356{
357  if ( !attr || !attr->is_initialized )
358    return EINVAL;
359
360  *param = attr->schedparam;
361  return 0;
362}
363
364/*PAGE
365 *
366 *  13.5.2 Dynamic Thread Scheduling Parameters Access,
367 *         P1003.1c/Draft 10, p. 124
368 */
369
370int pthread_getschedparam(
371  pthread_t           thread,
372  int                *policy,
373  struct sched_param *param
374)
375{
376  pthread_attr_t *attr;   /* XXX: really need to get this from the thread */
377
378  if ( !policy || !param  )
379    return EINVAL;
380
381  *policy = attr->schedpolicy;
382  *param  = attr->schedparam;
383  return 0;
384}
385
386/*PAGE
387 *
388 *  13.5.2 Dynamic Thread Scheduling Parameters Access,
389 *         P1003.1c/Draft 10, p. 124
390 */
391
392int pthread_setschedparam(
393  pthread_t           thread,
394  int                 policy,
395  struct sched_param *param
396)
397{
398  /* XXX need to reschedule after doing this to the thread */
399  pthread_attr_t *attr;   /* XXX: really need to get this from the thread */
400
401  if ( !param )
402    return EINVAL;
403
404  attr->schedpolicy = policy;
405  attr->schedparam  = *param;
406  return 0;
407}
408
409/*PAGE
410 *
411 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
412 */
413
414int pthread_attr_init(
415  pthread_attr_t  *attr
416)
417{
418  if ( !attr )
419    return EINVAL;
420 
421  *attr = _POSIX_Threads_Default_attributes;
422  return 0;
423}
424
425/*PAGE
426 *
427 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
428 */
429
430int pthread_attr_destroy(
431  pthread_attr_t  *attr
432)
433{
434  if ( !attr || !attr->is_initialized )
435    return EINVAL;
436 
437  attr->is_initialized = FALSE;
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_getstacksize(
447  const pthread_attr_t  *attr,
448  size_t                *stacksize
449)
450{
451  if ( !attr || !attr->is_initialized )
452    return EINVAL;
453
454  *stacksize = attr->stacksize;
455  return 0;
456}
457 
458/*PAGE
459 *
460 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
461 */
462
463int pthread_attr_setstacksize(
464  pthread_attr_t  *attr,
465  size_t           stacksize
466)
467{
468  if ( !attr || !attr->is_initialized )
469    return EINVAL;
470
[9c877c0d]471  if ( stacksize < STACK_MINIMUM_SIZE )
472    attr->stacksize = STACK_MINIMUM_SIZE;
473  else
474    attr->stacksize = stacksize;
[5e9b32b]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_getstackaddr(
484  const pthread_attr_t   *attr,
485  void                  **stackaddr
486)
487{
488  if ( !attr || !attr->is_initialized )
489    return EINVAL;
490
491  *stackaddr = attr->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_setstackaddr(
501  pthread_attr_t  *attr,
502  void            *stackaddr
503)
504{
505  if ( !attr || !attr->is_initialized )
506    return EINVAL;
507
508  attr->stackaddr = stackaddr;
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_getdetachstate(
518  const pthread_attr_t  *attr,
519  int                   *detachstate
520)
521{
522  if ( !attr || !attr->is_initialized )
523    return EINVAL;
524
525  *detachstate = attr->detachstate;
526  return 0;
527}
528 
529/*PAGE
530 *
531 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
532 */
533
534int pthread_attr_setdetachstate(
535  pthread_attr_t  *attr,
536  int              detachstate
537)
538{
539  if ( !attr || !attr->is_initialized )
540    return EINVAL;
541
542  attr->detachstate = detachstate;
543  return 0;
544}
545
546/*PAGE
547 *
548 *  16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
549 */
550
551int pthread_create(
[974ff40]552  pthread_t              *thread,
553  const pthread_attr_t   *attr,
554  void                 *(*start_routine)( void * ),
555  void                   *arg
[5e9b32b]556)
557{
[cfcfdf0]558  const pthread_attr_t  *attrp;
[ece8c9a]559  Priority_Control       core_priority;
560  boolean                is_fp;
561  boolean                status;
562  Thread_Control        *the_thread;
563  char                  *default_name = "psx";
[5a18e04]564
[cfcfdf0]565  attrp = (attr) ? attr : &_POSIX_Threads_Default_attributes;
[5a18e04]566
[cfcfdf0]567  if ( !attrp->is_initialized )
[5a18e04]568    return EINVAL;
569
570  /*
571   *  Core Thread Initialize insures we get the minimum amount of
572   *  stack space.
573   */
574
575#if 0
576  int contentionscope;
577  int inheritsched;
578  int schedpolicy;
579  struct sched_param schedparam;
580
581#if defined(_POSIX_THREAD_CPUTIME)
582  int  cputime_clock_allowed;  /* see time.h */
583#endif
584  int  detachstate;
585#endif
[974ff40]586
[e72d995a]587  /*
588   *  P1003.1c/D10, p. 121.
589   *
590   *  If inheritsched is set to PTHREAD_INHERIT_SCHED, then this thread
591   *  inherits scheduling attributes from the creating thread.   If it is
592   *  PTHREAD_EXPLICIT_SCHED, then scheduling parameters come from the
593   *  attributes structure.
594   */
595
596  switch ( attrp->inheritsched ) {
597    case PTHREAD_INHERIT_SCHED:
598      break;
599    case PTHREAD_EXPLICIT_SCHED:
600      break;
601  }
602
[ece8c9a]603  /*
604   *  Validate the RTEMS API priority and convert it to the core priority range.
605   */
606 
[cfcfdf0]607  if ( !_POSIX_Priority_Is_valid( attrp->schedparam.sched_priority ) )
[ece8c9a]608    return EINVAL;
609 
[cfcfdf0]610  core_priority = _POSIX_Priority_To_core( attrp->schedparam.sched_priority );
[ece8c9a]611 
612  /*
[7f72217e]613   *  Currently all POSIX threads are floating point if the hardware
614   *  supports it.
[ece8c9a]615   */
616
[7f72217e]617  is_fp = CPU_HARDWARE_FP;
[ece8c9a]618
619  /*
620   *  Disable dispatch for protection
621   */
622 
623  _Thread_Disable_dispatch();
624 
625  /*
626   *  Allocate the thread control block.
627   *
628   *  NOTE:  Global threads are not currently supported.
629   */
630
631  the_thread = _POSIX_Threads_Allocate();
632
633  if ( !the_thread ) {
634    _Thread_Enable_dispatch();
635    return EINVAL;
636  }
637
638  /*
639   *  Initialize the core thread for this task.
640   */
641 
642  status = _Thread_Initialize(
643    &_POSIX_Threads_Information,
644    the_thread,
[cfcfdf0]645    attrp->stackaddr,
646    attrp->stacksize,
[ece8c9a]647    is_fp,
648    core_priority,
649    TRUE,                 /* preemptible */
650    TRUE,                 /* timesliced */
651    0,                    /* isr level */
652    &default_name         /* posix threads don't have a name */
653  );
654 
655  if ( !status ) {
656    _POSIX_Threads_Free( the_thread );
657    _Thread_Enable_dispatch();
658    return EINVAL;
659  }
660
[cfcfdf0]661  status = _Thread_Start(
662    the_thread,
663    THREAD_START_POINTER,
664    start_routine,
665    arg,
666    0                     /* unused */
667  );
668
669  /*
670   *  _Thread_Start only fails if the thread was in the incorrect state
671   */
672
673  if ( !status ) {
674    _POSIX_Threads_Free( the_thread );
675    _Thread_Enable_dispatch();
676    return EINVAL;
677  }
678
679
680  /*
681   *  Return the id and indicate we successfully created the thread
682   */
683
[ece8c9a]684  *thread = the_thread->Object.id;
685
686 _Thread_Enable_dispatch();
687
688 return 0;
689
[5e9b32b]690}
691
692/*PAGE
693 *
694 *  16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147
695 */
696
697int pthread_join(
698  pthread_t   thread,
699  void      **value_ptr
700)
701{
702  return POSIX_NOT_IMPLEMENTED();
703}
704
705/*PAGE
706 *
707 *  16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149
708 */
709
710int pthread_detach(
711  pthread_t   thread
712)
713{
714  return POSIX_NOT_IMPLEMENTED();
715}
716
[974ff40]717/*PAGE
718 *
719 * 16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150
720 */
721 
722void pthread_exit(
723  void  *value_ptr
724)
725{
[cfcfdf0]726  register Thread_Control *the_thread;
727
728  the_thread = _Thread_Executing;
729
730  _Thread_Disable_dispatch();
731
732  /*
733   *  XXX Will need to deal with join/detach
734   */
735
736  _Thread_Close( &_POSIX_Threads_Information, the_thread );
737 
738  _POSIX_Threads_Free( the_thread );
739
740  _Thread_Enable_dispatch();
[974ff40]741}
[5e9b32b]742
743/*PAGE
744 *
745 * 16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. XXX
746 */
747
748pthread_t pthread_self( void )
749{
750  return _Thread_Executing->Object.id;
751}
752
753/*PAGE
754 *
755 *  16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153
756 */
757
758int pthread_equal(
759  pthread_t  t1,
760  pthread_t  t2
761)
762{
763#ifdef RTEMS_DEBUG
764 /* XXX may want to do a "get" to make sure both are valid. */
765 /* XXX behavior is undefined if not valid pthread_t's */
766#endif
767  return _Objects_Are_ids_equal( t1, t1 );
768}
769
770/*PAGE
771 *
772 *  16.1.8 Dynamic Package Initialization
773 */
774
775int pthread_once(
776  pthread_once_t  *once_control,
777  void           (*init_routine)(void)
778)
779{
780  /* XXX: Should we implement this routine this way or make it a full */
781  /* XXX: fledged object? */
782
783  if ( !once_control || !init_routine )
784    return EINVAL;
785
786  _Thread_Disable_dispatch();
787
788  if ( !once_control->is_initialized ) {
789
790    once_control->is_initialized = TRUE;
791    once_control->init_executed = TRUE;
792    (*init_routine)();
793
794  } if ( !once_control->init_executed ) {
795
796    once_control->init_executed = TRUE;
797    (*init_routine)();
798
799  }
800 
801  _Thread_Enable_dispatch();
802
803  return 0;
804}
805
806/*PAGE
807 *
808 *  20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/D8, p. 58
809 */
810 
811int pthread_getcpuclockid(
812  pthread_t    pid,
813  clockid_t   *clock_id
814)
815{
816  return POSIX_NOT_IMPLEMENTED();
817}
818
819/*PAGE
820 *
821 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
822 */
823
824int pthread_attr_setcputime(
825  pthread_attr_t  *attr,
826  int              clock_allowed
827)
828{
829  if ( !attr || !attr->is_initialized )
830    return EINVAL;
831
832  attr->cputime_clock_allowed = clock_allowed;
833  return 0;
834}
835
836/*PAGE
837 *
838 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
839 */
840
841int pthread_attr_getcputime(
842  pthread_attr_t  *attr,
843  int             *clock_allowed
844)
845{
846  if ( !attr || !attr->is_initialized )
847    return EINVAL;
848
849  *clock_allowed = attr->cputime_clock_allowed;
850  return 0;
851}
Note: See TracBrowser for help on using the repository browser.