Changeset c4d69e2 in rtems


Ignore:
Timestamp:
May 17, 1999, 9:02:16 PM (22 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
d7851582
Parents:
05df0a8
Message:

Split Task Manager into multiple files. Eventually this effort will
reduce the size of executables.

Files:
28 added
3 edited

Legend:

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

    r05df0a8 rc4d69e2  
    2020MP_PIECES = $(MP_PIECES_$(HAS_MP)_V)
    2121
     22TASK_PIECES=\
     23  tasks taskcreate taskdelete taskgetnote taskident taskinitusers \
     24  taskmode taskrestart taskresume tasksetnote tasksetpriority \
     25  taskstart tasksuspend taskwakeafter taskwakewhen
     26
    2227C_PIECES=attr clock dpmem event intr intrbody msg \
    2328   part ratemon region sem signal \
    24    tasks timer $(MP_PIECES)
     29   $(TASK_PIECES) timer $(MP_PIECES)
    2530C_FILES=$(C_PIECES:%=%.c)
    2631C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
  • c/src/exec/rtems/src/tasks.c

    r05df0a8 rc4d69e2  
    216216}
    217217
    218 /*PAGE
    219  *
    220  *  rtems_task_create
    221  *
    222  *  This directive creates a thread by allocating and initializing a
    223  *  thread control block and a stack.  The newly created thread is
    224  *  placed in the dormant state.
    225  *
    226  *  Input parameters:
    227  *    name             - user defined thread name
    228  *    initial_priority - thread priority
    229  *    stack_size       - stack size in bytes
    230  *    initial_modes    - initial thread mode
    231  *    attribute_set    - thread attributes
    232  *    id               - pointer to thread id
    233  *
    234  *  Output parameters:
    235  *    id                - thread id
    236  *    RTEMS_SUCCESSFUL - if successful
    237  *    error code        - if unsuccessful
    238  */
    239 
    240 rtems_status_code rtems_task_create(
    241   rtems_name           name,
    242   rtems_task_priority  initial_priority,
    243   unsigned32           stack_size,
    244   rtems_mode           initial_modes,
    245   rtems_attribute      attribute_set,
    246   Objects_Id          *id
    247 )
    248 {
    249   register Thread_Control *the_thread;
    250   boolean                  is_fp;
    251 #if defined(RTEMS_MULTIPROCESSING)
    252   Objects_MP_Control      *the_global_object = NULL;
    253   boolean                  is_global;
    254 #endif
    255   boolean                  status;
    256   rtems_attribute          the_attribute_set;
    257   Priority_Control         core_priority;
    258   RTEMS_API_Control       *api;
    259   ASR_Information         *asr;
    260  
    261 
    262   if ( !rtems_is_name_valid( name ) )
    263     return RTEMS_INVALID_NAME;
    264 
    265   /*
    266    *  Core Thread Initialize insures we get the minimum amount of
    267    *  stack space.
    268    */
    269 
    270 #if 0
    271   if ( !_Stack_Is_enough( stack_size ) )
    272     return RTEMS_INVALID_SIZE;
    273 #endif
    274 
    275   /*
    276    *  Fix the attribute set to match the attributes which
    277    *  this processor (1) requires and (2) is able to support.
    278    *  First add in the required flags for attribute_set
    279    *  Typically this might include FP if the platform
    280    *  or application required all tasks to be fp aware.
    281    *  Then turn off the requested bits which are not supported.
    282    */
    283 
    284   the_attribute_set = _Attributes_Set( attribute_set, ATTRIBUTES_REQUIRED );
    285   the_attribute_set =
    286     _Attributes_Clear( the_attribute_set, ATTRIBUTES_NOT_SUPPORTED );
    287 
    288   if ( _Attributes_Is_floating_point( the_attribute_set ) )
    289     is_fp = TRUE;
    290   else
    291     is_fp = FALSE;
    292 
    293   /*
    294    *  Validate the RTEMS API priority and convert it to the core priority range.
    295    */
    296 
    297   if ( !_Attributes_Is_system_task( the_attribute_set ) ) {
    298     if ( !_RTEMS_tasks_Priority_is_valid( initial_priority ) )
    299       return RTEMS_INVALID_PRIORITY;
    300   }
    301 
    302   core_priority = _RTEMS_tasks_Priority_to_Core( initial_priority );
    303 
    304 #if defined(RTEMS_MULTIPROCESSING)
    305   if ( _Attributes_Is_global( the_attribute_set ) ) {
    306 
    307     is_global = TRUE;
    308 
    309     if ( !_System_state_Is_multiprocessing )
    310       return RTEMS_MP_NOT_CONFIGURED;
    311 
    312   } else
    313     is_global = FALSE;
    314 #endif
    315 
    316   /*
    317    *  Make sure system is MP if this task is global
    318    */
    319 
    320   /*
    321    *  Disable dispatch for protection
    322    */
    323 
    324   _Thread_Disable_dispatch();
    325 
    326   /*
    327    *  Allocate the thread control block and -- if the task is global --
    328    *  allocate a global object control block.
    329    *
    330    *  NOTE:  This routine does not use the combined allocate and open
    331    *         global object routine because this results in a lack of
    332    *         control over when memory is allocated and can be freed in
    333    *         the event of an error.
    334    */
    335 
    336   the_thread = _RTEMS_tasks_Allocate();
    337 
    338   if ( !the_thread ) {
    339     _Thread_Enable_dispatch();
    340     return RTEMS_TOO_MANY;
    341   }
    342 
    343 #if defined(RTEMS_MULTIPROCESSING)
    344   if ( is_global ) {
    345     the_global_object = _Objects_MP_Allocate_global_object();
    346 
    347     if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
    348       _RTEMS_tasks_Free( the_thread );
    349       _Thread_Enable_dispatch();
    350       return RTEMS_TOO_MANY;
    351     }
    352   }
    353 #endif
    354 
    355   /*
    356    *  Initialize the core thread for this task.
    357    */
    358 
    359   status = _Thread_Initialize(
    360     &_RTEMS_tasks_Information,
    361     the_thread,
    362     NULL,
    363     stack_size,
    364     is_fp,
    365     core_priority,
    366     _Modes_Is_preempt(initial_modes)   ? TRUE : FALSE,
    367     _Modes_Is_timeslice(initial_modes) ?
    368       THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE :
    369       THREAD_CPU_BUDGET_ALGORITHM_NONE,
    370     NULL,        /* no budget algorithm callout */
    371     _Modes_Get_interrupt_level(initial_modes),
    372     &name
    373   );
    374 
    375   if ( !status ) {
    376 #if defined(RTEMS_MULTIPROCESSING)
    377     if ( is_global )
    378       _Objects_MP_Free_global_object( the_global_object );
    379 #endif
    380     _RTEMS_tasks_Free( the_thread );
    381     _Thread_Enable_dispatch();
    382     return RTEMS_UNSATISFIED;
    383   }
    384 
    385   api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    386   asr = &api->Signal;
    387  
    388   asr->is_enabled = _Modes_Is_asr_disabled(initial_modes) ? FALSE : TRUE;
    389 
    390   *id = the_thread->Object.id;
    391 
    392 #if defined(RTEMS_MULTIPROCESSING)
    393   if ( is_global ) {
    394 
    395     the_thread->is_global = TRUE;
    396 
    397     _Objects_MP_Open(
    398       &_RTEMS_tasks_Information,
    399       the_global_object,
    400       name,
    401       the_thread->Object.id
    402     );
    403 
    404     _RTEMS_tasks_MP_Send_process_packet(
    405       RTEMS_TASKS_MP_ANNOUNCE_CREATE,
    406       the_thread->Object.id,
    407       name
    408     );
    409 
    410    }
    411 #endif
    412 
    413   _Thread_Enable_dispatch();
    414   return RTEMS_SUCCESSFUL;
    415 }
    416 
    417 /*PAGE
    418  *
    419  *  rtems_task_ident
    420  *
    421  *  This directive returns the system ID associated with
    422  *  the thread name.
    423  *
    424  *  Input parameters:
    425  *    name - user defined thread name
    426  *    node - node(s) to be searched
    427  *    id   - pointer to thread id
    428  *
    429  *  Output parameters:
    430  *    *id               - thread id
    431  *    RTEMS_SUCCESSFUL - if successful
    432  *    error code        - if unsuccessful
    433  */
    434 
    435 rtems_status_code rtems_task_ident(
    436   rtems_name    name,
    437   unsigned32    node,
    438   Objects_Id   *id
    439 )
    440 {
    441   Objects_Name_to_id_errors  status;
    442 
    443   if ( name == OBJECTS_ID_OF_SELF ) {
    444     *id = _Thread_Executing->Object.id;
    445     return RTEMS_SUCCESSFUL;
    446    }
    447 
    448   status = _Objects_Name_to_id( &_RTEMS_tasks_Information, &name, node, id );
    449 
    450   return _Status_Object_name_errors_to_status[ status ];
    451 }
    452 
    453 /*PAGE
    454  *
    455  *  rtems_task_start
    456  *
    457  *  This directive readies the thread identified by the "id"
    458  *  based on its current priorty, to await execution.  A thread
    459  *  can be started only from the dormant state.
    460  *
    461  *  Input parameters:
    462  *    id          - thread id
    463  *    entry_point - start execution address of thread
    464  *    argument    - thread argument
    465  *
    466  *  Output parameters:
    467  *    RTEMS_SUCCESSFUL - if successful
    468  *    error code        - if unsuccessful
    469  */
    470 
    471 rtems_status_code rtems_task_start(
    472   rtems_id         id,
    473   rtems_task_entry entry_point,
    474   unsigned32       argument
    475 )
    476 {
    477   register Thread_Control *the_thread;
    478   Objects_Locations        location;
    479 
    480   if ( entry_point == NULL )
    481     return RTEMS_INVALID_ADDRESS;
    482 
    483   the_thread = _Thread_Get( id, &location );
    484   switch ( location ) {
    485 
    486     case OBJECTS_REMOTE:
    487 #if defined(RTEMS_MULTIPROCESSING)
    488       _Thread_Dispatch();
    489       return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
    490 #endif
    491 
    492     case OBJECTS_ERROR:
    493       return RTEMS_INVALID_ID;
    494 
    495     case OBJECTS_LOCAL:
    496       if ( _Thread_Start(
    497              the_thread, THREAD_START_NUMERIC, entry_point, NULL, argument ) ) {
    498         _Thread_Enable_dispatch();
    499         return RTEMS_SUCCESSFUL;
    500       }
    501       _Thread_Enable_dispatch();
    502       return RTEMS_INCORRECT_STATE;
    503   }
    504 
    505   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    506 }
    507 
    508 /*PAGE
    509  *
    510  *  rtems_task_restart
    511  *
    512  *  This directive readies the specified thread.  It restores
    513  *  the thread environment to the original values established
    514  *  at thread creation and start time.  A thread can be restarted
    515  *  from any state except the dormant state.
    516  *
    517  *  Input parameters:
    518  *    id       - thread id
    519  *    argument - thread argument
    520  *
    521  *  Output parameters:
    522  *    RTEMS_SUCCESSFUL - if successful
    523  *    error code        - if unsuccessful
    524  */
    525 
    526 rtems_status_code rtems_task_restart(
    527   Objects_Id id,
    528   unsigned32 argument
    529 )
    530 {
    531   register Thread_Control *the_thread;
    532   Objects_Locations        location;
    533 
    534   the_thread = _Thread_Get( id, &location );
    535   switch ( location ) {
    536 
    537     case OBJECTS_REMOTE:
    538 #if defined(RTEMS_MULTIPROCESSING)
    539       _Thread_Dispatch();
    540       return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
    541 #endif
    542 
    543     case OBJECTS_ERROR:
    544       return RTEMS_INVALID_ID;
    545 
    546     case OBJECTS_LOCAL:
    547       if ( _Thread_Restart( the_thread, NULL, argument ) ) {
    548         _Thread_Enable_dispatch();
    549         return RTEMS_SUCCESSFUL;
    550       }
    551       _Thread_Enable_dispatch();
    552       return RTEMS_INCORRECT_STATE;
    553   }
    554 
    555   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    556 }
    557 
    558 /*PAGE
    559  *
    560  *  rtems_task_delete
    561  *
    562  *  This directive allows a thread to delete itself or the thread
    563  *  identified in the id field.  The executive halts execution
    564  *  of the thread and frees the thread control block.
    565  *
    566  *  Input parameters:
    567  *    id - thread id
    568  *
    569  *  Output parameters:
    570  *    nothing           - if id is the requesting thread (always succeeds)
    571  *    RTEMS_SUCCESSFUL - if successful and id is
    572  *                           not the requesting thread
    573  *    error code        - if unsuccessful
    574  */
    575 
    576 rtems_status_code rtems_task_delete(
    577   Objects_Id id
    578 )
    579 {
    580   register Thread_Control *the_thread;
    581   Objects_Locations        location;
    582   Objects_Information     *the_information;
    583 
    584   the_thread = _Thread_Get( id, &location );
    585   switch ( location ) {
    586 
    587     case OBJECTS_REMOTE:
    588 #if defined(RTEMS_MULTIPROCESSING)
    589       _Thread_Dispatch();
    590       return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
    591 #endif
    592 
    593     case OBJECTS_ERROR:
    594       return RTEMS_INVALID_ID;
    595 
    596     case OBJECTS_LOCAL:
    597       the_information = _Objects_Get_information( the_thread->Object.id );
    598 
    599       if ( !the_information ) {
    600         _Thread_Enable_dispatch();
    601         return RTEMS_INVALID_ID;
    602         /* This should never happen if _Thread_Get() works right */
    603       }
    604  
    605       _Thread_Close( the_information, the_thread );
    606 
    607       _RTEMS_tasks_Free( the_thread );
    608 
    609 #if defined(RTEMS_MULTIPROCESSING)
    610       if ( the_thread->is_global ) {
    611 
    612         _Objects_MP_Close( &_RTEMS_tasks_Information, the_thread->Object.id );
    613 
    614         _RTEMS_tasks_MP_Send_process_packet(
    615           RTEMS_TASKS_MP_ANNOUNCE_DELETE,
    616           the_thread->Object.id,
    617           0                                /* Not used */
    618         );
    619       }
    620 #endif
    621 
    622       _Thread_Enable_dispatch();
    623       return RTEMS_SUCCESSFUL;
    624   }
    625 
    626   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    627 }
    628 
    629 /*PAGE
    630  *
    631  *  rtems_task_suspend
    632  *
    633  *  This directive will place the specified thread in the "suspended"
    634  *  state.  Note that the suspended state can be in addition to
    635  *  other waiting states.
    636  *
    637  *  Input parameters:
    638  *    id - thread id
    639  *
    640  *  Output parameters:
    641  *    RTEMS_SUCCESSFUL - if successful
    642  *    error code        - if unsuccessful
    643  */
    644 
    645 rtems_status_code rtems_task_suspend(
    646   Objects_Id id
    647 )
    648 {
    649   register Thread_Control *the_thread;
    650   Objects_Locations               location;
    651 
    652   the_thread = _Thread_Get( id, &location );
    653   switch ( location ) {
    654 
    655     case OBJECTS_REMOTE:
    656 #if defined(RTEMS_MULTIPROCESSING)
    657       return _RTEMS_tasks_MP_Send_request_packet(
    658         RTEMS_TASKS_MP_SUSPEND_REQUEST,
    659         id,
    660         0,          /* Not used */
    661         0,          /* Not used */
    662         0           /* Not used */
    663       );
    664 #endif
    665 
    666     case OBJECTS_ERROR:
    667       return RTEMS_INVALID_ID;
    668 
    669     case OBJECTS_LOCAL:
    670       if ( !_States_Is_suspended( the_thread->current_state ) ) {
    671         _Thread_Set_state( the_thread, STATES_SUSPENDED );
    672         _Thread_Enable_dispatch();
    673         return RTEMS_SUCCESSFUL;
    674       }
    675       _Thread_Enable_dispatch();
    676       return RTEMS_ALREADY_SUSPENDED;
    677   }
    678 
    679   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    680 }
    681 
    682 /*PAGE
    683  *
    684  *  rtems_task_resume
    685  *
    686  *  This directive will remove the specified thread
    687  *  from the suspended state.
    688  *
    689  *  Input parameters:
    690  *    id - thread id
    691  *
    692  *  Output parameters:
    693  *    RTEMS_SUCCESSFUL - if successful
    694  *    error code        - if unsuccessful
    695  */
    696 
    697 rtems_status_code rtems_task_resume(
    698   Objects_Id id
    699 )
    700 {
    701   register Thread_Control *the_thread;
    702   Objects_Locations        location;
    703 
    704   the_thread = _Thread_Get( id, &location );
    705   switch ( location ) {
    706 
    707     case OBJECTS_REMOTE:
    708 #if defined(RTEMS_MULTIPROCESSING)
    709       return _RTEMS_tasks_MP_Send_request_packet(
    710           RTEMS_TASKS_MP_RESUME_REQUEST,
    711           id,
    712           0,          /* Not used */
    713           0,          /* Not used */
    714           0           /* Not used */
    715         );
    716 #endif
    717 
    718     case OBJECTS_ERROR:
    719       return RTEMS_INVALID_ID;
    720 
    721     case OBJECTS_LOCAL:
    722       if ( _States_Is_suspended( the_thread->current_state ) ) {
    723         _Thread_Resume( the_thread );
    724         _Thread_Enable_dispatch();
    725         return RTEMS_SUCCESSFUL;
    726       }
    727       _Thread_Enable_dispatch();
    728       return RTEMS_INCORRECT_STATE;
    729   }
    730 
    731   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    732 }
    733 
    734 /*PAGE
    735  *
    736  *  rtems_task_set_priority
    737  *
    738  *  This directive changes the priority of the specified thread.
    739  *  The specified thread can be any thread in the system including
    740  *  the requesting thread.
    741  *
    742  *  Input parameters:
    743  *    id           - thread id (0 indicates requesting thread)
    744  *    new_priority - thread priority (0 indicates current priority)
    745  *    old_priority - pointer to previous priority
    746  *
    747  *  Output parameters:
    748  *    old_priority      - previous priority
    749  *    RTEMS_SUCCESSFUL - if successful
    750  *    error code        - if unsuccessful
    751  */
    752 
    753 rtems_status_code rtems_task_set_priority(
    754   Objects_Id           id,
    755   rtems_task_priority  new_priority,
    756   rtems_task_priority *old_priority
    757 )
    758 {
    759   register Thread_Control *the_thread;
    760   Objects_Locations               location;
    761 
    762   if ( new_priority != RTEMS_CURRENT_PRIORITY &&
    763        !_RTEMS_tasks_Priority_is_valid( new_priority ) )
    764     return RTEMS_INVALID_PRIORITY;
    765 
    766   the_thread = _Thread_Get( id, &location );
    767   switch ( location ) {
    768 
    769     case OBJECTS_REMOTE:
    770 #if defined(RTEMS_MULTIPROCESSING)
    771       _Thread_Executing->Wait.return_argument = old_priority;
    772       return _RTEMS_tasks_MP_Send_request_packet(
    773           RTEMS_TASKS_MP_SET_PRIORITY_REQUEST,
    774           id,
    775           new_priority,
    776           0,          /* Not used */
    777           0           /* Not used */
    778       );
    779 #endif
    780 
    781     case OBJECTS_ERROR:
    782       return RTEMS_INVALID_ID;
    783 
    784     case OBJECTS_LOCAL:
    785       *old_priority = the_thread->current_priority;
    786       if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
    787         the_thread->real_priority = new_priority;
    788         if ( the_thread->resource_count == 0 ||
    789              the_thread->current_priority > new_priority )
    790           _Thread_Change_priority( the_thread, new_priority, FALSE );
    791       }
    792       _Thread_Enable_dispatch();
    793       return RTEMS_SUCCESSFUL;
    794   }
    795 
    796   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    797 }
    798 
    799 /*PAGE
    800  *
    801  *  rtems_task_mode
    802  *
    803  *  This directive enables and disables several modes of
    804  *  execution for the requesting thread.
    805  *
    806  *  Input parameters:
    807  *    mode_set          - new mode
    808  *    mask              - mask
    809  *    previous_mode_set - address of previous mode set
    810  *
    811  *  Output:
    812  *    *previous_mode_set - previous mode set
    813  *     always return RTEMS_SUCCESSFUL;
    814  */
    815 
    816 rtems_status_code rtems_task_mode(
    817   rtems_mode  mode_set,
    818   rtems_mode  mask,
    819   rtems_mode *previous_mode_set
    820 )
    821 {
    822   Thread_Control     *executing;
    823   RTEMS_API_Control  *api;
    824   ASR_Information    *asr;
    825   boolean             is_asr_enabled = FALSE;
    826   boolean             needs_asr_dispatching = FALSE;
    827   rtems_mode          old_mode;
    828 
    829   executing     = _Thread_Executing;
    830   api = executing->API_Extensions[ THREAD_API_RTEMS ];
    831   asr = &api->Signal;
    832 
    833   old_mode  = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;
    834 
    835   if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE )
    836     old_mode |= RTEMS_NO_TIMESLICE;
    837   else
    838     old_mode |= RTEMS_TIMESLICE;
    839 
    840   old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR;
    841   old_mode |= _ISR_Get_level();
    842 
    843   *previous_mode_set = old_mode;
    844 
    845   /*
    846    *  These are generic thread scheduling characteristics.
    847    */
    848 
    849   if ( mask & RTEMS_PREEMPT_MASK )
    850     executing->is_preemptible = _Modes_Is_preempt(mode_set) ? TRUE : FALSE;
    851 
    852   if ( mask & RTEMS_TIMESLICE_MASK ) {
    853     if ( _Modes_Is_timeslice(mode_set) )
    854       executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
    855     else
    856       executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    857   }
    858 
    859   /*
    860    *  Set the new interrupt level
    861    */
    862 
    863   if ( mask & RTEMS_INTERRUPT_MASK )
    864     _Modes_Set_interrupt_level( mode_set );
    865 
    866   /*
    867    *  This is specific to the RTEMS API
    868    */
    869 
    870   is_asr_enabled = FALSE;
    871   needs_asr_dispatching = FALSE;
    872 
    873   if ( mask & RTEMS_ASR_MASK ) {
    874     is_asr_enabled = _Modes_Is_asr_disabled( mode_set ) ? FALSE : TRUE;
    875     if ( is_asr_enabled != asr->is_enabled ) {
    876       asr->is_enabled = is_asr_enabled;
    877       _ASR_Swap_signals( asr );
    878       if ( _ASR_Are_signals_pending( asr ) ) {
    879         needs_asr_dispatching = TRUE;
    880         executing->do_post_task_switch_extension = TRUE;
    881       }
    882     }
    883   }
    884 
    885   if ( _Thread_Evaluate_mode() || needs_asr_dispatching )
    886     _Thread_Dispatch();
    887 
    888   return RTEMS_SUCCESSFUL;
    889 }
    890 
    891 /*PAGE
    892  *
    893  *  rtems_task_get_note
    894  *
    895  *  This directive obtains the note from the specified notepad
    896  *  of the specified thread.
    897  *
    898  *  Input parameters:
    899  *    id      - thread id
    900  *    notepad - notepad number
    901  *    note    - pointer to note
    902  *
    903  *  Output parameters:
    904  *    note              - filled in if successful
    905  *    RTEMS_SUCCESSFUL - if successful
    906  *    error code        - if unsuccessful
    907  */
    908 
    909 rtems_status_code rtems_task_get_note(
    910   Objects_Id  id,
    911   unsigned32  notepad,
    912   unsigned32 *note
    913 )
    914 {
    915   register Thread_Control *the_thread;
    916   Objects_Locations        location;
    917   RTEMS_API_Control       *api;
    918 
    919   /*
    920    *  NOTE:  There is no check for < RTEMS_NOTEPAD_FIRST because that would
    921    *         be checking an unsigned number for being negative.
    922    */
    923 
    924   if ( notepad > RTEMS_NOTEPAD_LAST )
    925     return RTEMS_INVALID_NUMBER;
    926 
    927   /*
    928    *  Optimize the most likely case to avoid the Thread_Dispatch.
    929    */
    930 
    931   if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ||
    932        _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) {
    933       api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
    934       *note = api->Notepads[ notepad ];
    935       return RTEMS_SUCCESSFUL;
    936   }
    937 
    938   the_thread = _Thread_Get( id, &location );
    939   switch ( location ) {
    940 
    941     case OBJECTS_REMOTE:
    942 #if defined(RTEMS_MULTIPROCESSING)
    943       _Thread_Executing->Wait.return_argument = note;
    944 
    945       return _RTEMS_tasks_MP_Send_request_packet(
    946         RTEMS_TASKS_MP_GET_NOTE_REQUEST,
    947         id,
    948         0,          /* Not used */
    949         notepad,
    950         0           /* Not used */
    951       );
    952 #endif
    953 
    954     case OBJECTS_ERROR:
    955       return RTEMS_INVALID_ID;
    956 
    957     case OBJECTS_LOCAL:
    958       api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    959       *note = api->Notepads[ notepad ];
    960       _Thread_Enable_dispatch();
    961       return RTEMS_SUCCESSFUL;
    962   }
    963 
    964   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    965 }
    966 
    967 /*PAGE
    968  *
    969  * rtems_task_set_note
    970  *
    971  *  This directive sets the specified notepad contents to the given
    972  *  note.
    973  *
    974  *  Input parameters:
    975  *    id      - thread id
    976  *    notepad - notepad number
    977  *    note    - note value
    978  *
    979  *  Output parameters:
    980  *    RTEMS_SUCCESSFUL - if successful
    981  *    error code        - if unsuccessful
    982  */
    983 
    984 rtems_status_code rtems_task_set_note(
    985   Objects_Id id,
    986   unsigned32 notepad,
    987   unsigned32 note
    988 )
    989 {
    990   register Thread_Control *the_thread;
    991   Objects_Locations        location;
    992   RTEMS_API_Control       *api;
    993 
    994   /*
    995    *  NOTE:  There is no check for < RTEMS_NOTEPAD_FIRST because that would
    996    *         be checking an unsigned number for being negative.
    997    */
    998 
    999   if ( notepad > RTEMS_NOTEPAD_LAST )
    1000     return RTEMS_INVALID_NUMBER;
    1001 
    1002   /*
    1003    *  Optimize the most likely case to avoid the Thread_Dispatch.
    1004    */
    1005 
    1006   if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ||
    1007        _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) {
    1008       api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
    1009       api->Notepads[ notepad ] = note;
    1010       return RTEMS_SUCCESSFUL;
    1011   }
    1012 
    1013   the_thread = _Thread_Get( id, &location );
    1014   switch ( location ) {
    1015 
    1016     case OBJECTS_REMOTE:
    1017 #if defined(RTEMS_MULTIPROCESSING)
    1018       return _RTEMS_tasks_MP_Send_request_packet(
    1019         RTEMS_TASKS_MP_SET_NOTE_REQUEST,
    1020         id,
    1021         0,          /* Not used */
    1022         notepad,
    1023         note
    1024       );
    1025 #endif
    1026 
    1027     case OBJECTS_ERROR:
    1028       return RTEMS_INVALID_ID;
    1029 
    1030     case OBJECTS_LOCAL:
    1031       api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    1032       api->Notepads[ notepad ] = note;
    1033       _Thread_Enable_dispatch();
    1034       return RTEMS_SUCCESSFUL;
    1035   }
    1036 
    1037   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    1038 }
    1039 
    1040 /*PAGE
    1041  *
    1042  *  rtems_task_wake_after
    1043  *
    1044  *  This directive suspends the requesting thread for the given amount
    1045  *  of ticks.
    1046  *
    1047  *  Input parameters:
    1048  *    ticks - number of ticks to wait
    1049  *
    1050  *  Output parameters:
    1051  *    RTEMS_SUCCESSFUL - always successful
    1052  */
    1053 
    1054 rtems_status_code rtems_task_wake_after(
    1055   rtems_interval ticks
    1056 )
    1057 {
    1058   _Thread_Disable_dispatch();
    1059     if ( ticks == 0 ) {
    1060       _Thread_Yield_processor();
    1061     } else {
    1062       _Thread_Set_state( _Thread_Executing, STATES_DELAYING );
    1063       _Watchdog_Initialize(
    1064         &_Thread_Executing->Timer,
    1065         _Thread_Delay_ended,
    1066         _Thread_Executing->Object.id,
    1067         NULL
    1068       );
    1069       _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
    1070     }
    1071   _Thread_Enable_dispatch();
    1072   return RTEMS_SUCCESSFUL;
    1073 }
    1074 
    1075 /*PAGE
    1076  *
    1077  *  rtems_task_wake_when
    1078  *
    1079  *  This directive blocks the requesting thread until the given date and
    1080  *  time is reached.
    1081  *
    1082  *  Input parameters:
    1083  *    time_buffer - pointer to the time and date structure
    1084  *
    1085  *  Output parameters:
    1086  *    RTEMS_SUCCESSFUL - if successful
    1087  *    error code        - if unsuccessful
    1088  */
    1089 
    1090 rtems_status_code rtems_task_wake_when(
    1091 rtems_time_of_day *time_buffer
    1092 )
    1093 {
    1094   Watchdog_Interval   seconds;
    1095 
    1096   if ( !_TOD_Is_set )
    1097     return RTEMS_NOT_DEFINED;
    1098 
    1099   time_buffer->ticks = 0;
    1100 
    1101   if ( !_TOD_Validate( time_buffer ) )
    1102     return RTEMS_INVALID_CLOCK;
    1103 
    1104   seconds = _TOD_To_seconds( time_buffer );
    1105 
    1106   if ( seconds <= _TOD_Seconds_since_epoch )
    1107     return RTEMS_INVALID_CLOCK;
    1108 
    1109   _Thread_Disable_dispatch();
    1110     _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_TIME );
    1111     _Watchdog_Initialize(
    1112       &_Thread_Executing->Timer,
    1113       _Thread_Delay_ended,
    1114       _Thread_Executing->Object.id,
    1115       NULL
    1116     );
    1117     _Watchdog_Insert_seconds(
    1118       &_Thread_Executing->Timer,
    1119       seconds - _TOD_Seconds_since_epoch
    1120     );
    1121   _Thread_Enable_dispatch();
    1122   return RTEMS_SUCCESSFUL;
    1123 }
    1124 
    1125 /*PAGE
    1126  *
    1127  *  _RTEMS_tasks_Initialize_user_tasks
    1128  *
    1129  *  This routine creates and starts all configured user
    1130  *  initialzation threads.
    1131  *
    1132  *  Input parameters: NONE
    1133  *
    1134  *  Output parameters:  NONE
    1135  */
    1136 
    1137 void _RTEMS_tasks_Initialize_user_tasks( void )
    1138 {
    1139   unsigned32                        index;
    1140   unsigned32                        maximum;
    1141   rtems_id                          id;
    1142   rtems_status_code                 return_value;
    1143   rtems_initialization_tasks_table *user_tasks;
    1144 
    1145   /*
    1146    *  NOTE:  This is slightly different from the Ada implementation.
    1147    */
    1148 
    1149   user_tasks = _RTEMS_tasks_User_initialization_tasks;
    1150   maximum    = _RTEMS_tasks_Number_of_initialization_tasks;
    1151 
    1152   if ( !user_tasks || maximum == 0 )
    1153     return;
    1154 
    1155   for ( index=0 ; index < maximum ; index++ ) {
    1156     return_value = rtems_task_create(
    1157       user_tasks[ index ].name,
    1158       user_tasks[ index ].initial_priority,
    1159       user_tasks[ index ].stack_size,
    1160       user_tasks[ index ].mode_set,
    1161       user_tasks[ index ].attribute_set,
    1162       &id
    1163     );
    1164 
    1165     if ( !rtems_is_status_successful( return_value ) )
    1166       _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, return_value );
    1167 
    1168     return_value = rtems_task_start(
    1169       id,
    1170       user_tasks[ index ].entry_point,
    1171       user_tasks[ index ].argument
    1172     );
    1173 
    1174     if ( !rtems_is_status_successful( return_value ) )
    1175       _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, return_value );
    1176   }
    1177 }
    1178 
  • cpukit/rtems/src/tasks.c

    r05df0a8 rc4d69e2  
    216216}
    217217
    218 /*PAGE
    219  *
    220  *  rtems_task_create
    221  *
    222  *  This directive creates a thread by allocating and initializing a
    223  *  thread control block and a stack.  The newly created thread is
    224  *  placed in the dormant state.
    225  *
    226  *  Input parameters:
    227  *    name             - user defined thread name
    228  *    initial_priority - thread priority
    229  *    stack_size       - stack size in bytes
    230  *    initial_modes    - initial thread mode
    231  *    attribute_set    - thread attributes
    232  *    id               - pointer to thread id
    233  *
    234  *  Output parameters:
    235  *    id                - thread id
    236  *    RTEMS_SUCCESSFUL - if successful
    237  *    error code        - if unsuccessful
    238  */
    239 
    240 rtems_status_code rtems_task_create(
    241   rtems_name           name,
    242   rtems_task_priority  initial_priority,
    243   unsigned32           stack_size,
    244   rtems_mode           initial_modes,
    245   rtems_attribute      attribute_set,
    246   Objects_Id          *id
    247 )
    248 {
    249   register Thread_Control *the_thread;
    250   boolean                  is_fp;
    251 #if defined(RTEMS_MULTIPROCESSING)
    252   Objects_MP_Control      *the_global_object = NULL;
    253   boolean                  is_global;
    254 #endif
    255   boolean                  status;
    256   rtems_attribute          the_attribute_set;
    257   Priority_Control         core_priority;
    258   RTEMS_API_Control       *api;
    259   ASR_Information         *asr;
    260  
    261 
    262   if ( !rtems_is_name_valid( name ) )
    263     return RTEMS_INVALID_NAME;
    264 
    265   /*
    266    *  Core Thread Initialize insures we get the minimum amount of
    267    *  stack space.
    268    */
    269 
    270 #if 0
    271   if ( !_Stack_Is_enough( stack_size ) )
    272     return RTEMS_INVALID_SIZE;
    273 #endif
    274 
    275   /*
    276    *  Fix the attribute set to match the attributes which
    277    *  this processor (1) requires and (2) is able to support.
    278    *  First add in the required flags for attribute_set
    279    *  Typically this might include FP if the platform
    280    *  or application required all tasks to be fp aware.
    281    *  Then turn off the requested bits which are not supported.
    282    */
    283 
    284   the_attribute_set = _Attributes_Set( attribute_set, ATTRIBUTES_REQUIRED );
    285   the_attribute_set =
    286     _Attributes_Clear( the_attribute_set, ATTRIBUTES_NOT_SUPPORTED );
    287 
    288   if ( _Attributes_Is_floating_point( the_attribute_set ) )
    289     is_fp = TRUE;
    290   else
    291     is_fp = FALSE;
    292 
    293   /*
    294    *  Validate the RTEMS API priority and convert it to the core priority range.
    295    */
    296 
    297   if ( !_Attributes_Is_system_task( the_attribute_set ) ) {
    298     if ( !_RTEMS_tasks_Priority_is_valid( initial_priority ) )
    299       return RTEMS_INVALID_PRIORITY;
    300   }
    301 
    302   core_priority = _RTEMS_tasks_Priority_to_Core( initial_priority );
    303 
    304 #if defined(RTEMS_MULTIPROCESSING)
    305   if ( _Attributes_Is_global( the_attribute_set ) ) {
    306 
    307     is_global = TRUE;
    308 
    309     if ( !_System_state_Is_multiprocessing )
    310       return RTEMS_MP_NOT_CONFIGURED;
    311 
    312   } else
    313     is_global = FALSE;
    314 #endif
    315 
    316   /*
    317    *  Make sure system is MP if this task is global
    318    */
    319 
    320   /*
    321    *  Disable dispatch for protection
    322    */
    323 
    324   _Thread_Disable_dispatch();
    325 
    326   /*
    327    *  Allocate the thread control block and -- if the task is global --
    328    *  allocate a global object control block.
    329    *
    330    *  NOTE:  This routine does not use the combined allocate and open
    331    *         global object routine because this results in a lack of
    332    *         control over when memory is allocated and can be freed in
    333    *         the event of an error.
    334    */
    335 
    336   the_thread = _RTEMS_tasks_Allocate();
    337 
    338   if ( !the_thread ) {
    339     _Thread_Enable_dispatch();
    340     return RTEMS_TOO_MANY;
    341   }
    342 
    343 #if defined(RTEMS_MULTIPROCESSING)
    344   if ( is_global ) {
    345     the_global_object = _Objects_MP_Allocate_global_object();
    346 
    347     if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
    348       _RTEMS_tasks_Free( the_thread );
    349       _Thread_Enable_dispatch();
    350       return RTEMS_TOO_MANY;
    351     }
    352   }
    353 #endif
    354 
    355   /*
    356    *  Initialize the core thread for this task.
    357    */
    358 
    359   status = _Thread_Initialize(
    360     &_RTEMS_tasks_Information,
    361     the_thread,
    362     NULL,
    363     stack_size,
    364     is_fp,
    365     core_priority,
    366     _Modes_Is_preempt(initial_modes)   ? TRUE : FALSE,
    367     _Modes_Is_timeslice(initial_modes) ?
    368       THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE :
    369       THREAD_CPU_BUDGET_ALGORITHM_NONE,
    370     NULL,        /* no budget algorithm callout */
    371     _Modes_Get_interrupt_level(initial_modes),
    372     &name
    373   );
    374 
    375   if ( !status ) {
    376 #if defined(RTEMS_MULTIPROCESSING)
    377     if ( is_global )
    378       _Objects_MP_Free_global_object( the_global_object );
    379 #endif
    380     _RTEMS_tasks_Free( the_thread );
    381     _Thread_Enable_dispatch();
    382     return RTEMS_UNSATISFIED;
    383   }
    384 
    385   api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    386   asr = &api->Signal;
    387  
    388   asr->is_enabled = _Modes_Is_asr_disabled(initial_modes) ? FALSE : TRUE;
    389 
    390   *id = the_thread->Object.id;
    391 
    392 #if defined(RTEMS_MULTIPROCESSING)
    393   if ( is_global ) {
    394 
    395     the_thread->is_global = TRUE;
    396 
    397     _Objects_MP_Open(
    398       &_RTEMS_tasks_Information,
    399       the_global_object,
    400       name,
    401       the_thread->Object.id
    402     );
    403 
    404     _RTEMS_tasks_MP_Send_process_packet(
    405       RTEMS_TASKS_MP_ANNOUNCE_CREATE,
    406       the_thread->Object.id,
    407       name
    408     );
    409 
    410    }
    411 #endif
    412 
    413   _Thread_Enable_dispatch();
    414   return RTEMS_SUCCESSFUL;
    415 }
    416 
    417 /*PAGE
    418  *
    419  *  rtems_task_ident
    420  *
    421  *  This directive returns the system ID associated with
    422  *  the thread name.
    423  *
    424  *  Input parameters:
    425  *    name - user defined thread name
    426  *    node - node(s) to be searched
    427  *    id   - pointer to thread id
    428  *
    429  *  Output parameters:
    430  *    *id               - thread id
    431  *    RTEMS_SUCCESSFUL - if successful
    432  *    error code        - if unsuccessful
    433  */
    434 
    435 rtems_status_code rtems_task_ident(
    436   rtems_name    name,
    437   unsigned32    node,
    438   Objects_Id   *id
    439 )
    440 {
    441   Objects_Name_to_id_errors  status;
    442 
    443   if ( name == OBJECTS_ID_OF_SELF ) {
    444     *id = _Thread_Executing->Object.id;
    445     return RTEMS_SUCCESSFUL;
    446    }
    447 
    448   status = _Objects_Name_to_id( &_RTEMS_tasks_Information, &name, node, id );
    449 
    450   return _Status_Object_name_errors_to_status[ status ];
    451 }
    452 
    453 /*PAGE
    454  *
    455  *  rtems_task_start
    456  *
    457  *  This directive readies the thread identified by the "id"
    458  *  based on its current priorty, to await execution.  A thread
    459  *  can be started only from the dormant state.
    460  *
    461  *  Input parameters:
    462  *    id          - thread id
    463  *    entry_point - start execution address of thread
    464  *    argument    - thread argument
    465  *
    466  *  Output parameters:
    467  *    RTEMS_SUCCESSFUL - if successful
    468  *    error code        - if unsuccessful
    469  */
    470 
    471 rtems_status_code rtems_task_start(
    472   rtems_id         id,
    473   rtems_task_entry entry_point,
    474   unsigned32       argument
    475 )
    476 {
    477   register Thread_Control *the_thread;
    478   Objects_Locations        location;
    479 
    480   if ( entry_point == NULL )
    481     return RTEMS_INVALID_ADDRESS;
    482 
    483   the_thread = _Thread_Get( id, &location );
    484   switch ( location ) {
    485 
    486     case OBJECTS_REMOTE:
    487 #if defined(RTEMS_MULTIPROCESSING)
    488       _Thread_Dispatch();
    489       return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
    490 #endif
    491 
    492     case OBJECTS_ERROR:
    493       return RTEMS_INVALID_ID;
    494 
    495     case OBJECTS_LOCAL:
    496       if ( _Thread_Start(
    497              the_thread, THREAD_START_NUMERIC, entry_point, NULL, argument ) ) {
    498         _Thread_Enable_dispatch();
    499         return RTEMS_SUCCESSFUL;
    500       }
    501       _Thread_Enable_dispatch();
    502       return RTEMS_INCORRECT_STATE;
    503   }
    504 
    505   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    506 }
    507 
    508 /*PAGE
    509  *
    510  *  rtems_task_restart
    511  *
    512  *  This directive readies the specified thread.  It restores
    513  *  the thread environment to the original values established
    514  *  at thread creation and start time.  A thread can be restarted
    515  *  from any state except the dormant state.
    516  *
    517  *  Input parameters:
    518  *    id       - thread id
    519  *    argument - thread argument
    520  *
    521  *  Output parameters:
    522  *    RTEMS_SUCCESSFUL - if successful
    523  *    error code        - if unsuccessful
    524  */
    525 
    526 rtems_status_code rtems_task_restart(
    527   Objects_Id id,
    528   unsigned32 argument
    529 )
    530 {
    531   register Thread_Control *the_thread;
    532   Objects_Locations        location;
    533 
    534   the_thread = _Thread_Get( id, &location );
    535   switch ( location ) {
    536 
    537     case OBJECTS_REMOTE:
    538 #if defined(RTEMS_MULTIPROCESSING)
    539       _Thread_Dispatch();
    540       return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
    541 #endif
    542 
    543     case OBJECTS_ERROR:
    544       return RTEMS_INVALID_ID;
    545 
    546     case OBJECTS_LOCAL:
    547       if ( _Thread_Restart( the_thread, NULL, argument ) ) {
    548         _Thread_Enable_dispatch();
    549         return RTEMS_SUCCESSFUL;
    550       }
    551       _Thread_Enable_dispatch();
    552       return RTEMS_INCORRECT_STATE;
    553   }
    554 
    555   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    556 }
    557 
    558 /*PAGE
    559  *
    560  *  rtems_task_delete
    561  *
    562  *  This directive allows a thread to delete itself or the thread
    563  *  identified in the id field.  The executive halts execution
    564  *  of the thread and frees the thread control block.
    565  *
    566  *  Input parameters:
    567  *    id - thread id
    568  *
    569  *  Output parameters:
    570  *    nothing           - if id is the requesting thread (always succeeds)
    571  *    RTEMS_SUCCESSFUL - if successful and id is
    572  *                           not the requesting thread
    573  *    error code        - if unsuccessful
    574  */
    575 
    576 rtems_status_code rtems_task_delete(
    577   Objects_Id id
    578 )
    579 {
    580   register Thread_Control *the_thread;
    581   Objects_Locations        location;
    582   Objects_Information     *the_information;
    583 
    584   the_thread = _Thread_Get( id, &location );
    585   switch ( location ) {
    586 
    587     case OBJECTS_REMOTE:
    588 #if defined(RTEMS_MULTIPROCESSING)
    589       _Thread_Dispatch();
    590       return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
    591 #endif
    592 
    593     case OBJECTS_ERROR:
    594       return RTEMS_INVALID_ID;
    595 
    596     case OBJECTS_LOCAL:
    597       the_information = _Objects_Get_information( the_thread->Object.id );
    598 
    599       if ( !the_information ) {
    600         _Thread_Enable_dispatch();
    601         return RTEMS_INVALID_ID;
    602         /* This should never happen if _Thread_Get() works right */
    603       }
    604  
    605       _Thread_Close( the_information, the_thread );
    606 
    607       _RTEMS_tasks_Free( the_thread );
    608 
    609 #if defined(RTEMS_MULTIPROCESSING)
    610       if ( the_thread->is_global ) {
    611 
    612         _Objects_MP_Close( &_RTEMS_tasks_Information, the_thread->Object.id );
    613 
    614         _RTEMS_tasks_MP_Send_process_packet(
    615           RTEMS_TASKS_MP_ANNOUNCE_DELETE,
    616           the_thread->Object.id,
    617           0                                /* Not used */
    618         );
    619       }
    620 #endif
    621 
    622       _Thread_Enable_dispatch();
    623       return RTEMS_SUCCESSFUL;
    624   }
    625 
    626   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    627 }
    628 
    629 /*PAGE
    630  *
    631  *  rtems_task_suspend
    632  *
    633  *  This directive will place the specified thread in the "suspended"
    634  *  state.  Note that the suspended state can be in addition to
    635  *  other waiting states.
    636  *
    637  *  Input parameters:
    638  *    id - thread id
    639  *
    640  *  Output parameters:
    641  *    RTEMS_SUCCESSFUL - if successful
    642  *    error code        - if unsuccessful
    643  */
    644 
    645 rtems_status_code rtems_task_suspend(
    646   Objects_Id id
    647 )
    648 {
    649   register Thread_Control *the_thread;
    650   Objects_Locations               location;
    651 
    652   the_thread = _Thread_Get( id, &location );
    653   switch ( location ) {
    654 
    655     case OBJECTS_REMOTE:
    656 #if defined(RTEMS_MULTIPROCESSING)
    657       return _RTEMS_tasks_MP_Send_request_packet(
    658         RTEMS_TASKS_MP_SUSPEND_REQUEST,
    659         id,
    660         0,          /* Not used */
    661         0,          /* Not used */
    662         0           /* Not used */
    663       );
    664 #endif
    665 
    666     case OBJECTS_ERROR:
    667       return RTEMS_INVALID_ID;
    668 
    669     case OBJECTS_LOCAL:
    670       if ( !_States_Is_suspended( the_thread->current_state ) ) {
    671         _Thread_Set_state( the_thread, STATES_SUSPENDED );
    672         _Thread_Enable_dispatch();
    673         return RTEMS_SUCCESSFUL;
    674       }
    675       _Thread_Enable_dispatch();
    676       return RTEMS_ALREADY_SUSPENDED;
    677   }
    678 
    679   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    680 }
    681 
    682 /*PAGE
    683  *
    684  *  rtems_task_resume
    685  *
    686  *  This directive will remove the specified thread
    687  *  from the suspended state.
    688  *
    689  *  Input parameters:
    690  *    id - thread id
    691  *
    692  *  Output parameters:
    693  *    RTEMS_SUCCESSFUL - if successful
    694  *    error code        - if unsuccessful
    695  */
    696 
    697 rtems_status_code rtems_task_resume(
    698   Objects_Id id
    699 )
    700 {
    701   register Thread_Control *the_thread;
    702   Objects_Locations        location;
    703 
    704   the_thread = _Thread_Get( id, &location );
    705   switch ( location ) {
    706 
    707     case OBJECTS_REMOTE:
    708 #if defined(RTEMS_MULTIPROCESSING)
    709       return _RTEMS_tasks_MP_Send_request_packet(
    710           RTEMS_TASKS_MP_RESUME_REQUEST,
    711           id,
    712           0,          /* Not used */
    713           0,          /* Not used */
    714           0           /* Not used */
    715         );
    716 #endif
    717 
    718     case OBJECTS_ERROR:
    719       return RTEMS_INVALID_ID;
    720 
    721     case OBJECTS_LOCAL:
    722       if ( _States_Is_suspended( the_thread->current_state ) ) {
    723         _Thread_Resume( the_thread );
    724         _Thread_Enable_dispatch();
    725         return RTEMS_SUCCESSFUL;
    726       }
    727       _Thread_Enable_dispatch();
    728       return RTEMS_INCORRECT_STATE;
    729   }
    730 
    731   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    732 }
    733 
    734 /*PAGE
    735  *
    736  *  rtems_task_set_priority
    737  *
    738  *  This directive changes the priority of the specified thread.
    739  *  The specified thread can be any thread in the system including
    740  *  the requesting thread.
    741  *
    742  *  Input parameters:
    743  *    id           - thread id (0 indicates requesting thread)
    744  *    new_priority - thread priority (0 indicates current priority)
    745  *    old_priority - pointer to previous priority
    746  *
    747  *  Output parameters:
    748  *    old_priority      - previous priority
    749  *    RTEMS_SUCCESSFUL - if successful
    750  *    error code        - if unsuccessful
    751  */
    752 
    753 rtems_status_code rtems_task_set_priority(
    754   Objects_Id           id,
    755   rtems_task_priority  new_priority,
    756   rtems_task_priority *old_priority
    757 )
    758 {
    759   register Thread_Control *the_thread;
    760   Objects_Locations               location;
    761 
    762   if ( new_priority != RTEMS_CURRENT_PRIORITY &&
    763        !_RTEMS_tasks_Priority_is_valid( new_priority ) )
    764     return RTEMS_INVALID_PRIORITY;
    765 
    766   the_thread = _Thread_Get( id, &location );
    767   switch ( location ) {
    768 
    769     case OBJECTS_REMOTE:
    770 #if defined(RTEMS_MULTIPROCESSING)
    771       _Thread_Executing->Wait.return_argument = old_priority;
    772       return _RTEMS_tasks_MP_Send_request_packet(
    773           RTEMS_TASKS_MP_SET_PRIORITY_REQUEST,
    774           id,
    775           new_priority,
    776           0,          /* Not used */
    777           0           /* Not used */
    778       );
    779 #endif
    780 
    781     case OBJECTS_ERROR:
    782       return RTEMS_INVALID_ID;
    783 
    784     case OBJECTS_LOCAL:
    785       *old_priority = the_thread->current_priority;
    786       if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
    787         the_thread->real_priority = new_priority;
    788         if ( the_thread->resource_count == 0 ||
    789              the_thread->current_priority > new_priority )
    790           _Thread_Change_priority( the_thread, new_priority, FALSE );
    791       }
    792       _Thread_Enable_dispatch();
    793       return RTEMS_SUCCESSFUL;
    794   }
    795 
    796   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    797 }
    798 
    799 /*PAGE
    800  *
    801  *  rtems_task_mode
    802  *
    803  *  This directive enables and disables several modes of
    804  *  execution for the requesting thread.
    805  *
    806  *  Input parameters:
    807  *    mode_set          - new mode
    808  *    mask              - mask
    809  *    previous_mode_set - address of previous mode set
    810  *
    811  *  Output:
    812  *    *previous_mode_set - previous mode set
    813  *     always return RTEMS_SUCCESSFUL;
    814  */
    815 
    816 rtems_status_code rtems_task_mode(
    817   rtems_mode  mode_set,
    818   rtems_mode  mask,
    819   rtems_mode *previous_mode_set
    820 )
    821 {
    822   Thread_Control     *executing;
    823   RTEMS_API_Control  *api;
    824   ASR_Information    *asr;
    825   boolean             is_asr_enabled = FALSE;
    826   boolean             needs_asr_dispatching = FALSE;
    827   rtems_mode          old_mode;
    828 
    829   executing     = _Thread_Executing;
    830   api = executing->API_Extensions[ THREAD_API_RTEMS ];
    831   asr = &api->Signal;
    832 
    833   old_mode  = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;
    834 
    835   if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE )
    836     old_mode |= RTEMS_NO_TIMESLICE;
    837   else
    838     old_mode |= RTEMS_TIMESLICE;
    839 
    840   old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR;
    841   old_mode |= _ISR_Get_level();
    842 
    843   *previous_mode_set = old_mode;
    844 
    845   /*
    846    *  These are generic thread scheduling characteristics.
    847    */
    848 
    849   if ( mask & RTEMS_PREEMPT_MASK )
    850     executing->is_preemptible = _Modes_Is_preempt(mode_set) ? TRUE : FALSE;
    851 
    852   if ( mask & RTEMS_TIMESLICE_MASK ) {
    853     if ( _Modes_Is_timeslice(mode_set) )
    854       executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
    855     else
    856       executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
    857   }
    858 
    859   /*
    860    *  Set the new interrupt level
    861    */
    862 
    863   if ( mask & RTEMS_INTERRUPT_MASK )
    864     _Modes_Set_interrupt_level( mode_set );
    865 
    866   /*
    867    *  This is specific to the RTEMS API
    868    */
    869 
    870   is_asr_enabled = FALSE;
    871   needs_asr_dispatching = FALSE;
    872 
    873   if ( mask & RTEMS_ASR_MASK ) {
    874     is_asr_enabled = _Modes_Is_asr_disabled( mode_set ) ? FALSE : TRUE;
    875     if ( is_asr_enabled != asr->is_enabled ) {
    876       asr->is_enabled = is_asr_enabled;
    877       _ASR_Swap_signals( asr );
    878       if ( _ASR_Are_signals_pending( asr ) ) {
    879         needs_asr_dispatching = TRUE;
    880         executing->do_post_task_switch_extension = TRUE;
    881       }
    882     }
    883   }
    884 
    885   if ( _Thread_Evaluate_mode() || needs_asr_dispatching )
    886     _Thread_Dispatch();
    887 
    888   return RTEMS_SUCCESSFUL;
    889 }
    890 
    891 /*PAGE
    892  *
    893  *  rtems_task_get_note
    894  *
    895  *  This directive obtains the note from the specified notepad
    896  *  of the specified thread.
    897  *
    898  *  Input parameters:
    899  *    id      - thread id
    900  *    notepad - notepad number
    901  *    note    - pointer to note
    902  *
    903  *  Output parameters:
    904  *    note              - filled in if successful
    905  *    RTEMS_SUCCESSFUL - if successful
    906  *    error code        - if unsuccessful
    907  */
    908 
    909 rtems_status_code rtems_task_get_note(
    910   Objects_Id  id,
    911   unsigned32  notepad,
    912   unsigned32 *note
    913 )
    914 {
    915   register Thread_Control *the_thread;
    916   Objects_Locations        location;
    917   RTEMS_API_Control       *api;
    918 
    919   /*
    920    *  NOTE:  There is no check for < RTEMS_NOTEPAD_FIRST because that would
    921    *         be checking an unsigned number for being negative.
    922    */
    923 
    924   if ( notepad > RTEMS_NOTEPAD_LAST )
    925     return RTEMS_INVALID_NUMBER;
    926 
    927   /*
    928    *  Optimize the most likely case to avoid the Thread_Dispatch.
    929    */
    930 
    931   if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ||
    932        _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) {
    933       api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
    934       *note = api->Notepads[ notepad ];
    935       return RTEMS_SUCCESSFUL;
    936   }
    937 
    938   the_thread = _Thread_Get( id, &location );
    939   switch ( location ) {
    940 
    941     case OBJECTS_REMOTE:
    942 #if defined(RTEMS_MULTIPROCESSING)
    943       _Thread_Executing->Wait.return_argument = note;
    944 
    945       return _RTEMS_tasks_MP_Send_request_packet(
    946         RTEMS_TASKS_MP_GET_NOTE_REQUEST,
    947         id,
    948         0,          /* Not used */
    949         notepad,
    950         0           /* Not used */
    951       );
    952 #endif
    953 
    954     case OBJECTS_ERROR:
    955       return RTEMS_INVALID_ID;
    956 
    957     case OBJECTS_LOCAL:
    958       api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    959       *note = api->Notepads[ notepad ];
    960       _Thread_Enable_dispatch();
    961       return RTEMS_SUCCESSFUL;
    962   }
    963 
    964   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    965 }
    966 
    967 /*PAGE
    968  *
    969  * rtems_task_set_note
    970  *
    971  *  This directive sets the specified notepad contents to the given
    972  *  note.
    973  *
    974  *  Input parameters:
    975  *    id      - thread id
    976  *    notepad - notepad number
    977  *    note    - note value
    978  *
    979  *  Output parameters:
    980  *    RTEMS_SUCCESSFUL - if successful
    981  *    error code        - if unsuccessful
    982  */
    983 
    984 rtems_status_code rtems_task_set_note(
    985   Objects_Id id,
    986   unsigned32 notepad,
    987   unsigned32 note
    988 )
    989 {
    990   register Thread_Control *the_thread;
    991   Objects_Locations        location;
    992   RTEMS_API_Control       *api;
    993 
    994   /*
    995    *  NOTE:  There is no check for < RTEMS_NOTEPAD_FIRST because that would
    996    *         be checking an unsigned number for being negative.
    997    */
    998 
    999   if ( notepad > RTEMS_NOTEPAD_LAST )
    1000     return RTEMS_INVALID_NUMBER;
    1001 
    1002   /*
    1003    *  Optimize the most likely case to avoid the Thread_Dispatch.
    1004    */
    1005 
    1006   if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ||
    1007        _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) {
    1008       api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
    1009       api->Notepads[ notepad ] = note;
    1010       return RTEMS_SUCCESSFUL;
    1011   }
    1012 
    1013   the_thread = _Thread_Get( id, &location );
    1014   switch ( location ) {
    1015 
    1016     case OBJECTS_REMOTE:
    1017 #if defined(RTEMS_MULTIPROCESSING)
    1018       return _RTEMS_tasks_MP_Send_request_packet(
    1019         RTEMS_TASKS_MP_SET_NOTE_REQUEST,
    1020         id,
    1021         0,          /* Not used */
    1022         notepad,
    1023         note
    1024       );
    1025 #endif
    1026 
    1027     case OBJECTS_ERROR:
    1028       return RTEMS_INVALID_ID;
    1029 
    1030     case OBJECTS_LOCAL:
    1031       api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    1032       api->Notepads[ notepad ] = note;
    1033       _Thread_Enable_dispatch();
    1034       return RTEMS_SUCCESSFUL;
    1035   }
    1036 
    1037   return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
    1038 }
    1039 
    1040 /*PAGE
    1041  *
    1042  *  rtems_task_wake_after
    1043  *
    1044  *  This directive suspends the requesting thread for the given amount
    1045  *  of ticks.
    1046  *
    1047  *  Input parameters:
    1048  *    ticks - number of ticks to wait
    1049  *
    1050  *  Output parameters:
    1051  *    RTEMS_SUCCESSFUL - always successful
    1052  */
    1053 
    1054 rtems_status_code rtems_task_wake_after(
    1055   rtems_interval ticks
    1056 )
    1057 {
    1058   _Thread_Disable_dispatch();
    1059     if ( ticks == 0 ) {
    1060       _Thread_Yield_processor();
    1061     } else {
    1062       _Thread_Set_state( _Thread_Executing, STATES_DELAYING );
    1063       _Watchdog_Initialize(
    1064         &_Thread_Executing->Timer,
    1065         _Thread_Delay_ended,
    1066         _Thread_Executing->Object.id,
    1067         NULL
    1068       );
    1069       _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
    1070     }
    1071   _Thread_Enable_dispatch();
    1072   return RTEMS_SUCCESSFUL;
    1073 }
    1074 
    1075 /*PAGE
    1076  *
    1077  *  rtems_task_wake_when
    1078  *
    1079  *  This directive blocks the requesting thread until the given date and
    1080  *  time is reached.
    1081  *
    1082  *  Input parameters:
    1083  *    time_buffer - pointer to the time and date structure
    1084  *
    1085  *  Output parameters:
    1086  *    RTEMS_SUCCESSFUL - if successful
    1087  *    error code        - if unsuccessful
    1088  */
    1089 
    1090 rtems_status_code rtems_task_wake_when(
    1091 rtems_time_of_day *time_buffer
    1092 )
    1093 {
    1094   Watchdog_Interval   seconds;
    1095 
    1096   if ( !_TOD_Is_set )
    1097     return RTEMS_NOT_DEFINED;
    1098 
    1099   time_buffer->ticks = 0;
    1100 
    1101   if ( !_TOD_Validate( time_buffer ) )
    1102     return RTEMS_INVALID_CLOCK;
    1103 
    1104   seconds = _TOD_To_seconds( time_buffer );
    1105 
    1106   if ( seconds <= _TOD_Seconds_since_epoch )
    1107     return RTEMS_INVALID_CLOCK;
    1108 
    1109   _Thread_Disable_dispatch();
    1110     _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_TIME );
    1111     _Watchdog_Initialize(
    1112       &_Thread_Executing->Timer,
    1113       _Thread_Delay_ended,
    1114       _Thread_Executing->Object.id,
    1115       NULL
    1116     );
    1117     _Watchdog_Insert_seconds(
    1118       &_Thread_Executing->Timer,
    1119       seconds - _TOD_Seconds_since_epoch
    1120     );
    1121   _Thread_Enable_dispatch();
    1122   return RTEMS_SUCCESSFUL;
    1123 }
    1124 
    1125 /*PAGE
    1126  *
    1127  *  _RTEMS_tasks_Initialize_user_tasks
    1128  *
    1129  *  This routine creates and starts all configured user
    1130  *  initialzation threads.
    1131  *
    1132  *  Input parameters: NONE
    1133  *
    1134  *  Output parameters:  NONE
    1135  */
    1136 
    1137 void _RTEMS_tasks_Initialize_user_tasks( void )
    1138 {
    1139   unsigned32                        index;
    1140   unsigned32                        maximum;
    1141   rtems_id                          id;
    1142   rtems_status_code                 return_value;
    1143   rtems_initialization_tasks_table *user_tasks;
    1144 
    1145   /*
    1146    *  NOTE:  This is slightly different from the Ada implementation.
    1147    */
    1148 
    1149   user_tasks = _RTEMS_tasks_User_initialization_tasks;
    1150   maximum    = _RTEMS_tasks_Number_of_initialization_tasks;
    1151 
    1152   if ( !user_tasks || maximum == 0 )
    1153     return;
    1154 
    1155   for ( index=0 ; index < maximum ; index++ ) {
    1156     return_value = rtems_task_create(
    1157       user_tasks[ index ].name,
    1158       user_tasks[ index ].initial_priority,
    1159       user_tasks[ index ].stack_size,
    1160       user_tasks[ index ].mode_set,
    1161       user_tasks[ index ].attribute_set,
    1162       &id
    1163     );
    1164 
    1165     if ( !rtems_is_status_successful( return_value ) )
    1166       _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, return_value );
    1167 
    1168     return_value = rtems_task_start(
    1169       id,
    1170       user_tasks[ index ].entry_point,
    1171       user_tasks[ index ].argument
    1172     );
    1173 
    1174     if ( !rtems_is_status_successful( return_value ) )
    1175       _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, return_value );
    1176   }
    1177 }
    1178 
Note: See TracChangeset for help on using the changeset viewer.