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

4.104.114.84.95
Last change on this file since fdec30b was fdec30b, checked in by Joel Sherrill <joel.sherrill@…>, on 06/10/96 at 20:47:23

first attempt at the routine which vectors signals.

  • Property mode set to 100644
File size: 26.4 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#include <rtems/posix/key.h>
20#include <rtems/posix/time.h>
21
22/*PAGE
23 *
24 *  The default pthreads attributes structure.
25 */
26 
27const pthread_attr_t _POSIX_Threads_Default_attributes = {
28  TRUE,                    /* is_initialized */
29  NULL,                    /* stackaddr */
30  STACK_MINIMUM_SIZE,      /* stacksize */
31  PTHREAD_SCOPE_PROCESS,   /* contentionscope */
32  PTHREAD_EXPLICIT_SCHED,  /* inheritsched */
33  SCHED_FIFO,              /* schedpolicy */
34  {                        /* schedparam */
35    128,                   /* sched_priority */
36    0,                     /* ss_low_priority */
37    { 0L, 0 },             /* ss_replenish_period */
38    { 0L, 0 }              /* ss_initial_budget */
39  },
40  PTHREAD_CREATE_JOINABLE, /* detachstate */
41  1                        /* cputime_clock_allowed */
42};
43
44/*PAGE
45 *
46 *  _POSIX_Threads_Sporadic_budget_TSR
47 */
48
49void _POSIX_Threads_Sporadic_budget_TSR(
50  Objects_Id      id,
51  void           *argument
52)
53{
54  Thread_Control     *the_thread;
55  POSIX_API_Control  *api;
56
57  the_thread = argument;
58
59  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
60
61  the_thread->cpu_time_budget =
62    _POSIX_Timespec_to_interval( &api->schedparam.ss_initial_budget );
63
64  _Thread_Change_priority(
65    the_thread,
66    _POSIX_Priority_To_core( api->schedparam.sched_priority )
67  );
68 
69  _Watchdog_Insert_ticks(
70    &api->Sporadic_timer,
71    _POSIX_Timespec_to_interval( &api->schedparam.ss_replenish_period )
72  );
73}
74
75/*PAGE
76 *
77 *  _POSIX_Threads_Sporadic_budget_callout
78 */
79
80void _POSIX_Threads_Sporadic_budget_callout(
81  Thread_Control *the_thread
82)
83{
84  POSIX_API_Control                  *api;
85
86  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
87
88  /* XXX really should be based on MAX_U32 */
89
90  the_thread->cpu_time_budget = 0xFFFFFFFF;
91
92  _Thread_Change_priority(
93    the_thread,
94    _POSIX_Priority_To_core( api->schedparam.ss_low_priority )
95  );
96}
97
98/*PAGE
99 *
100 *  _POSIX_Threads_Create_extension
101 *
102 *  XXX
103 */
104 
105boolean _POSIX_Threads_Create_extension(
106  Thread_Control *executing,
107  Thread_Control *created
108)
109{
110  POSIX_API_Control *api;
111 
112  api = _Workspace_Allocate( sizeof( POSIX_API_Control ) );
113 
114  if ( !api )
115    return FALSE;
116 
117  created->API_Extensions[ THREAD_API_POSIX ] = api;
118 
119  api->Attributes  = _POSIX_Threads_Default_attributes;
120  api->detachstate = _POSIX_Threads_Default_attributes.detachstate;
121  api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy;
122  api->schedparam  = _POSIX_Threads_Default_attributes.schedparam;
123  api->schedparam.sched_priority =
124     _POSIX_Priority_From_core( created->current_priority );
125 
126/* XXX set signal parameters -- block all signals for non-posix threads */
127
128  _Thread_queue_Initialize(
129    &api->Join_List,
130    OBJECTS_NO_CLASS,                 /* only used for proxy operations */
131    THREAD_QUEUE_DISCIPLINE_FIFO,
132    STATES_WAITING_FOR_JOIN_AT_EXIT,
133    NULL,                             /* no extract proxy handler */
134    0
135  );
136 
137  _Watchdog_Initialize(
138    &api->Sporadic_timer,
139    _POSIX_Threads_Sporadic_budget_TSR,
140    created->Object.id,
141    created
142  );
143
144  return TRUE;
145}
146
147/*PAGE
148 *
149 *  _POSIX_Threads_Delete_extension
150 */
151 
152User_extensions_routine _POSIX_Threads_Delete_extension(
153  Thread_Control *executing,
154  Thread_Control *deleted
155)
156{
157  Thread_Control     *the_thread;
158  POSIX_API_Control  *api;
159  void              **value_ptr;
160
161  (void) _Workspace_Free( deleted->API_Extensions[ THREAD_API_POSIX ] );
162 
163  deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
164
165  /* XXX run cancellation handlers */
166
167  _POSIX_Keys_Run_destructors( deleted );
168
169  /*
170   *  Wakeup all the tasks which joined with this one
171   */
172 
173  api = deleted->API_Extensions[ THREAD_API_POSIX ];
174 
175  value_ptr = (void **) deleted->Wait.return_argument;
176
177  while ( (the_thread = _Thread_queue_Dequeue( &api->Join_List )) )
178      *(void **)the_thread->Wait.return_argument = value_ptr;
179 
180  if ( api->schedpolicy == SCHED_SPORADIC )
181    (void) _Watchdog_Remove( &api->Sporadic_timer );
182}
183
184/*PAGE
185 *
186 *  _POSIX_Threads_Initialize_user_threads
187 *
188 *  This routine creates and starts all configured user
189 *  initialzation threads.
190 *
191 *  Input parameters: NONE
192 *
193 *  Output parameters:  NONE
194 */
195 
196void _POSIX_Threads_Initialize_user_threads( void )
197{
198  int                                 status;
199  unsigned32                          index;
200  unsigned32                          maximum;
201  posix_initialization_threads_table *user_threads;
202  pthread_t                           thread_id;
203 
204  user_threads = _POSIX_Threads_User_initialization_threads;
205  maximum      = _POSIX_Threads_Number_of_initialization_threads;
206
207  if ( !user_threads || maximum == 0 )
208    return;
209 
210  for ( index=0 ; index < maximum ; index++ ) {
211    status = pthread_create(
212      &thread_id,
213      NULL,
214      user_threads[ index ].entry,
215      NULL
216    );
217    assert( !status );
218  }
219}
220
221API_extensions_Control _POSIX_Threads_API_extensions = {
222  { NULL, NULL },
223  NULL,                                     /* predriver */
224  _POSIX_Threads_Initialize_user_threads,   /* postdriver */
225  NULL,                                     /* post switch */
226};
227 
228User_extensions_Control _POSIX_Threads_User_extensions = {
229  { NULL, NULL },
230  { _POSIX_Threads_Create_extension,          /* create */
231    NULL,                                     /* start */
232    NULL,                                     /* restart */
233    _POSIX_Threads_Delete_extension,          /* delete */
234    NULL,                                     /* switch */
235    NULL,                                     /* begin */
236    NULL,                                     /* exitted */
237    NULL                                      /* fatal */
238  }
239};
240 
241/*PAGE
242 *
243 *  _POSIX_Threads_Manager_initialization
244 *
245 *  This routine initializes all threads manager related data structures.
246 *
247 *  Input parameters:
248 *    maximum_pthreads - maximum configured pthreads
249 *
250 *  Output parameters:  NONE
251 */
252 
253void _POSIX_Threads_Manager_initialization(
254  unsigned32                          maximum_pthreads,
255  unsigned32                          number_of_initialization_threads,
256  posix_initialization_threads_table *user_threads
257 
258)
259{
260  _POSIX_Threads_Number_of_initialization_threads =
261                                           number_of_initialization_threads;
262  _POSIX_Threads_User_initialization_threads = user_threads;
263
264  /*
265   *  There may not be any POSIX initialization threads configured.
266   */
267
268#if 0
269  if ( user_threads == NULL || number_of_initialization_threads == 0 )
270    _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
271#endif
272
273  _Objects_Initialize_information(
274    &_POSIX_Threads_Information,
275    OBJECTS_POSIX_THREADS,
276    FALSE,                               /* does not support global */
277    maximum_pthreads,
278    sizeof( Thread_Control ),
279    TRUE,
280    5,                                   /* length is arbitrary for now */
281    TRUE                                 /* this class is threads */
282  );
283
284  /*
285   *  Add all the extensions for this API
286   */
287 
288  _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
289 
290  _API_extensions_Add( &_POSIX_Threads_API_extensions );
291 
292  /*
293   *  If we supported MP, then here we would ...
294   *       Register the MP Process Packet routine.
295   */
296 
297}
298
299/*PAGE
300 *
301 *  3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
302 *
303 *  RTEMS does not support processes, so we fall under this and do not
304 *  provide this routine:
305 *
306 *  "Either the implementation shall support the pthread_atfork() function
307 *   as described above or the pthread_atfork() funciton shall not be
308 *   provided."
309 */
310
311/*PAGE
312 *
313 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
314 */
315
316int pthread_attr_setscope(
317  pthread_attr_t  *attr,
318  int              contentionscope
319)
320{
321  if ( !attr || !attr->is_initialized )
322    return EINVAL;
323
324  switch ( contentionscope ) {
325    case PTHREAD_SCOPE_PROCESS:
326      attr->contentionscope = contentionscope;
327      return 0;
328
329    case PTHREAD_SCOPE_SYSTEM:
330      return ENOSYS;
331
332    default:
333      return EINVAL;
334  }
335}
336
337/*PAGE
338 *
339 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
340 */
341
342int pthread_attr_getscope(
343  const pthread_attr_t  *attr,
344  int                   *contentionscope
345)
346{
347  if ( !attr || !attr->is_initialized )
348    return EINVAL;
349
350  *contentionscope = attr->contentionscope;
351  return 0;
352}
353
354/*PAGE
355 *
356 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
357 */
358
359int pthread_attr_setinheritsched(
360  pthread_attr_t  *attr,
361  int              inheritsched
362)
363{
364  if ( !attr || !attr->is_initialized )
365    return EINVAL;
366
367  switch ( inheritsched ) {
368    case PTHREAD_INHERIT_SCHED:
369    case PTHREAD_EXPLICIT_SCHED:
370      attr->inheritsched = inheritsched;
371      return 0;
372
373    default:
374      return EINVAL;
375  }
376}
377
378/*PAGE
379 *
380 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
381 */
382
383int pthread_attr_getinheritsched(
384  const pthread_attr_t  *attr,
385  int                   *inheritsched
386)
387{
388  if ( !attr || !attr->is_initialized )
389    return EINVAL;
390
391  *inheritsched = attr->inheritsched;
392  return 0;
393}
394
395/*PAGE
396 *
397 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
398 */
399
400int pthread_attr_setschedpolicy(
401  pthread_attr_t  *attr,
402  int              policy
403)
404{
405  if ( !attr || !attr->is_initialized )
406    return EINVAL;
407
408  switch ( policy ) {
409    case SCHED_OTHER:
410    case SCHED_FIFO:
411    case SCHED_RR:
412    case SCHED_SPORADIC:
413      attr->schedpolicy = policy;
414      return 0;
415 
416    default:
417      return EINVAL;
418  }
419}
420
421/*PAGE
422 *
423 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
424 */
425
426int pthread_attr_getschedpolicy(
427  const pthread_attr_t  *attr,
428  int                   *policy
429)
430{
431  if ( !attr || !attr->is_initialized )
432    return EINVAL;
433
434  *policy = attr->schedpolicy;
435  return 0;
436}
437
438/*PAGE
439 *
440 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
441 */
442
443int pthread_attr_setschedparam(
444  pthread_attr_t            *attr,
445  const struct sched_param  *param
446)
447{
448  if ( !attr || !attr->is_initialized )
449    return EINVAL;
450
451  attr->schedparam = *param;
452  return 0;
453}
454
455/*PAGE
456 *
457 *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
458 */
459
460int pthread_attr_getschedparam(
461  const pthread_attr_t   *attr,
462  struct sched_param     *param
463)
464{
465  if ( !attr || !attr->is_initialized )
466    return EINVAL;
467
468  *param = attr->schedparam;
469  return 0;
470}
471
472/*PAGE
473 *
474 *  13.5.2 Dynamic Thread Scheduling Parameters Access,
475 *         P1003.1c/Draft 10, p. 124
476 */
477
478int pthread_getschedparam(
479  pthread_t           thread,
480  int                *policy,
481  struct sched_param *param
482)
483{
484  Objects_Locations        location;
485  POSIX_API_Control       *api;
486  register Thread_Control *the_thread;
487
488  if ( !policy || !param  )
489    return EINVAL;
490
491  the_thread = _POSIX_Threads_Get( thread, &location );
492  switch ( location ) {
493    case OBJECTS_ERROR:
494    case OBJECTS_REMOTE:
495      return ESRCH;
496    case OBJECTS_LOCAL:
497      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
498      *policy = api->schedpolicy;
499      *param  = api->schedparam;
500      _Thread_Enable_dispatch();
501      return 0;
502  }
503 
504  return POSIX_BOTTOM_REACHED();
505
506}
507
508/*PAGE
509 *
510 *  13.5.2 Dynamic Thread Scheduling Parameters Access,
511 *         P1003.1c/Draft 10, p. 124
512 */
513
514int pthread_setschedparam(
515  pthread_t           thread,
516  int                 policy,
517  struct sched_param *param
518)
519{
520  register Thread_Control             *the_thread;
521  POSIX_API_Control                   *api;
522  Thread_CPU_budget_algorithms         budget_algorithm;
523  Thread_CPU_budget_algorithm_callout  budget_callout;
524  Objects_Locations                    location;
525 
526  /*
527   *  Check all the parameters
528   */
529
530  if ( !param )
531    return EINVAL;
532
533  if ( !_POSIX_Priority_Is_valid( param->sched_priority ) )
534    return EINVAL;
535
536  budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
537  budget_callout = NULL;
538
539  switch ( policy ) {
540    case SCHED_OTHER:
541      budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
542      break;
543 
544    case SCHED_FIFO:
545      budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
546      break;
547 
548    case SCHED_RR:
549      budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE;
550      break;
551 
552    case SCHED_SPORADIC:
553      budget_algorithm  = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
554      budget_callout = _POSIX_Threads_Sporadic_budget_callout;
555 
556      if ( _POSIX_Timespec_to_interval( &param->ss_replenish_period ) <
557           _POSIX_Timespec_to_interval( &param->ss_initial_budget ) )
558        return EINVAL;
559 
560      if ( !_POSIX_Priority_Is_valid( param->ss_low_priority ) )
561        return EINVAL;
562 
563      break;
564 
565    default:
566      return EINVAL;
567  }
568
569  /*
570   *  Actually change the scheduling policy and parameters
571   */
572
573  the_thread = _POSIX_Threads_Get( thread, &location );
574  switch ( location ) {
575    case OBJECTS_ERROR:
576    case OBJECTS_REMOTE:
577      return ESRCH;
578    case OBJECTS_LOCAL:
579      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
580
581      if ( api->schedpolicy == SCHED_SPORADIC )
582        (void) _Watchdog_Remove( &api->Sporadic_timer );
583
584      api->schedpolicy = policy;
585      api->schedparam  = *param;
586      the_thread->budget_algorithm = budget_algorithm;
587      the_thread->budget_callout   = budget_callout;
588
589      switch ( api->schedpolicy ) {
590        case SCHED_OTHER:
591        case SCHED_FIFO:
592        case SCHED_RR:
593          the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
594
595          _Thread_Change_priority(
596            the_thread,
597            _POSIX_Priority_To_core( api->schedparam.sched_priority )
598          );
599          break;
600 
601        case SCHED_SPORADIC:
602          _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread );
603          break;
604      }
605
606      _Thread_Enable_dispatch();
607      return 0;
608  }
609  return POSIX_BOTTOM_REACHED();
610}
611
612/*PAGE
613 *
614 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
615 */
616
617int pthread_attr_init(
618  pthread_attr_t  *attr
619)
620{
621  if ( !attr )
622    return EINVAL;
623 
624  *attr = _POSIX_Threads_Default_attributes;
625  return 0;
626}
627
628/*PAGE
629 *
630 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
631 */
632
633int pthread_attr_destroy(
634  pthread_attr_t  *attr
635)
636{
637  if ( !attr || !attr->is_initialized )
638    return EINVAL;
639 
640  attr->is_initialized = FALSE;
641  return 0;
642}
643 
644/*PAGE
645 *
646 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
647 */
648
649int pthread_attr_getstacksize(
650  const pthread_attr_t  *attr,
651  size_t                *stacksize
652)
653{
654  if ( !attr || !attr->is_initialized )
655    return EINVAL;
656
657  *stacksize = attr->stacksize;
658  return 0;
659}
660 
661/*PAGE
662 *
663 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
664 */
665
666int pthread_attr_setstacksize(
667  pthread_attr_t  *attr,
668  size_t           stacksize
669)
670{
671  if ( !attr || !attr->is_initialized )
672    return EINVAL;
673
674  if (stacksize < STACK_MINIMUM_SIZE)
675    attr->stacksize = STACK_MINIMUM_SIZE;
676  else
677    attr->stacksize = stacksize;
678  return 0;
679}
680 
681/*PAGE
682 *
683 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
684 */
685
686int pthread_attr_getstackaddr(
687  const pthread_attr_t   *attr,
688  void                  **stackaddr
689)
690{
691  if ( !attr || !attr->is_initialized )
692    return EINVAL;
693
694  *stackaddr = attr->stackaddr;
695  return 0;
696}
697 
698/*PAGE
699 *
700 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
701 */
702
703int pthread_attr_setstackaddr(
704  pthread_attr_t  *attr,
705  void            *stackaddr
706)
707{
708  if ( !attr || !attr->is_initialized )
709    return EINVAL;
710
711  attr->stackaddr = stackaddr;
712  return 0;
713}
714 
715/*PAGE
716 *
717 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
718 */
719
720int pthread_attr_getdetachstate(
721  const pthread_attr_t  *attr,
722  int                   *detachstate
723)
724{
725  if ( !attr || !attr->is_initialized )
726    return EINVAL;
727
728  *detachstate = attr->detachstate;
729  return 0;
730}
731 
732/*PAGE
733 *
734 *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
735 */
736
737int pthread_attr_setdetachstate(
738  pthread_attr_t  *attr,
739  int              detachstate
740)
741{
742  if ( !attr || !attr->is_initialized )
743    return EINVAL;
744
745  switch ( detachstate ) {
746    case PTHREAD_CREATE_DETACHED:
747    case PTHREAD_CREATE_JOINABLE:
748      attr->detachstate = detachstate;
749      return 0;
750 
751    default:
752      return EINVAL;
753  }
754}
755
756/*PAGE
757 *
758 *  16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
759 */
760
761int pthread_create(
762  pthread_t              *thread,
763  const pthread_attr_t   *attr,
764  void                 *(*start_routine)( void * ),
765  void                   *arg
766)
767{
768  const pthread_attr_t               *the_attr;
769  Priority_Control                    core_priority;
770  Thread_CPU_budget_algorithms        budget_algorithm;
771  Thread_CPU_budget_algorithm_callout budget_callout;
772  boolean                             is_fp;
773  boolean                             status;
774  Thread_Control                     *the_thread;
775  char                               *default_name = "psx";
776  POSIX_API_Control                  *api;
777  int                                 schedpolicy = SCHED_RR;
778  struct sched_param                  schedparam;
779
780  the_attr = (attr) ? attr : &_POSIX_Threads_Default_attributes;
781
782  if ( !the_attr->is_initialized )
783    return EINVAL;
784
785  /*
786   *  Core Thread Initialize insures we get the minimum amount of
787   *  stack space if it is allowed to allocate it itself.
788   */
789
790  if ( the_attr->stackaddr && !_Stack_Is_enough( the_attr->stacksize ) )
791    return EINVAL;
792
793#if 0
794  int  cputime_clock_allowed;  /* see time.h */
795  POSIX_NOT_IMPLEMENTED();
796#endif
797
798  /*
799   *  P1003.1c/Draft 10, p. 121.
800   *
801   *  If inheritsched is set to PTHREAD_INHERIT_SCHED, then this thread
802   *  inherits scheduling attributes from the creating thread.   If it is
803   *  PTHREAD_EXPLICIT_SCHED, then scheduling parameters come from the
804   *  attributes structure.
805   */
806
807  switch ( the_attr->inheritsched ) {
808    case PTHREAD_INHERIT_SCHED:
809      api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
810      schedpolicy = api->schedpolicy;
811      schedparam  = api->schedparam;
812      break;
813
814    case PTHREAD_EXPLICIT_SCHED:
815      schedpolicy = the_attr->schedpolicy;
816      schedparam  = the_attr->schedparam;
817      break;
818
819    default:
820      return EINVAL;
821  }
822
823  /*
824   *  Check the contentionscope since rtems only supports PROCESS wide
825   *  contention (i.e. no system wide contention).
826   */
827
828  if ( the_attr->contentionscope != PTHREAD_SCOPE_PROCESS )
829    return ENOSYS;
830
831  /*
832   *  Interpret the scheduling parameters.
833   */
834
835  if ( !_POSIX_Priority_Is_valid( schedparam.sched_priority ) )
836    return EINVAL;
837 
838  core_priority = _POSIX_Priority_To_core( schedparam.sched_priority );
839 
840  /*
841   *  Set the core scheduling policy information.
842   */
843
844  budget_callout = NULL;
845  budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
846
847  switch ( schedpolicy ) {
848    case SCHED_OTHER:
849      budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
850      break;
851     
852    case SCHED_FIFO:
853      budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
854      break;
855
856    case SCHED_RR:
857      budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE;
858      break;
859
860    case SCHED_SPORADIC:
861      budget_algorithm  = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
862      budget_callout = _POSIX_Threads_Sporadic_budget_callout;
863 
864      if ( _POSIX_Timespec_to_interval( &schedparam.ss_replenish_period ) <
865           _POSIX_Timespec_to_interval( &schedparam.ss_initial_budget ) )
866        return EINVAL;
867
868      if ( !_POSIX_Priority_Is_valid( schedparam.ss_low_priority ) )
869        return EINVAL;
870
871      break;
872
873    default:
874      return EINVAL;
875  }
876
877  /*
878   *  Currently all POSIX threads are floating point if the hardware
879   *  supports it.
880   */
881
882  is_fp = CPU_HARDWARE_FP;
883
884  /*
885   *  Disable dispatch for protection
886   */
887 
888  _Thread_Disable_dispatch();
889 
890  /*
891   *  Allocate the thread control block.
892   *
893   *  NOTE:  Global threads are not currently supported.
894   */
895
896  the_thread = _POSIX_Threads_Allocate();
897
898  if ( !the_thread ) {
899    _Thread_Enable_dispatch();
900    return EINVAL;
901  }
902
903  /*
904   *  Initialize the core thread for this task.
905   */
906 
907  status = _Thread_Initialize(
908    &_POSIX_Threads_Information,
909    the_thread,
910    the_attr->stackaddr,
911    the_attr->stacksize,
912    is_fp,
913    core_priority,
914    TRUE,                 /* preemptible */
915    budget_algorithm,
916    budget_callout,
917    0,                    /* isr level */
918    &default_name         /* posix threads don't have a name */
919  );
920 
921  if ( !status ) {
922    _POSIX_Threads_Free( the_thread );
923    _Thread_Enable_dispatch();
924    return EINVAL;
925  }
926
927  /*
928   *  finish initializing the per API structure
929   */
930
931 
932  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
933
934  api->Attributes  = *the_attr;
935  api->detachstate = attr->detachstate;
936  api->schedpolicy = schedpolicy;
937  api->schedparam  = schedparam;
938
939  /*
940   *  POSIX threads are allocated and started in one operation.
941   */
942
943  status = _Thread_Start(
944    the_thread,
945    THREAD_START_POINTER,
946    start_routine,
947    arg,
948    0                     /* unused */
949  );
950
951  if ( schedpolicy == SCHED_SPORADIC ) {
952    _Watchdog_Insert_ticks(
953      &api->Sporadic_timer,
954      _POSIX_Timespec_to_interval( &api->schedparam.ss_replenish_period )
955    );
956  }
957
958  /*
959   *  _Thread_Start only fails if the thread was in the incorrect state
960   */
961
962  if ( !status ) {
963    _POSIX_Threads_Free( the_thread );
964    _Thread_Enable_dispatch();
965    return EINVAL;
966  }
967
968  /*
969   *  Return the id and indicate we successfully created the thread
970   */
971
972  *thread = the_thread->Object.id;
973
974 _Thread_Enable_dispatch();
975
976 return 0;
977}
978
979/*PAGE
980 *
981 *  16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147
982 */
983
984int pthread_join(
985  pthread_t   thread,
986  void      **value_ptr
987)
988{
989  register Thread_Control *the_thread;
990  POSIX_API_Control       *api;
991  Objects_Locations        location;
992
993  the_thread = _POSIX_Threads_Get( thread, &location );
994  switch ( location ) {
995    case OBJECTS_ERROR:
996    case OBJECTS_REMOTE:
997      return ESRCH;
998    case OBJECTS_LOCAL:
999      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
1000
1001      if ( api->detachstate == PTHREAD_CREATE_DETACHED ) {
1002        _Thread_Enable_dispatch();
1003        return EINVAL;
1004      }
1005
1006      if ( _Thread_Is_executing( the_thread ) ) {
1007        _Thread_Enable_dispatch();
1008        return EDEADLK;
1009      }
1010
1011      /*
1012       *  Put ourself on the threads join list
1013       */
1014
1015      _Thread_Executing->Wait.return_argument = (unsigned32 *) value_ptr;
1016
1017      _Thread_queue_Enter_critical_section( &api->Join_List );
1018
1019      _Thread_queue_Enqueue( &api->Join_List, WATCHDOG_NO_TIMEOUT );
1020
1021      _Thread_Enable_dispatch();
1022
1023      return 0;
1024  }
1025
1026  return POSIX_BOTTOM_REACHED();
1027}
1028
1029/*PAGE
1030 *
1031 *  16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149
1032 */
1033
1034int pthread_detach(
1035  pthread_t   thread
1036)
1037{
1038  register Thread_Control *the_thread;
1039  POSIX_API_Control       *api;
1040  Objects_Locations        location;
1041 
1042  the_thread = _POSIX_Threads_Get( thread, &location );
1043  switch ( location ) {
1044    case OBJECTS_ERROR:
1045    case OBJECTS_REMOTE:
1046      return ESRCH;
1047    case OBJECTS_LOCAL:
1048
1049      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
1050      api->detachstate = PTHREAD_CREATE_DETACHED;
1051      _Thread_Enable_dispatch();
1052      return 0;
1053  }
1054 
1055  return POSIX_BOTTOM_REACHED();
1056}
1057
1058/*PAGE
1059 *
1060 *  16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150
1061 *
1062 *  NOTE: Key destructors are executed in the POSIX api delete extension.
1063 */
1064 
1065void pthread_exit(
1066  void  *value_ptr
1067)
1068{
1069  _Thread_Disable_dispatch();
1070
1071  _Thread_Executing->Wait.return_argument = (unsigned32 *)value_ptr;
1072
1073  _Thread_Close( &_POSIX_Threads_Information, _Thread_Executing );
1074
1075  _POSIX_Threads_Free( _Thread_Executing );
1076
1077  _Thread_Enable_dispatch();
1078}
1079
1080/*PAGE
1081 *
1082 *  16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. 152
1083 */
1084
1085pthread_t pthread_self( void )
1086{
1087  return _Thread_Executing->Object.id;
1088}
1089
1090/*PAGE
1091 *
1092 *  16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153
1093 *
1094 *  NOTE:  POSIX does not define the behavior when either thread id is invalid.
1095 */
1096
1097int pthread_equal(
1098  pthread_t  t1,
1099  pthread_t  t2
1100)
1101{
1102  /*
1103   *  If the system is configured for debug, then we will do everything we
1104   *  can to insure that both ids are valid.  Otherwise, we will do the
1105   *  cheapest possible thing to determine if they are equal.
1106   */
1107
1108#ifndef RTEMS_DEBUG
1109  return _Objects_Are_ids_equal( t1, t2 );
1110#else
1111  int               status;
1112  Objects_Locations location;
1113
1114  /*
1115   *  By default this is not a match.
1116   */
1117
1118  status = 0;
1119
1120  /*
1121   *  Validate the first id and return 0 if it is not valid
1122   */
1123
1124  (void) _POSIX_Threads_Get( t1, &location );
1125  switch ( location ) {
1126    case OBJECTS_ERROR:
1127    case OBJECTS_REMOTE:
1128      break;
1129
1130    case OBJECTS_LOCAL:
1131
1132      /*
1133       *  Validate the second id and return 0 if it is not valid
1134       */
1135
1136      (void) _POSIX_Threads_Get( t2, &location );
1137      switch ( location ) {
1138        case OBJECTS_ERROR:
1139        case OBJECTS_REMOTE:
1140          break;
1141        case OBJECTS_LOCAL:
1142          status = _Objects_Are_ids_equal( t1, t2 );
1143          break;
1144      }
1145      _Thread_Unnest_dispatch();
1146      break;
1147  }
1148
1149  _Thread_Enable_dispatch();
1150  return status;
1151#endif
1152}
1153
1154/*PAGE
1155 *
1156 *  16.1.8 Dynamic Package Initialization, P1003.1c/Draft 10, p. 154
1157 */
1158
1159int pthread_once(
1160  pthread_once_t  *once_control,
1161  void           (*init_routine)(void)
1162)
1163{
1164  if ( !once_control || !init_routine )
1165    return EINVAL;
1166
1167  _Thread_Disable_dispatch();
1168
1169  if ( !once_control->init_executed ) {
1170    once_control->is_initialized = TRUE;
1171    once_control->init_executed = TRUE;
1172    (*init_routine)();
1173  }
1174 
1175  _Thread_Enable_dispatch();
1176  return 0;
1177}
1178
1179/*PAGE
1180 *
1181 *  20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/Draft 8, p. 58
1182 */
1183 
1184int pthread_getcpuclockid(
1185  pthread_t    pid,
1186  clockid_t   *clock_id
1187)
1188{
1189  return POSIX_NOT_IMPLEMENTED();
1190}
1191
1192/*PAGE
1193 *
1194 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/Draft 8, p. 59
1195 */
1196
1197int pthread_attr_setcputime(
1198  pthread_attr_t  *attr,
1199  int              clock_allowed
1200)
1201{
1202  if ( !attr || !attr->is_initialized )
1203    return EINVAL;
1204
1205  switch ( clock_allowed ) {
1206    case CLOCK_ENABLED:
1207    case CLOCK_DISABLED:
1208      attr->cputime_clock_allowed = clock_allowed;
1209      return 0;
1210 
1211    default:
1212      return EINVAL;
1213  }
1214}
1215
1216/*PAGE
1217 *
1218 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/Draft 8, p. 59
1219 */
1220
1221int pthread_attr_getcputime(
1222  pthread_attr_t  *attr,
1223  int             *clock_allowed
1224)
1225{
1226  if ( !attr || !attr->is_initialized )
1227    return EINVAL;
1228
1229  *clock_allowed = attr->cputime_clock_allowed;
1230  return 0;
1231}
Note: See TracBrowser for help on using the repository browser.