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

4.104.114.84.95
Last change on this file since b85649c4 was b85649c4, checked in by Joel Sherrill <joel.sherrill@…>, on 06/13/96 at 16:42:21

basic test cases for kill() and alarm().

kill() in particular needs more test cases for full coverage. The search
for a thread interested in this signal has a lot of paths.

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