Changeset 03598b1 in rtems


Ignore:
Timestamp:
01/25/99 23:20:52 (25 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
39c9723
Parents:
535db3ae
Message:

Split most of POSIX Threads Manager into multiple files.

Files:
56 added
5 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/posix/src/Makefile.in

    r535db3ae r03598b1  
    1616    pthreadatfork wait waitpid
    1717
    18 C_PIECES= adasupp cond getpid key mutex pthread psignal sched time \
     18PTHREAD_PIECES=\
     19  pthread pthreadsetcputime pthreadgetcputime pthreadgetcpuclockid \
     20  pthreadonce pthreadequal pthreadself pthreadexit pthreaddetach \
     21  pthreadjoin pthreadcreate \
     22  pthreadattrsetdetachstate pthreadattrgetdetachstate \
     23  pthreadattrgetstackaddr pthreadattrsetstackaddr \
     24  pthreadattrgetstacksize pthreadattrsetstacksize \
     25  pthreadattrinit pthreadattrdestroy \
     26  pthreadsetschedparam pthreadgetschedparam \
     27  pthreadattrsetschedparam pthreadattrgetschedparam \
     28  pthreadattrgetschedpolicy pthreadattrsetschedpolicy \
     29  pthreadattrgetinheritsched pthreadattrsetinheritsched \
     30  pthreadattrgetscope pthreadattrsetscope
     31
     32C_PIECES= adasupp cond getpid key mutex $(PTHREAD_PIECES) psignal sched time \
    1933  types unistd $(ENOSYS_C_PIECES)
    2034C_FILES=$(C_PIECES:%=%.c)
  • c/src/exec/posix/src/pthread.c

    r535db3ae r03598b1  
    355355 
    356356}
    357 
    358 /*PAGE
    359  *
    360  *  3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
    361  *
    362  *  RTEMS does not support processes, so we fall under this and do not
    363  *  provide this routine:
    364  *
    365  *  "Either the implementation shall support the pthread_atfork() function
    366  *   as described above or the pthread_atfork() funciton shall not be
    367  *   provided."
    368  */
    369 
    370 /*PAGE
    371  *
    372  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    373  */
    374 
    375 int pthread_attr_setscope(
    376   pthread_attr_t  *attr,
    377   int              contentionscope
    378 )
    379 {
    380   if ( !attr || !attr->is_initialized )
    381     return EINVAL;
    382 
    383   switch ( contentionscope ) {
    384     case PTHREAD_SCOPE_PROCESS:
    385       attr->contentionscope = contentionscope;
    386       return 0;
    387 
    388     case PTHREAD_SCOPE_SYSTEM:
    389       return ENOTSUP;
    390 
    391     default:
    392       return EINVAL;
    393   }
    394 }
    395 
    396 /*PAGE
    397  *
    398  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    399  */
    400 
    401 int pthread_attr_getscope(
    402   const pthread_attr_t  *attr,
    403   int                   *contentionscope
    404 )
    405 {
    406   if ( !attr || !attr->is_initialized || !contentionscope )
    407     return EINVAL;
    408 
    409   *contentionscope = attr->contentionscope;
    410   return 0;
    411 }
    412 
    413 /*PAGE
    414  *
    415  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    416  */
    417 
    418 int pthread_attr_setinheritsched(
    419   pthread_attr_t  *attr,
    420   int              inheritsched
    421 )
    422 {
    423   if ( !attr || !attr->is_initialized )
    424     return EINVAL;
    425 
    426   switch ( inheritsched ) {
    427     case PTHREAD_INHERIT_SCHED:
    428     case PTHREAD_EXPLICIT_SCHED:
    429       attr->inheritsched = inheritsched;
    430       return 0;
    431 
    432     default:
    433       return ENOTSUP;
    434   }
    435 }
    436 
    437 /*PAGE
    438  *
    439  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    440  */
    441 
    442 int pthread_attr_getinheritsched(
    443   const pthread_attr_t  *attr,
    444   int                   *inheritsched
    445 )
    446 {
    447   if ( !attr || !attr->is_initialized || !inheritsched )
    448     return EINVAL;
    449 
    450   *inheritsched = attr->inheritsched;
    451   return 0;
    452 }
    453 
    454 /*PAGE
    455  *
    456  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    457  */
    458 
    459 int pthread_attr_setschedpolicy(
    460   pthread_attr_t  *attr,
    461   int              policy
    462 )
    463 {
    464   if ( !attr || !attr->is_initialized )
    465     return EINVAL;
    466 
    467   switch ( policy ) {
    468     case SCHED_OTHER:
    469     case SCHED_FIFO:
    470     case SCHED_RR:
    471     case SCHED_SPORADIC:
    472       attr->schedpolicy = policy;
    473       return 0;
    474  
    475     default:
    476       return ENOTSUP;
    477   }
    478 }
    479 
    480 /*PAGE
    481  *
    482  *  13.5.1 Thread Creation Scheduling Parameters, P1003.1c/Draft 10, p. 120
    483  */
    484 
    485 int pthread_attr_getschedpolicy(
    486   const pthread_attr_t  *attr,
    487   int                   *policy
    488 )
    489 {
    490   if ( !attr || !attr->is_initialized || !policy )
    491     return EINVAL;
    492 
    493   *policy = attr->schedpolicy;
    494   return 0;
    495 }
    496 
    497 /*PAGE
    498  *
    499  *  13.5.1 Thread Creation Scheduling Parameters, P1003.1c/Draft 10, p. 120
    500  */
    501 
    502 int pthread_attr_setschedparam(
    503   pthread_attr_t           *attr,
    504   const struct sched_param *param
    505 )
    506 {
    507   if ( !attr || !attr->is_initialized || !param )
    508     return EINVAL;
    509 
    510   attr->schedparam = *param;
    511   return 0;
    512 }
    513 
    514 /*PAGE
    515  *
    516  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    517  */
    518 
    519 int pthread_attr_getschedparam(
    520   const pthread_attr_t   *attr,
    521   struct sched_param     *param
    522 )
    523 {
    524   if ( !attr || !attr->is_initialized || !param )
    525     return EINVAL;
    526 
    527   *param = attr->schedparam;
    528   return 0;
    529 }
    530 
    531 /*PAGE
    532  *
    533  *  13.5.2 Dynamic Thread Scheduling Parameters Access,
    534  *         P1003.1c/Draft 10, p. 124
    535  */
    536 
    537 int pthread_getschedparam(
    538   pthread_t           thread,
    539   int                *policy,
    540   struct sched_param *param
    541 )
    542 {
    543   Objects_Locations        location;
    544   POSIX_API_Control       *api;
    545   register Thread_Control *the_thread;
    546 
    547   if ( !policy || !param  )
    548     return EINVAL;
    549 
    550   the_thread = _POSIX_Threads_Get( thread, &location );
    551   switch ( location ) {
    552     case OBJECTS_ERROR:
    553     case OBJECTS_REMOTE:
    554       return ESRCH;
    555     case OBJECTS_LOCAL:
    556       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    557       *policy = api->schedpolicy;
    558       *param  = api->schedparam;
    559       param->sched_priority =
    560         _POSIX_Priority_From_core( the_thread->current_priority );
    561       _Thread_Enable_dispatch();
    562       return 0;
    563   }
    564  
    565   return POSIX_BOTTOM_REACHED();
    566 
    567 }
    568 
    569 /*PAGE
    570  *
    571  *  13.5.2 Dynamic Thread Scheduling Parameters Access,
    572  *         P1003.1c/Draft 10, p. 124
    573  */
    574 
    575 int pthread_setschedparam(
    576   pthread_t           thread,
    577   int                 policy,
    578   struct sched_param *param
    579 )
    580 {
    581   register Thread_Control             *the_thread;
    582   POSIX_API_Control                   *api;
    583   Thread_CPU_budget_algorithms         budget_algorithm;
    584   Thread_CPU_budget_algorithm_callout  budget_callout;
    585   Objects_Locations                    location;
    586  
    587   /*
    588    *  Check all the parameters
    589    */
    590 
    591   if ( !param )
    592     return EINVAL;
    593 
    594   if ( !_POSIX_Priority_Is_valid( param->sched_priority ) )
    595     return EINVAL;
    596 
    597   budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    598   budget_callout = NULL;
    599 
    600   switch ( policy ) {
    601     case SCHED_OTHER:
    602       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
    603       break;
    604  
    605     case SCHED_FIFO:
    606       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    607       break;
    608  
    609     case SCHED_RR:
    610       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE;
    611       break;
    612  
    613     case SCHED_SPORADIC:
    614       budget_algorithm  = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
    615       budget_callout = _POSIX_Threads_Sporadic_budget_callout;
    616  
    617       if ( _POSIX_Timespec_to_interval( &param->ss_replenish_period ) <
    618            _POSIX_Timespec_to_interval( &param->ss_initial_budget ) )
    619         return EINVAL;
    620  
    621       if ( !_POSIX_Priority_Is_valid( param->ss_low_priority ) )
    622         return EINVAL;
    623  
    624       break;
    625  
    626     default:
    627       return EINVAL;
    628   }
    629 
    630   /*
    631    *  Actually change the scheduling policy and parameters
    632    */
    633 
    634   the_thread = _POSIX_Threads_Get( thread, &location );
    635   switch ( location ) {
    636     case OBJECTS_ERROR:
    637     case OBJECTS_REMOTE:
    638       return ESRCH;
    639     case OBJECTS_LOCAL:
    640       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    641 
    642       if ( api->schedpolicy == SCHED_SPORADIC )
    643         (void) _Watchdog_Remove( &api->Sporadic_timer );
    644 
    645       api->schedpolicy = policy;
    646       api->schedparam  = *param;
    647       the_thread->budget_algorithm = budget_algorithm;
    648       the_thread->budget_callout   = budget_callout;
    649 
    650       switch ( api->schedpolicy ) {
    651         case SCHED_OTHER:
    652         case SCHED_FIFO:
    653         case SCHED_RR:
    654           the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
    655 
    656           the_thread->real_priority =
    657             _POSIX_Priority_To_core( api->schedparam.sched_priority );
    658 
    659           _Thread_Change_priority(
    660              the_thread,
    661              the_thread->real_priority,
    662              TRUE
    663           );
    664           break;
    665  
    666         case SCHED_SPORADIC:
    667           api->ss_high_priority = api->schedparam.sched_priority;
    668           _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread );
    669           break;
    670       }
    671 
    672       _Thread_Enable_dispatch();
    673       return 0;
    674   }
    675   return POSIX_BOTTOM_REACHED();
    676 }
    677 
    678 /*PAGE
    679  *
    680  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    681  */
    682 
    683 int pthread_attr_init(
    684   pthread_attr_t  *attr
    685 )
    686 {
    687   if ( !attr )
    688     return EINVAL;
    689  
    690   *attr = _POSIX_Threads_Default_attributes;
    691   return 0;
    692 }
    693 
    694 /*PAGE
    695  *
    696  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    697  */
    698 
    699 int pthread_attr_destroy(
    700   pthread_attr_t  *attr
    701 )
    702 {
    703   if ( !attr || !attr->is_initialized )
    704     return EINVAL;
    705  
    706   attr->is_initialized = FALSE;
    707   return 0;
    708 }
    709  
    710 /*PAGE
    711  *
    712  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    713  */
    714 
    715 int pthread_attr_getstacksize(
    716   const pthread_attr_t  *attr,
    717   size_t                *stacksize
    718 )
    719 {
    720   if ( !attr || !attr->is_initialized || !stacksize )
    721     return EINVAL;
    722 
    723   *stacksize = attr->stacksize;
    724   return 0;
    725 }
    726  
    727 /*PAGE
    728  *
    729  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    730  */
    731 
    732 int pthread_attr_setstacksize(
    733   pthread_attr_t  *attr,
    734   size_t           stacksize
    735 )
    736 {
    737   if ( !attr || !attr->is_initialized )
    738     return EINVAL;
    739 
    740   if (stacksize < PTHREAD_MINIMUM_STACK_SIZE)
    741     attr->stacksize = PTHREAD_MINIMUM_STACK_SIZE;
    742   else
    743     attr->stacksize = stacksize;
    744   return 0;
    745 }
    746  
    747 /*PAGE
    748  *
    749  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    750  */
    751 
    752 int pthread_attr_getstackaddr(
    753   const pthread_attr_t   *attr,
    754   void                  **stackaddr
    755 )
    756 {
    757   if ( !attr || !attr->is_initialized || !stackaddr )
    758     return EINVAL;
    759 
    760   *stackaddr = attr->stackaddr;
    761   return 0;
    762 }
    763  
    764 /*PAGE
    765  *
    766  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    767  */
    768 
    769 int pthread_attr_setstackaddr(
    770   pthread_attr_t  *attr,
    771   void            *stackaddr
    772 )
    773 {
    774   if ( !attr || !attr->is_initialized )
    775     return EINVAL;
    776 
    777   attr->stackaddr = stackaddr;
    778   return 0;
    779 }
    780  
    781 /*PAGE
    782  *
    783  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    784  */
    785 
    786 int pthread_attr_getdetachstate(
    787   const pthread_attr_t  *attr,
    788   int                   *detachstate
    789 )
    790 {
    791   if ( !attr || !attr->is_initialized || !detachstate )
    792     return EINVAL;
    793 
    794   *detachstate = attr->detachstate;
    795   return 0;
    796 }
    797  
    798 /*PAGE
    799  *
    800  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    801  */
    802 
    803 int pthread_attr_setdetachstate(
    804   pthread_attr_t  *attr,
    805   int              detachstate
    806 )
    807 {
    808   if ( !attr || !attr->is_initialized )
    809     return EINVAL;
    810 
    811   switch ( detachstate ) {
    812     case PTHREAD_CREATE_DETACHED:
    813     case PTHREAD_CREATE_JOINABLE:
    814       attr->detachstate = detachstate;
    815       return 0;
    816  
    817     default:
    818       return EINVAL;
    819   }
    820 }
    821 
    822 /*PAGE
    823  *
    824  *  16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
    825  */
    826 
    827 int pthread_create(
    828   pthread_t              *thread,
    829   const pthread_attr_t   *attr,
    830   void                 *(*start_routine)( void * ),
    831   void                   *arg
    832 )
    833 {
    834   const pthread_attr_t               *the_attr;
    835   Priority_Control                    core_priority;
    836   Thread_CPU_budget_algorithms        budget_algorithm;
    837   Thread_CPU_budget_algorithm_callout budget_callout;
    838   boolean                             is_fp;
    839   boolean                             status;
    840   Thread_Control                     *the_thread;
    841   char                               *default_name = "psx";
    842   POSIX_API_Control                  *api;
    843   int                                 schedpolicy = SCHED_RR;
    844   struct sched_param                  schedparam;
    845 
    846   the_attr = (attr) ? attr : &_POSIX_Threads_Default_attributes;
    847 
    848   if ( !the_attr->is_initialized )
    849     return EINVAL;
    850 
    851   /*
    852    *  Core Thread Initialize insures we get the minimum amount of
    853    *  stack space if it is allowed to allocate it itself.
    854    */
    855 
    856   if ( the_attr->stackaddr && !_Stack_Is_enough( the_attr->stacksize ) )
    857     return EINVAL;
    858 
    859 #if 0
    860   int  cputime_clock_allowed;  /* see time.h */
    861   POSIX_NOT_IMPLEMENTED();
    862 #endif
    863 
    864   /*
    865    *  P1003.1c/Draft 10, p. 121.
    866    *
    867    *  If inheritsched is set to PTHREAD_INHERIT_SCHED, then this thread
    868    *  inherits scheduling attributes from the creating thread.   If it is
    869    *  PTHREAD_EXPLICIT_SCHED, then scheduling parameters come from the
    870    *  attributes structure.
    871    */
    872 
    873   switch ( the_attr->inheritsched ) {
    874     case PTHREAD_INHERIT_SCHED:
    875       api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
    876       schedpolicy = api->schedpolicy;
    877       schedparam  = api->schedparam;
    878       break;
    879 
    880     case PTHREAD_EXPLICIT_SCHED:
    881       schedpolicy = the_attr->schedpolicy;
    882       schedparam  = the_attr->schedparam;
    883       break;
    884 
    885     default:
    886       return EINVAL;
    887   }
    888 
    889   /*
    890    *  Check the contentionscope since rtems only supports PROCESS wide
    891    *  contention (i.e. no system wide contention).
    892    */
    893 
    894   if ( the_attr->contentionscope != PTHREAD_SCOPE_PROCESS )
    895     return ENOTSUP;
    896 
    897   /*
    898    *  Interpret the scheduling parameters.
    899    */
    900 
    901   if ( !_POSIX_Priority_Is_valid( schedparam.sched_priority ) )
    902     return EINVAL;
    903  
    904   core_priority = _POSIX_Priority_To_core( schedparam.sched_priority );
    905  
    906   /*
    907    *  Set the core scheduling policy information.
    908    */
    909 
    910   budget_callout = NULL;
    911   budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    912 
    913   switch ( schedpolicy ) {
    914     case SCHED_OTHER:
    915       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
    916       break;
    917      
    918     case SCHED_FIFO:
    919       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    920       break;
    921 
    922     case SCHED_RR:
    923       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE;
    924       break;
    925 
    926     case SCHED_SPORADIC:
    927       budget_algorithm  = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
    928       budget_callout = _POSIX_Threads_Sporadic_budget_callout;
    929  
    930       if ( _POSIX_Timespec_to_interval( &schedparam.ss_replenish_period ) <
    931            _POSIX_Timespec_to_interval( &schedparam.ss_initial_budget ) )
    932         return EINVAL;
    933 
    934       if ( !_POSIX_Priority_Is_valid( schedparam.ss_low_priority ) )
    935         return EINVAL;
    936 
    937       break;
    938 
    939     default:
    940       return EINVAL;
    941   }
    942 
    943   /*
    944    *  Currently all POSIX threads are floating point if the hardware
    945    *  supports it.
    946    */
    947 
    948   is_fp = CPU_HARDWARE_FP;
    949 
    950   /*
    951    *  Disable dispatch for protection
    952    */
    953  
    954   _Thread_Disable_dispatch();
    955  
    956   /*
    957    *  Allocate the thread control block.
    958    *
    959    *  NOTE:  Global threads are not currently supported.
    960    */
    961 
    962   the_thread = _POSIX_Threads_Allocate();
    963 
    964   if ( !the_thread ) {
    965     _Thread_Enable_dispatch();
    966     return EAGAIN;
    967   }
    968 
    969   /*
    970    *  Initialize the core thread for this task.
    971    */
    972  
    973   status = _Thread_Initialize(
    974     &_POSIX_Threads_Information,
    975     the_thread,
    976     the_attr->stackaddr,
    977     the_attr->stacksize,
    978     is_fp,
    979     core_priority,
    980     TRUE,                 /* preemptible */
    981     budget_algorithm,
    982     budget_callout,
    983     0,                    /* isr level */
    984     &default_name         /* posix threads don't have a name */
    985   );
    986  
    987   if ( !status ) {
    988     _POSIX_Threads_Free( the_thread );
    989     _Thread_Enable_dispatch();
    990     return EAGAIN;
    991   }
    992 
    993   /*
    994    *  finish initializing the per API structure
    995    */
    996 
    997  
    998   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    999 
    1000   api->Attributes  = *the_attr;
    1001   api->detachstate = the_attr->detachstate;
    1002   api->schedpolicy = schedpolicy;
    1003   api->schedparam  = schedparam;
    1004 
    1005   /*
    1006    *  This insures we evaluate the process-wide signals pending when we
    1007    *  first run.
    1008    *
    1009    *  NOTE:  Since the thread starts with all unblocked, this is necessary.
    1010    */
    1011 
    1012   the_thread->do_post_task_switch_extension = TRUE;
    1013 
    1014   /*
    1015    *  POSIX threads are allocated and started in one operation.
    1016    */
    1017 
    1018   status = _Thread_Start(
    1019     the_thread,
    1020     THREAD_START_POINTER,
    1021     start_routine,
    1022     arg,
    1023     0                     /* unused */
    1024   );
    1025 
    1026   if ( schedpolicy == SCHED_SPORADIC ) {
    1027     _Watchdog_Insert_ticks(
    1028       &api->Sporadic_timer,
    1029       _POSIX_Timespec_to_interval( &api->schedparam.ss_replenish_period )
    1030     );
    1031   }
    1032 
    1033   /*
    1034    *  _Thread_Start only fails if the thread was in the incorrect state
    1035    */
    1036 
    1037   if ( !status ) {
    1038     _POSIX_Threads_Free( the_thread );
    1039     _Thread_Enable_dispatch();
    1040     return EINVAL;
    1041   }
    1042 
    1043   /*
    1044    *  Return the id and indicate we successfully created the thread
    1045    */
    1046 
    1047   *thread = the_thread->Object.id;
    1048 
    1049  _Thread_Enable_dispatch();
    1050 
    1051  return 0;
    1052 }
    1053 
    1054 /*PAGE
    1055  *
    1056  *  16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147
    1057  */
    1058 
    1059 int pthread_join(
    1060   pthread_t   thread,
    1061   void      **value_ptr
    1062 )
    1063 {
    1064   register Thread_Control *the_thread;
    1065   POSIX_API_Control       *api;
    1066   Objects_Locations        location;
    1067   void                    *return_pointer;
    1068 
    1069   the_thread = _POSIX_Threads_Get( thread, &location );
    1070   switch ( location ) {
    1071     case OBJECTS_ERROR:
    1072     case OBJECTS_REMOTE:
    1073       return ESRCH;
    1074     case OBJECTS_LOCAL:
    1075       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    1076 
    1077       if ( api->detachstate == PTHREAD_CREATE_DETACHED ) {
    1078         _Thread_Enable_dispatch();
    1079         return EINVAL;
    1080       }
    1081 
    1082       if ( _Thread_Is_executing( the_thread ) ) {
    1083         _Thread_Enable_dispatch();
    1084         return EDEADLK;
    1085       }
    1086 
    1087       /*
    1088        *  Put ourself on the threads join list
    1089        */
    1090 
    1091       _Thread_Executing->Wait.return_argument = (unsigned32 *) &return_pointer;
    1092 
    1093       _Thread_queue_Enter_critical_section( &api->Join_List );
    1094 
    1095       _Thread_queue_Enqueue( &api->Join_List, WATCHDOG_NO_TIMEOUT );
    1096 
    1097       _Thread_Enable_dispatch();
    1098 
    1099       if ( value_ptr )
    1100         *value_ptr = return_pointer;
    1101       return 0;
    1102   }
    1103 
    1104   return POSIX_BOTTOM_REACHED();
    1105 }
    1106 
    1107 /*PAGE
    1108  *
    1109  *  16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149
    1110  */
    1111 
    1112 int pthread_detach(
    1113   pthread_t   thread
    1114 )
    1115 {
    1116   register Thread_Control *the_thread;
    1117   POSIX_API_Control       *api;
    1118   Objects_Locations        location;
    1119  
    1120   the_thread = _POSIX_Threads_Get( thread, &location );
    1121   switch ( location ) {
    1122     case OBJECTS_ERROR:
    1123     case OBJECTS_REMOTE:
    1124       return ESRCH;
    1125     case OBJECTS_LOCAL:
    1126 
    1127       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    1128       api->detachstate = PTHREAD_CREATE_DETACHED;
    1129       _Thread_Enable_dispatch();
    1130       return 0;
    1131   }
    1132  
    1133   return POSIX_BOTTOM_REACHED();
    1134 }
    1135 
    1136 /*PAGE
    1137  *
    1138  *  16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150
    1139  *
    1140  *  NOTE: Key destructors are executed in the POSIX api delete extension.
    1141  */
    1142  
    1143 void pthread_exit(
    1144   void  *value_ptr
    1145 )
    1146 {
    1147   Objects_Information     *the_information;
    1148 
    1149   the_information = _Objects_Get_information( _Thread_Executing->Object.id );
    1150  
    1151   _Thread_Disable_dispatch();
    1152 
    1153   _Thread_Executing->Wait.return_argument = (unsigned32 *)value_ptr;
    1154 
    1155   _Thread_Close( the_information, _Thread_Executing );
    1156 
    1157   _POSIX_Threads_Free( _Thread_Executing );
    1158 
    1159   _Thread_Enable_dispatch();
    1160 }
    1161 
    1162 /*PAGE
    1163  *
    1164  *  16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. 152
    1165  */
    1166 
    1167 pthread_t pthread_self( void )
    1168 {
    1169   return _Thread_Executing->Object.id;
    1170 }
    1171 
    1172 /*PAGE
    1173  *
    1174  *  16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153
    1175  *
    1176  *  NOTE:  POSIX does not define the behavior when either thread id is invalid.
    1177  */
    1178 
    1179 int pthread_equal(
    1180   pthread_t  t1,
    1181   pthread_t  t2
    1182 )
    1183 {
    1184   /*
    1185    *  If the system is configured for debug, then we will do everything we
    1186    *  can to insure that both ids are valid.  Otherwise, we will do the
    1187    *  cheapest possible thing to determine if they are equal.
    1188    */
    1189 
    1190 #ifndef RTEMS_DEBUG
    1191   return _Objects_Are_ids_equal( t1, t2 );
    1192 #else
    1193   int               status;
    1194   Objects_Locations location;
    1195 
    1196   /*
    1197    *  By default this is not a match.
    1198    */
    1199 
    1200   status = 0;
    1201 
    1202   /*
    1203    *  Validate the first id and return 0 if it is not valid
    1204    */
    1205 
    1206   (void) _POSIX_Threads_Get( t1, &location );
    1207   switch ( location ) {
    1208     case OBJECTS_ERROR:
    1209     case OBJECTS_REMOTE:
    1210       break;
    1211 
    1212     case OBJECTS_LOCAL:
    1213 
    1214       /*
    1215        *  Validate the second id and return 0 if it is not valid
    1216        */
    1217 
    1218       (void) _POSIX_Threads_Get( t2, &location );
    1219       switch ( location ) {
    1220         case OBJECTS_ERROR:
    1221         case OBJECTS_REMOTE:
    1222           break;
    1223         case OBJECTS_LOCAL:
    1224           status = _Objects_Are_ids_equal( t1, t2 );
    1225           break;
    1226       }
    1227       _Thread_Unnest_dispatch();
    1228       break;
    1229   }
    1230 
    1231   _Thread_Enable_dispatch();
    1232   return status;
    1233 #endif
    1234 }
    1235 
    1236 /*PAGE
    1237  *
    1238  *  16.1.8 Dynamic Package Initialization, P1003.1c/Draft 10, p. 154
    1239  */
    1240 
    1241 int pthread_once(
    1242   pthread_once_t  *once_control,
    1243   void           (*init_routine)(void)
    1244 )
    1245 {
    1246   if ( !once_control || !init_routine )
    1247     return EINVAL;
    1248 
    1249   _Thread_Disable_dispatch();
    1250 
    1251   if ( !once_control->init_executed ) {
    1252     once_control->is_initialized = TRUE;
    1253     once_control->init_executed = TRUE;
    1254     (*init_routine)();
    1255   }
    1256  
    1257   _Thread_Enable_dispatch();
    1258   return 0;
    1259 }
    1260 
    1261 /*PAGE
    1262  *
    1263  *  20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/Draft 8, p. 58
    1264  */
    1265  
    1266 int pthread_getcpuclockid(
    1267   pthread_t    pid,
    1268   clockid_t   *clock_id
    1269 )
    1270 {
    1271   return POSIX_NOT_IMPLEMENTED();
    1272 }
    1273 
    1274 /*PAGE
    1275  *
    1276  *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/Draft 8, p. 59
    1277  */
    1278 
    1279 int pthread_attr_setcputime(
    1280   pthread_attr_t  *attr,
    1281   int              clock_allowed
    1282 )
    1283 {
    1284   if ( !attr || !attr->is_initialized )
    1285     return EINVAL;
    1286 
    1287   switch ( clock_allowed ) {
    1288     case CLOCK_ENABLED:
    1289     case CLOCK_DISABLED:
    1290       attr->cputime_clock_allowed = clock_allowed;
    1291       return 0;
    1292  
    1293     default:
    1294       return EINVAL;
    1295   }
    1296 }
    1297 
    1298 /*PAGE
    1299  *
    1300  *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/Draft 8, p. 59
    1301  */
    1302 
    1303 int pthread_attr_getcputime(
    1304   pthread_attr_t  *attr,
    1305   int             *clock_allowed
    1306 )
    1307 {
    1308   if ( !attr || !attr->is_initialized || !clock_allowed )
    1309     return EINVAL;
    1310 
    1311   *clock_allowed = attr->cputime_clock_allowed;
    1312   return 0;
    1313 }
  • c/src/exec/posix/src/pthreadatfork.c

    r535db3ae r03598b1  
    11/*
    22 *  pthread_atfork() - POSIX 1003.1b 3.1.3
     3 *
     4 *  3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
     5 *
     6 *  RTEMS does not support processes, so we fall under this and do not
     7 *  provide this routine:
     8 *
     9 *  "Either the implementation shall support the pthread_atfork() function
     10 *   as described above or the pthread_atfork() funciton shall not be
     11 *   provided."
    312 *
    413 *  $Id$
  • cpukit/posix/src/pthread.c

    r535db3ae r03598b1  
    355355 
    356356}
    357 
    358 /*PAGE
    359  *
    360  *  3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
    361  *
    362  *  RTEMS does not support processes, so we fall under this and do not
    363  *  provide this routine:
    364  *
    365  *  "Either the implementation shall support the pthread_atfork() function
    366  *   as described above or the pthread_atfork() funciton shall not be
    367  *   provided."
    368  */
    369 
    370 /*PAGE
    371  *
    372  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    373  */
    374 
    375 int pthread_attr_setscope(
    376   pthread_attr_t  *attr,
    377   int              contentionscope
    378 )
    379 {
    380   if ( !attr || !attr->is_initialized )
    381     return EINVAL;
    382 
    383   switch ( contentionscope ) {
    384     case PTHREAD_SCOPE_PROCESS:
    385       attr->contentionscope = contentionscope;
    386       return 0;
    387 
    388     case PTHREAD_SCOPE_SYSTEM:
    389       return ENOTSUP;
    390 
    391     default:
    392       return EINVAL;
    393   }
    394 }
    395 
    396 /*PAGE
    397  *
    398  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    399  */
    400 
    401 int pthread_attr_getscope(
    402   const pthread_attr_t  *attr,
    403   int                   *contentionscope
    404 )
    405 {
    406   if ( !attr || !attr->is_initialized || !contentionscope )
    407     return EINVAL;
    408 
    409   *contentionscope = attr->contentionscope;
    410   return 0;
    411 }
    412 
    413 /*PAGE
    414  *
    415  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    416  */
    417 
    418 int pthread_attr_setinheritsched(
    419   pthread_attr_t  *attr,
    420   int              inheritsched
    421 )
    422 {
    423   if ( !attr || !attr->is_initialized )
    424     return EINVAL;
    425 
    426   switch ( inheritsched ) {
    427     case PTHREAD_INHERIT_SCHED:
    428     case PTHREAD_EXPLICIT_SCHED:
    429       attr->inheritsched = inheritsched;
    430       return 0;
    431 
    432     default:
    433       return ENOTSUP;
    434   }
    435 }
    436 
    437 /*PAGE
    438  *
    439  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    440  */
    441 
    442 int pthread_attr_getinheritsched(
    443   const pthread_attr_t  *attr,
    444   int                   *inheritsched
    445 )
    446 {
    447   if ( !attr || !attr->is_initialized || !inheritsched )
    448     return EINVAL;
    449 
    450   *inheritsched = attr->inheritsched;
    451   return 0;
    452 }
    453 
    454 /*PAGE
    455  *
    456  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    457  */
    458 
    459 int pthread_attr_setschedpolicy(
    460   pthread_attr_t  *attr,
    461   int              policy
    462 )
    463 {
    464   if ( !attr || !attr->is_initialized )
    465     return EINVAL;
    466 
    467   switch ( policy ) {
    468     case SCHED_OTHER:
    469     case SCHED_FIFO:
    470     case SCHED_RR:
    471     case SCHED_SPORADIC:
    472       attr->schedpolicy = policy;
    473       return 0;
    474  
    475     default:
    476       return ENOTSUP;
    477   }
    478 }
    479 
    480 /*PAGE
    481  *
    482  *  13.5.1 Thread Creation Scheduling Parameters, P1003.1c/Draft 10, p. 120
    483  */
    484 
    485 int pthread_attr_getschedpolicy(
    486   const pthread_attr_t  *attr,
    487   int                   *policy
    488 )
    489 {
    490   if ( !attr || !attr->is_initialized || !policy )
    491     return EINVAL;
    492 
    493   *policy = attr->schedpolicy;
    494   return 0;
    495 }
    496 
    497 /*PAGE
    498  *
    499  *  13.5.1 Thread Creation Scheduling Parameters, P1003.1c/Draft 10, p. 120
    500  */
    501 
    502 int pthread_attr_setschedparam(
    503   pthread_attr_t           *attr,
    504   const struct sched_param *param
    505 )
    506 {
    507   if ( !attr || !attr->is_initialized || !param )
    508     return EINVAL;
    509 
    510   attr->schedparam = *param;
    511   return 0;
    512 }
    513 
    514 /*PAGE
    515  *
    516  *  13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
    517  */
    518 
    519 int pthread_attr_getschedparam(
    520   const pthread_attr_t   *attr,
    521   struct sched_param     *param
    522 )
    523 {
    524   if ( !attr || !attr->is_initialized || !param )
    525     return EINVAL;
    526 
    527   *param = attr->schedparam;
    528   return 0;
    529 }
    530 
    531 /*PAGE
    532  *
    533  *  13.5.2 Dynamic Thread Scheduling Parameters Access,
    534  *         P1003.1c/Draft 10, p. 124
    535  */
    536 
    537 int pthread_getschedparam(
    538   pthread_t           thread,
    539   int                *policy,
    540   struct sched_param *param
    541 )
    542 {
    543   Objects_Locations        location;
    544   POSIX_API_Control       *api;
    545   register Thread_Control *the_thread;
    546 
    547   if ( !policy || !param  )
    548     return EINVAL;
    549 
    550   the_thread = _POSIX_Threads_Get( thread, &location );
    551   switch ( location ) {
    552     case OBJECTS_ERROR:
    553     case OBJECTS_REMOTE:
    554       return ESRCH;
    555     case OBJECTS_LOCAL:
    556       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    557       *policy = api->schedpolicy;
    558       *param  = api->schedparam;
    559       param->sched_priority =
    560         _POSIX_Priority_From_core( the_thread->current_priority );
    561       _Thread_Enable_dispatch();
    562       return 0;
    563   }
    564  
    565   return POSIX_BOTTOM_REACHED();
    566 
    567 }
    568 
    569 /*PAGE
    570  *
    571  *  13.5.2 Dynamic Thread Scheduling Parameters Access,
    572  *         P1003.1c/Draft 10, p. 124
    573  */
    574 
    575 int pthread_setschedparam(
    576   pthread_t           thread,
    577   int                 policy,
    578   struct sched_param *param
    579 )
    580 {
    581   register Thread_Control             *the_thread;
    582   POSIX_API_Control                   *api;
    583   Thread_CPU_budget_algorithms         budget_algorithm;
    584   Thread_CPU_budget_algorithm_callout  budget_callout;
    585   Objects_Locations                    location;
    586  
    587   /*
    588    *  Check all the parameters
    589    */
    590 
    591   if ( !param )
    592     return EINVAL;
    593 
    594   if ( !_POSIX_Priority_Is_valid( param->sched_priority ) )
    595     return EINVAL;
    596 
    597   budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    598   budget_callout = NULL;
    599 
    600   switch ( policy ) {
    601     case SCHED_OTHER:
    602       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
    603       break;
    604  
    605     case SCHED_FIFO:
    606       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    607       break;
    608  
    609     case SCHED_RR:
    610       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE;
    611       break;
    612  
    613     case SCHED_SPORADIC:
    614       budget_algorithm  = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
    615       budget_callout = _POSIX_Threads_Sporadic_budget_callout;
    616  
    617       if ( _POSIX_Timespec_to_interval( &param->ss_replenish_period ) <
    618            _POSIX_Timespec_to_interval( &param->ss_initial_budget ) )
    619         return EINVAL;
    620  
    621       if ( !_POSIX_Priority_Is_valid( param->ss_low_priority ) )
    622         return EINVAL;
    623  
    624       break;
    625  
    626     default:
    627       return EINVAL;
    628   }
    629 
    630   /*
    631    *  Actually change the scheduling policy and parameters
    632    */
    633 
    634   the_thread = _POSIX_Threads_Get( thread, &location );
    635   switch ( location ) {
    636     case OBJECTS_ERROR:
    637     case OBJECTS_REMOTE:
    638       return ESRCH;
    639     case OBJECTS_LOCAL:
    640       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    641 
    642       if ( api->schedpolicy == SCHED_SPORADIC )
    643         (void) _Watchdog_Remove( &api->Sporadic_timer );
    644 
    645       api->schedpolicy = policy;
    646       api->schedparam  = *param;
    647       the_thread->budget_algorithm = budget_algorithm;
    648       the_thread->budget_callout   = budget_callout;
    649 
    650       switch ( api->schedpolicy ) {
    651         case SCHED_OTHER:
    652         case SCHED_FIFO:
    653         case SCHED_RR:
    654           the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
    655 
    656           the_thread->real_priority =
    657             _POSIX_Priority_To_core( api->schedparam.sched_priority );
    658 
    659           _Thread_Change_priority(
    660              the_thread,
    661              the_thread->real_priority,
    662              TRUE
    663           );
    664           break;
    665  
    666         case SCHED_SPORADIC:
    667           api->ss_high_priority = api->schedparam.sched_priority;
    668           _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread );
    669           break;
    670       }
    671 
    672       _Thread_Enable_dispatch();
    673       return 0;
    674   }
    675   return POSIX_BOTTOM_REACHED();
    676 }
    677 
    678 /*PAGE
    679  *
    680  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    681  */
    682 
    683 int pthread_attr_init(
    684   pthread_attr_t  *attr
    685 )
    686 {
    687   if ( !attr )
    688     return EINVAL;
    689  
    690   *attr = _POSIX_Threads_Default_attributes;
    691   return 0;
    692 }
    693 
    694 /*PAGE
    695  *
    696  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    697  */
    698 
    699 int pthread_attr_destroy(
    700   pthread_attr_t  *attr
    701 )
    702 {
    703   if ( !attr || !attr->is_initialized )
    704     return EINVAL;
    705  
    706   attr->is_initialized = FALSE;
    707   return 0;
    708 }
    709  
    710 /*PAGE
    711  *
    712  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    713  */
    714 
    715 int pthread_attr_getstacksize(
    716   const pthread_attr_t  *attr,
    717   size_t                *stacksize
    718 )
    719 {
    720   if ( !attr || !attr->is_initialized || !stacksize )
    721     return EINVAL;
    722 
    723   *stacksize = attr->stacksize;
    724   return 0;
    725 }
    726  
    727 /*PAGE
    728  *
    729  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    730  */
    731 
    732 int pthread_attr_setstacksize(
    733   pthread_attr_t  *attr,
    734   size_t           stacksize
    735 )
    736 {
    737   if ( !attr || !attr->is_initialized )
    738     return EINVAL;
    739 
    740   if (stacksize < PTHREAD_MINIMUM_STACK_SIZE)
    741     attr->stacksize = PTHREAD_MINIMUM_STACK_SIZE;
    742   else
    743     attr->stacksize = stacksize;
    744   return 0;
    745 }
    746  
    747 /*PAGE
    748  *
    749  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    750  */
    751 
    752 int pthread_attr_getstackaddr(
    753   const pthread_attr_t   *attr,
    754   void                  **stackaddr
    755 )
    756 {
    757   if ( !attr || !attr->is_initialized || !stackaddr )
    758     return EINVAL;
    759 
    760   *stackaddr = attr->stackaddr;
    761   return 0;
    762 }
    763  
    764 /*PAGE
    765  *
    766  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    767  */
    768 
    769 int pthread_attr_setstackaddr(
    770   pthread_attr_t  *attr,
    771   void            *stackaddr
    772 )
    773 {
    774   if ( !attr || !attr->is_initialized )
    775     return EINVAL;
    776 
    777   attr->stackaddr = stackaddr;
    778   return 0;
    779 }
    780  
    781 /*PAGE
    782  *
    783  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    784  */
    785 
    786 int pthread_attr_getdetachstate(
    787   const pthread_attr_t  *attr,
    788   int                   *detachstate
    789 )
    790 {
    791   if ( !attr || !attr->is_initialized || !detachstate )
    792     return EINVAL;
    793 
    794   *detachstate = attr->detachstate;
    795   return 0;
    796 }
    797  
    798 /*PAGE
    799  *
    800  *  16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
    801  */
    802 
    803 int pthread_attr_setdetachstate(
    804   pthread_attr_t  *attr,
    805   int              detachstate
    806 )
    807 {
    808   if ( !attr || !attr->is_initialized )
    809     return EINVAL;
    810 
    811   switch ( detachstate ) {
    812     case PTHREAD_CREATE_DETACHED:
    813     case PTHREAD_CREATE_JOINABLE:
    814       attr->detachstate = detachstate;
    815       return 0;
    816  
    817     default:
    818       return EINVAL;
    819   }
    820 }
    821 
    822 /*PAGE
    823  *
    824  *  16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
    825  */
    826 
    827 int pthread_create(
    828   pthread_t              *thread,
    829   const pthread_attr_t   *attr,
    830   void                 *(*start_routine)( void * ),
    831   void                   *arg
    832 )
    833 {
    834   const pthread_attr_t               *the_attr;
    835   Priority_Control                    core_priority;
    836   Thread_CPU_budget_algorithms        budget_algorithm;
    837   Thread_CPU_budget_algorithm_callout budget_callout;
    838   boolean                             is_fp;
    839   boolean                             status;
    840   Thread_Control                     *the_thread;
    841   char                               *default_name = "psx";
    842   POSIX_API_Control                  *api;
    843   int                                 schedpolicy = SCHED_RR;
    844   struct sched_param                  schedparam;
    845 
    846   the_attr = (attr) ? attr : &_POSIX_Threads_Default_attributes;
    847 
    848   if ( !the_attr->is_initialized )
    849     return EINVAL;
    850 
    851   /*
    852    *  Core Thread Initialize insures we get the minimum amount of
    853    *  stack space if it is allowed to allocate it itself.
    854    */
    855 
    856   if ( the_attr->stackaddr && !_Stack_Is_enough( the_attr->stacksize ) )
    857     return EINVAL;
    858 
    859 #if 0
    860   int  cputime_clock_allowed;  /* see time.h */
    861   POSIX_NOT_IMPLEMENTED();
    862 #endif
    863 
    864   /*
    865    *  P1003.1c/Draft 10, p. 121.
    866    *
    867    *  If inheritsched is set to PTHREAD_INHERIT_SCHED, then this thread
    868    *  inherits scheduling attributes from the creating thread.   If it is
    869    *  PTHREAD_EXPLICIT_SCHED, then scheduling parameters come from the
    870    *  attributes structure.
    871    */
    872 
    873   switch ( the_attr->inheritsched ) {
    874     case PTHREAD_INHERIT_SCHED:
    875       api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
    876       schedpolicy = api->schedpolicy;
    877       schedparam  = api->schedparam;
    878       break;
    879 
    880     case PTHREAD_EXPLICIT_SCHED:
    881       schedpolicy = the_attr->schedpolicy;
    882       schedparam  = the_attr->schedparam;
    883       break;
    884 
    885     default:
    886       return EINVAL;
    887   }
    888 
    889   /*
    890    *  Check the contentionscope since rtems only supports PROCESS wide
    891    *  contention (i.e. no system wide contention).
    892    */
    893 
    894   if ( the_attr->contentionscope != PTHREAD_SCOPE_PROCESS )
    895     return ENOTSUP;
    896 
    897   /*
    898    *  Interpret the scheduling parameters.
    899    */
    900 
    901   if ( !_POSIX_Priority_Is_valid( schedparam.sched_priority ) )
    902     return EINVAL;
    903  
    904   core_priority = _POSIX_Priority_To_core( schedparam.sched_priority );
    905  
    906   /*
    907    *  Set the core scheduling policy information.
    908    */
    909 
    910   budget_callout = NULL;
    911   budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    912 
    913   switch ( schedpolicy ) {
    914     case SCHED_OTHER:
    915       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
    916       break;
    917      
    918     case SCHED_FIFO:
    919       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    920       break;
    921 
    922     case SCHED_RR:
    923       budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE;
    924       break;
    925 
    926     case SCHED_SPORADIC:
    927       budget_algorithm  = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
    928       budget_callout = _POSIX_Threads_Sporadic_budget_callout;
    929  
    930       if ( _POSIX_Timespec_to_interval( &schedparam.ss_replenish_period ) <
    931            _POSIX_Timespec_to_interval( &schedparam.ss_initial_budget ) )
    932         return EINVAL;
    933 
    934       if ( !_POSIX_Priority_Is_valid( schedparam.ss_low_priority ) )
    935         return EINVAL;
    936 
    937       break;
    938 
    939     default:
    940       return EINVAL;
    941   }
    942 
    943   /*
    944    *  Currently all POSIX threads are floating point if the hardware
    945    *  supports it.
    946    */
    947 
    948   is_fp = CPU_HARDWARE_FP;
    949 
    950   /*
    951    *  Disable dispatch for protection
    952    */
    953  
    954   _Thread_Disable_dispatch();
    955  
    956   /*
    957    *  Allocate the thread control block.
    958    *
    959    *  NOTE:  Global threads are not currently supported.
    960    */
    961 
    962   the_thread = _POSIX_Threads_Allocate();
    963 
    964   if ( !the_thread ) {
    965     _Thread_Enable_dispatch();
    966     return EAGAIN;
    967   }
    968 
    969   /*
    970    *  Initialize the core thread for this task.
    971    */
    972  
    973   status = _Thread_Initialize(
    974     &_POSIX_Threads_Information,
    975     the_thread,
    976     the_attr->stackaddr,
    977     the_attr->stacksize,
    978     is_fp,
    979     core_priority,
    980     TRUE,                 /* preemptible */
    981     budget_algorithm,
    982     budget_callout,
    983     0,                    /* isr level */
    984     &default_name         /* posix threads don't have a name */
    985   );
    986  
    987   if ( !status ) {
    988     _POSIX_Threads_Free( the_thread );
    989     _Thread_Enable_dispatch();
    990     return EAGAIN;
    991   }
    992 
    993   /*
    994    *  finish initializing the per API structure
    995    */
    996 
    997  
    998   api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    999 
    1000   api->Attributes  = *the_attr;
    1001   api->detachstate = the_attr->detachstate;
    1002   api->schedpolicy = schedpolicy;
    1003   api->schedparam  = schedparam;
    1004 
    1005   /*
    1006    *  This insures we evaluate the process-wide signals pending when we
    1007    *  first run.
    1008    *
    1009    *  NOTE:  Since the thread starts with all unblocked, this is necessary.
    1010    */
    1011 
    1012   the_thread->do_post_task_switch_extension = TRUE;
    1013 
    1014   /*
    1015    *  POSIX threads are allocated and started in one operation.
    1016    */
    1017 
    1018   status = _Thread_Start(
    1019     the_thread,
    1020     THREAD_START_POINTER,
    1021     start_routine,
    1022     arg,
    1023     0                     /* unused */
    1024   );
    1025 
    1026   if ( schedpolicy == SCHED_SPORADIC ) {
    1027     _Watchdog_Insert_ticks(
    1028       &api->Sporadic_timer,
    1029       _POSIX_Timespec_to_interval( &api->schedparam.ss_replenish_period )
    1030     );
    1031   }
    1032 
    1033   /*
    1034    *  _Thread_Start only fails if the thread was in the incorrect state
    1035    */
    1036 
    1037   if ( !status ) {
    1038     _POSIX_Threads_Free( the_thread );
    1039     _Thread_Enable_dispatch();
    1040     return EINVAL;
    1041   }
    1042 
    1043   /*
    1044    *  Return the id and indicate we successfully created the thread
    1045    */
    1046 
    1047   *thread = the_thread->Object.id;
    1048 
    1049  _Thread_Enable_dispatch();
    1050 
    1051  return 0;
    1052 }
    1053 
    1054 /*PAGE
    1055  *
    1056  *  16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147
    1057  */
    1058 
    1059 int pthread_join(
    1060   pthread_t   thread,
    1061   void      **value_ptr
    1062 )
    1063 {
    1064   register Thread_Control *the_thread;
    1065   POSIX_API_Control       *api;
    1066   Objects_Locations        location;
    1067   void                    *return_pointer;
    1068 
    1069   the_thread = _POSIX_Threads_Get( thread, &location );
    1070   switch ( location ) {
    1071     case OBJECTS_ERROR:
    1072     case OBJECTS_REMOTE:
    1073       return ESRCH;
    1074     case OBJECTS_LOCAL:
    1075       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    1076 
    1077       if ( api->detachstate == PTHREAD_CREATE_DETACHED ) {
    1078         _Thread_Enable_dispatch();
    1079         return EINVAL;
    1080       }
    1081 
    1082       if ( _Thread_Is_executing( the_thread ) ) {
    1083         _Thread_Enable_dispatch();
    1084         return EDEADLK;
    1085       }
    1086 
    1087       /*
    1088        *  Put ourself on the threads join list
    1089        */
    1090 
    1091       _Thread_Executing->Wait.return_argument = (unsigned32 *) &return_pointer;
    1092 
    1093       _Thread_queue_Enter_critical_section( &api->Join_List );
    1094 
    1095       _Thread_queue_Enqueue( &api->Join_List, WATCHDOG_NO_TIMEOUT );
    1096 
    1097       _Thread_Enable_dispatch();
    1098 
    1099       if ( value_ptr )
    1100         *value_ptr = return_pointer;
    1101       return 0;
    1102   }
    1103 
    1104   return POSIX_BOTTOM_REACHED();
    1105 }
    1106 
    1107 /*PAGE
    1108  *
    1109  *  16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149
    1110  */
    1111 
    1112 int pthread_detach(
    1113   pthread_t   thread
    1114 )
    1115 {
    1116   register Thread_Control *the_thread;
    1117   POSIX_API_Control       *api;
    1118   Objects_Locations        location;
    1119  
    1120   the_thread = _POSIX_Threads_Get( thread, &location );
    1121   switch ( location ) {
    1122     case OBJECTS_ERROR:
    1123     case OBJECTS_REMOTE:
    1124       return ESRCH;
    1125     case OBJECTS_LOCAL:
    1126 
    1127       api = the_thread->API_Extensions[ THREAD_API_POSIX ];
    1128       api->detachstate = PTHREAD_CREATE_DETACHED;
    1129       _Thread_Enable_dispatch();
    1130       return 0;
    1131   }
    1132  
    1133   return POSIX_BOTTOM_REACHED();
    1134 }
    1135 
    1136 /*PAGE
    1137  *
    1138  *  16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150
    1139  *
    1140  *  NOTE: Key destructors are executed in the POSIX api delete extension.
    1141  */
    1142  
    1143 void pthread_exit(
    1144   void  *value_ptr
    1145 )
    1146 {
    1147   Objects_Information     *the_information;
    1148 
    1149   the_information = _Objects_Get_information( _Thread_Executing->Object.id );
    1150  
    1151   _Thread_Disable_dispatch();
    1152 
    1153   _Thread_Executing->Wait.return_argument = (unsigned32 *)value_ptr;
    1154 
    1155   _Thread_Close( the_information, _Thread_Executing );
    1156 
    1157   _POSIX_Threads_Free( _Thread_Executing );
    1158 
    1159   _Thread_Enable_dispatch();
    1160 }
    1161 
    1162 /*PAGE
    1163  *
    1164  *  16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. 152
    1165  */
    1166 
    1167 pthread_t pthread_self( void )
    1168 {
    1169   return _Thread_Executing->Object.id;
    1170 }
    1171 
    1172 /*PAGE
    1173  *
    1174  *  16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153
    1175  *
    1176  *  NOTE:  POSIX does not define the behavior when either thread id is invalid.
    1177  */
    1178 
    1179 int pthread_equal(
    1180   pthread_t  t1,
    1181   pthread_t  t2
    1182 )
    1183 {
    1184   /*
    1185    *  If the system is configured for debug, then we will do everything we
    1186    *  can to insure that both ids are valid.  Otherwise, we will do the
    1187    *  cheapest possible thing to determine if they are equal.
    1188    */
    1189 
    1190 #ifndef RTEMS_DEBUG
    1191   return _Objects_Are_ids_equal( t1, t2 );
    1192 #else
    1193   int               status;
    1194   Objects_Locations location;
    1195 
    1196   /*
    1197    *  By default this is not a match.
    1198    */
    1199 
    1200   status = 0;
    1201 
    1202   /*
    1203    *  Validate the first id and return 0 if it is not valid
    1204    */
    1205 
    1206   (void) _POSIX_Threads_Get( t1, &location );
    1207   switch ( location ) {
    1208     case OBJECTS_ERROR:
    1209     case OBJECTS_REMOTE:
    1210       break;
    1211 
    1212     case OBJECTS_LOCAL:
    1213 
    1214       /*
    1215        *  Validate the second id and return 0 if it is not valid
    1216        */
    1217 
    1218       (void) _POSIX_Threads_Get( t2, &location );
    1219       switch ( location ) {
    1220         case OBJECTS_ERROR:
    1221         case OBJECTS_REMOTE:
    1222           break;
    1223         case OBJECTS_LOCAL:
    1224           status = _Objects_Are_ids_equal( t1, t2 );
    1225           break;
    1226       }
    1227       _Thread_Unnest_dispatch();
    1228       break;
    1229   }
    1230 
    1231   _Thread_Enable_dispatch();
    1232   return status;
    1233 #endif
    1234 }
    1235 
    1236 /*PAGE
    1237  *
    1238  *  16.1.8 Dynamic Package Initialization, P1003.1c/Draft 10, p. 154
    1239  */
    1240 
    1241 int pthread_once(
    1242   pthread_once_t  *once_control,
    1243   void           (*init_routine)(void)
    1244 )
    1245 {
    1246   if ( !once_control || !init_routine )
    1247     return EINVAL;
    1248 
    1249   _Thread_Disable_dispatch();
    1250 
    1251   if ( !once_control->init_executed ) {
    1252     once_control->is_initialized = TRUE;
    1253     once_control->init_executed = TRUE;
    1254     (*init_routine)();
    1255   }
    1256  
    1257   _Thread_Enable_dispatch();
    1258   return 0;
    1259 }
    1260 
    1261 /*PAGE
    1262  *
    1263  *  20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/Draft 8, p. 58
    1264  */
    1265  
    1266 int pthread_getcpuclockid(
    1267   pthread_t    pid,
    1268   clockid_t   *clock_id
    1269 )
    1270 {
    1271   return POSIX_NOT_IMPLEMENTED();
    1272 }
    1273 
    1274 /*PAGE
    1275  *
    1276  *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/Draft 8, p. 59
    1277  */
    1278 
    1279 int pthread_attr_setcputime(
    1280   pthread_attr_t  *attr,
    1281   int              clock_allowed
    1282 )
    1283 {
    1284   if ( !attr || !attr->is_initialized )
    1285     return EINVAL;
    1286 
    1287   switch ( clock_allowed ) {
    1288     case CLOCK_ENABLED:
    1289     case CLOCK_DISABLED:
    1290       attr->cputime_clock_allowed = clock_allowed;
    1291       return 0;
    1292  
    1293     default:
    1294       return EINVAL;
    1295   }
    1296 }
    1297 
    1298 /*PAGE
    1299  *
    1300  *  20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/Draft 8, p. 59
    1301  */
    1302 
    1303 int pthread_attr_getcputime(
    1304   pthread_attr_t  *attr,
    1305   int             *clock_allowed
    1306 )
    1307 {
    1308   if ( !attr || !attr->is_initialized || !clock_allowed )
    1309     return EINVAL;
    1310 
    1311   *clock_allowed = attr->cputime_clock_allowed;
    1312   return 0;
    1313 }
  • cpukit/posix/src/pthreadatfork.c

    r535db3ae r03598b1  
    11/*
    22 *  pthread_atfork() - POSIX 1003.1b 3.1.3
     3 *
     4 *  3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
     5 *
     6 *  RTEMS does not support processes, so we fall under this and do not
     7 *  provide this routine:
     8 *
     9 *  "Either the implementation shall support the pthread_atfork() function
     10 *   as described above or the pthread_atfork() funciton shall not be
     11 *   provided."
    312 *
    413 *  $Id$
Note: See TracChangeset for help on using the changeset viewer.