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

4.104.114.84.95
Last change on this file since c238a218 was c238a218, checked in by Joel Sherrill <joel.sherrill@…>, on 05/31/96 at 21:40:48

added checks to validate values passed to set attribute routines

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