source: rtems/cpukit/posix/src/pthread.c @ 65a5c1b

4.104.114.84.95
Last change on this file since 65a5c1b was 65a5c1b, checked in by Joel Sherrill <joel.sherrill@…>, on 06/06/96 at 15:32:49

completed pthread_setschedparam.

  • Property mode set to 100644
File size: 25.6 KB
RevLine 
[8165b48f]1/*
[eb5a7e07]2 *  $Id$
[5e9b32b]3 */
4
[613cff6]5#include <assert.h>
[5e9b32b]6#include <errno.h>
7#include <pthread.h>
8#include <limits.h>
9
[f4719d5a]10#include <rtems/system.h>
[5a18e04]11#include <rtems/score/apiext.h>
[5e9b32b]12#include <rtems/score/stack.h>
13#include <rtems/score/thread.h>
[5a18e04]14#include <rtems/score/userext.h>
15#include <rtems/score/wkspace.h>
[5e9b32b]16#include <rtems/posix/pthread.h>
[ece8c9a]17#include <rtems/posix/priority.h>
[5a18e04]18#include <rtems/posix/config.h>
[624133c]19#include <rtems/posix/time.h>
[5e9b32b]20
21/*PAGE
22 *
23 *  The default pthreads attributes structure.
24 */
25 
26const pthread_attr_t _POSIX_Threads_Default_attributes = {
27  TRUE,                    /* is_initialized */
[9b4e549]28  NULL,                    /* stackaddr */
[5e9b32b]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  },
[9b4e549]39  PTHREAD_CREATE_JOINABLE, /* detachstate */
[5e9b32b]40  1                        /* cputime_clock_allowed */
41};
42
[65a5c1b]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
[5a18e04]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;
[c238a218]138
139  /* XXX run _POSIX_Keys_Run_destructors here? */
[5a18e04]140}
141
142/*PAGE
143 *
[dd32d883]144 *  _POSIX_Threads_Initialize_user_threads
[5a18e04]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 
[dd32d883]154void _POSIX_Threads_Initialize_user_threads( void )
[5a18e04]155{
[dd32d883]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;
[613cff6]164
[dd32d883]165  if ( !user_threads || maximum == 0 )
[613cff6]166    return;
[5a18e04]167 
168  for ( index=0 ; index < maximum ; index++ ) {
[dd32d883]169    status = pthread_create(
170      &thread_id,
171      NULL,
172      user_threads[ index ].entry,
173      NULL
174    );
[613cff6]175    assert( !status );
[5a18e04]176  }
177}
178
179API_extensions_Control _POSIX_Threads_API_extensions = {
180  { NULL, NULL },
181  NULL,                                     /* predriver */
[dd32d883]182  _POSIX_Threads_Initialize_user_threads,   /* postdriver */
[5a18e04]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 
[5e9b32b]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(
[dd32d883]212  unsigned32                          maximum_pthreads,
213  unsigned32                          number_of_initialization_threads,
214  posix_initialization_threads_table *user_threads
[5a18e04]215 
[5e9b32b]216)
217{
[dd32d883]218  _POSIX_Threads_Number_of_initialization_threads =
219                                           number_of_initialization_threads;
220  _POSIX_Threads_User_initialization_threads = user_threads;
[5a18e04]221
[974ff40]222  /*
223   *  There may not be any POSIX initialization threads configured.
224   */
225
226#if 0
[dd32d883]227  if ( user_threads == NULL || number_of_initialization_threads == 0 )
[5a18e04]228    _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
[974ff40]229#endif
[5a18e04]230
[5e9b32b]231  _Objects_Initialize_information(
232    &_POSIX_Threads_Information,
233    OBJECTS_POSIX_THREADS,
[ece8c9a]234    FALSE,                               /* does not support global */
[5e9b32b]235    maximum_pthreads,
[e811d68]236    sizeof( Thread_Control ),
[5e9b32b]237    TRUE,
[ece8c9a]238    5,                                   /* length is arbitrary for now */
239    TRUE                                 /* this class is threads */
[5e9b32b]240  );
[5a18e04]241
[613cff6]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 
[5e9b32b]255}
256
257/*PAGE
258 *
259 *  3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
[568ebf3]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."
[5e9b32b]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
[e72d995a]282  switch ( contentionscope ) {
283    case PTHREAD_SCOPE_PROCESS:
[c238a218]284      attr->contentionscope = contentionscope;
285      return 0;
286
[2c207d1f]287    case PTHREAD_SCOPE_SYSTEM:
288      return ENOSYS;
289
[e72d995a]290    default:
291      return EINVAL;
292  }
[5e9b32b]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
[e72d995a]325  switch ( inheritsched ) {
326    case PTHREAD_INHERIT_SCHED:
327    case PTHREAD_EXPLICIT_SCHED:
[c238a218]328      attr->inheritsched = inheritsched;
329      return 0;
330
[e72d995a]331    default:
332      return EINVAL;
333  }
[5e9b32b]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
[c238a218]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  }
[5e9b32b]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,
[f4719d5a]403  const struct sched_param  *param
[5e9b32b]404)
405{
406  if ( !attr || !attr->is_initialized )
407    return EINVAL;
408
[f4719d5a]409  attr->schedparam = *param;
[5e9b32b]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{
[56bd4a36]442  Objects_Locations        location;
443  POSIX_API_Control       *api;
444  register Thread_Control *the_thread;
[5e9b32b]445
446  if ( !policy || !param  )
447    return EINVAL;
448
[56bd4a36]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;
[9b4e549]457      *param  = api->schedparam;
[56bd4a36]458      _Thread_Enable_dispatch();
459      return 0;
460  }
461 
462  return POSIX_BOTTOM_REACHED();
463
[5e9b32b]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{
[65a5c1b]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;
[230a0dcb]483 
[65a5c1b]484  /*
485   *  Check all the parameters
486   */
487
[5e9b32b]488  if ( !param )
489    return EINVAL;
490
[65a5c1b]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   */
[230a0dcb]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:
[65a5c1b]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 ) {
[230a0dcb]548        case SCHED_OTHER:
549        case SCHED_FIFO:
550        case SCHED_RR:
[65a5c1b]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          );
[230a0dcb]557          break;
558 
[65a5c1b]559        case SCHED_SPORADIC:
560          _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread );
561          break;
[230a0dcb]562      }
563
[56bd4a36]564      _Thread_Enable_dispatch();
[c238a218]565      return 0;
566  }
[230a0dcb]567  return POSIX_BOTTOM_REACHED();
[5e9b32b]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
[c238a218]632  if (stacksize < STACK_MINIMUM_SIZE)
[9c877c0d]633    attr->stacksize = STACK_MINIMUM_SIZE;
634  else
635    attr->stacksize = stacksize;
[5e9b32b]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
[c238a218]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  }
[5e9b32b]712}
713
714/*PAGE
715 *
716 *  16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
717 */
718
719int pthread_create(
[974ff40]720  pthread_t              *thread,
721  const pthread_attr_t   *attr,
722  void                 *(*start_routine)( void * ),
723  void                   *arg
[5e9b32b]724)
725{
[624133c]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;
[5a18e04]737
[6b067c4]738  the_attr = (attr) ? attr : &_POSIX_Threads_Default_attributes;
[5a18e04]739
[6b067c4]740  if ( !the_attr->is_initialized )
[5a18e04]741    return EINVAL;
742
743  /*
744   *  Core Thread Initialize insures we get the minimum amount of
[9b4e549]745   *  stack space if it is allowed to allocate it itself.
[5a18e04]746   */
747
[9b4e549]748  if ( the_attr->stackaddr && !_Stack_Is_enough( the_attr->stacksize ) )
749    return EINVAL;
750
[5a18e04]751#if 0
752  int  cputime_clock_allowed;  /* see time.h */
[624133c]753  POSIX_NOT_IMPLEMENTED();
[5a18e04]754#endif
[974ff40]755
[e72d995a]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
[6b067c4]765  switch ( the_attr->inheritsched ) {
[e72d995a]766    case PTHREAD_INHERIT_SCHED:
[c48e0ee]767      api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
768      schedpolicy = api->schedpolicy;
[9b4e549]769      schedparam  = api->schedparam;
[e72d995a]770      break;
[9b4e549]771
[e72d995a]772    case PTHREAD_EXPLICIT_SCHED:
[6b067c4]773      schedpolicy = the_attr->schedpolicy;
[9b4e549]774      schedparam  = the_attr->schedparam;
[e72d995a]775      break;
[9b4e549]776
777    default:
778      return EINVAL;
[e72d995a]779  }
780
[2c207d1f]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
[ece8c9a]789  /*
[c48e0ee]790   *  Interpret the scheduling parameters.
[ece8c9a]791   */
[c48e0ee]792
[624133c]793  if ( !_POSIX_Priority_Is_valid( schedparam.sched_priority ) )
[ece8c9a]794    return EINVAL;
795 
[624133c]796  core_priority = _POSIX_Priority_To_core( schedparam.sched_priority );
[ece8c9a]797 
[624133c]798  /*
799   *  Set the core scheduling policy information.
800   */
801
802  budget_callout = NULL;
803  budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
804
[c48e0ee]805  switch ( schedpolicy ) {
806    case SCHED_OTHER:
[624133c]807      budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
808      break;
809     
[c48e0ee]810    case SCHED_FIFO:
[624133c]811      budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
[c48e0ee]812      break;
[624133c]813
[c48e0ee]814    case SCHED_RR:
[624133c]815      budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE;
[c48e0ee]816      break;
[624133c]817
[c48e0ee]818    case SCHED_SPORADIC:
[624133c]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
[c48e0ee]829      break;
[65a5c1b]830
831    default:
832      return EINVAL;
[c48e0ee]833  }
834
[ece8c9a]835  /*
[7f72217e]836   *  Currently all POSIX threads are floating point if the hardware
837   *  supports it.
[ece8c9a]838   */
839
[7f72217e]840  is_fp = CPU_HARDWARE_FP;
[ece8c9a]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,
[6b067c4]868    the_attr->stackaddr,
869    the_attr->stacksize,
[ece8c9a]870    is_fp,
871    core_priority,
872    TRUE,                 /* preemptible */
[624133c]873    budget_algorithm,
874    budget_callout,
[ece8c9a]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
[e811d68]885  /*
886   *  finish initializing the per API structure
887   */
888
889 
890  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
891
[9b4e549]892  api->Attributes  = *the_attr;
[e811d68]893  api->detachstate = attr->detachstate;
[9b4e549]894  api->schedpolicy = schedpolicy;
895  api->schedparam  = schedparam;
[e811d68]896
[8f857992]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
[9b4e549]906  /*
907   *  POSIX threads are allocated and started in one operation.
908   */
909
[cfcfdf0]910  status = _Thread_Start(
911    the_thread,
912    THREAD_START_POINTER,
913    start_routine,
914    arg,
915    0                     /* unused */
916  );
917
[624133c]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
[cfcfdf0]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
[ece8c9a]946  *thread = the_thread->Object.id;
947
948 _Thread_Enable_dispatch();
949
950 return 0;
[5e9b32b]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{
[e811d68]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
[230a0dcb]975      if ( api->detachstate == PTHREAD_CREATE_DETACHED ) {
976        _Thread_Enable_dispatch();
[e811d68]977        return EINVAL;
[230a0dcb]978      }
[e811d68]979
[8f857992]980      /*
981       *  Put ourself on the threads join list
982       */
[e811d68]983
[8f857992]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
[56bd4a36]990      _Thread_Enable_dispatch();
991
[8f857992]992      return 0;
[e811d68]993  }
994
995  return POSIX_BOTTOM_REACHED();
[5e9b32b]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{
[e811d68]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;
[230a0dcb]1020      _Thread_Enable_dispatch();
[e811d68]1021      return 0;
1022  }
1023 
1024  return POSIX_BOTTOM_REACHED();
[5e9b32b]1025}
1026
[974ff40]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{
[8f857992]1036  register Thread_Control *executing;
[cfcfdf0]1037  register Thread_Control *the_thread;
[8f857992]1038  POSIX_API_Control       *api;
[cfcfdf0]1039
[8f857992]1040  executing = _Thread_Executing;
[cfcfdf0]1041
1042  _Thread_Disable_dispatch();
1043
[8f857992]1044  _Thread_Close( &_POSIX_Threads_Information, executing );
1045
[cfcfdf0]1046  /*
[8f857992]1047   *  Wakeup all the tasks which joined with this one
[cfcfdf0]1048   */
1049
[8f857992]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
[65a5c1b]1055  if ( api->schedpolicy == SCHED_SPORADIC )
1056    (void) _Watchdog_Remove( &api->Sporadic_timer );
1057
[c238a218]1058  /* XXX run _POSIX_Keys_Run_destructors here? */
1059
[8f857992]1060  _POSIX_Threads_Free( executing );
[cfcfdf0]1061
1062  _Thread_Enable_dispatch();
[974ff40]1063}
[5e9b32b]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
[65a5c1b]1078 *
1079 *  NOTE:  POSIX does not define the behavior when either thread id is invalid.
[5e9b32b]1080 */
1081
1082int pthread_equal(
1083  pthread_t  t1,
1084  pthread_t  t2
1085)
1086{
[230a0dcb]1087  int               status;
1088  Objects_Locations location;
[e811d68]1089
1090  /*
[230a0dcb]1091   *  By default this is not a match.
[e811d68]1092   */
1093
[230a0dcb]1094  status = 0;
[e811d68]1095
1096  /*
[230a0dcb]1097   *  Validate the first id and return 0 if it is not valid
[e811d68]1098   */
1099
[230a0dcb]1100  (void) _POSIX_Threads_Get( t1, &location );
[e811d68]1101  switch ( location ) {
1102    case OBJECTS_ERROR:
1103    case OBJECTS_REMOTE:
[230a0dcb]1104      break;
1105
[e811d68]1106    case OBJECTS_LOCAL:
[230a0dcb]1107
1108      /*
1109       *  Validate the second id and return 0 if it is not valid
1110       */
1111
1112      (void) _POSIX_Threads_Get( t2, &location );
1113      switch ( location ) {
1114        case OBJECTS_ERROR:
1115        case OBJECTS_REMOTE:
1116          break;
1117        case OBJECTS_LOCAL:
1118          status = _Objects_Are_ids_equal( t1, t2 );
1119          break;
1120      }
1121      _Thread_Unnest_dispatch();
[8f857992]1122      break;
[e811d68]1123  }
[230a0dcb]1124
1125  _Thread_Enable_dispatch();
1126  return status;
[5e9b32b]1127}
1128
1129/*PAGE
1130 *
1131 *  16.1.8 Dynamic Package Initialization
1132 */
1133
1134int pthread_once(
1135  pthread_once_t  *once_control,
1136  void           (*init_routine)(void)
1137)
1138{
1139  /* XXX: Should we implement this routine this way or make it a full */
1140  /* XXX: fledged object? */
1141
1142  if ( !once_control || !init_routine )
1143    return EINVAL;
1144
1145  _Thread_Disable_dispatch();
1146
1147  if ( !once_control->is_initialized ) {
1148
1149    once_control->is_initialized = TRUE;
1150    once_control->init_executed = TRUE;
1151    (*init_routine)();
1152
1153  } if ( !once_control->init_executed ) {
1154
1155    once_control->init_executed = TRUE;
1156    (*init_routine)();
1157
1158  }
1159 
1160  _Thread_Enable_dispatch();
1161  return 0;
1162}
1163
1164/*PAGE
1165 *
1166 *  20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/D8, p. 58
1167 */
1168 
1169int pthread_getcpuclockid(
1170  pthread_t    pid,
1171  clockid_t   *clock_id
1172)
1173{
1174  return POSIX_NOT_IMPLEMENTED();
1175}
1176
1177/*PAGE
1178 *
1179 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
1180 */
1181
1182int pthread_attr_setcputime(
1183  pthread_attr_t  *attr,
1184  int              clock_allowed
1185)
1186{
1187  if ( !attr || !attr->is_initialized )
1188    return EINVAL;
1189
[c238a218]1190  switch ( clock_allowed ) {
1191    case CLOCK_ENABLED:
1192    case CLOCK_DISABLED:
1193      attr->cputime_clock_allowed = clock_allowed;
1194      return 0;
1195 
1196    default:
1197      return EINVAL;
1198  }
[5e9b32b]1199}
1200
1201/*PAGE
1202 *
1203 *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/D8, p. 59
1204 */
1205
1206int pthread_attr_getcputime(
1207  pthread_attr_t  *attr,
1208  int             *clock_allowed
1209)
1210{
1211  if ( !attr || !attr->is_initialized )
1212    return EINVAL;
1213
1214  *clock_allowed = attr->cputime_clock_allowed;
1215  return 0;
1216}
Note: See TracBrowser for help on using the repository browser.