source: rtems/c/src/exec/posix/src/pthread.c @ 0207c55

4.104.114.84.95
Last change on this file since 0207c55 was 0207c55, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 6, 1996 at 3:36:18 PM

Made the implementation of pthread_equal conditional on RTEMS_DEBUG. If
RTEMS is built for debug, then every possible effort is made to validate
the two ids. Otherwise, a simple comparison is performed.

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