source: rtems/cpukit/rtems/src/tasks.c @ 94b3ec59

4.104.114.84.95
Last change on this file since 94b3ec59 was 94b3ec59, checked in by Joel Sherrill <joel.sherrill@…>, on 02/13/96 at 22:14:48

changed post task extension from user set to api set and added flag
in each thread which must be set when the post switch extension is to be run.

  • Property mode set to 100644
File size: 26.9 KB
RevLine 
[ac7d5ef0]1/*
2 *  RTEMS Task Manager
3 *
4 *
5 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
6 *  On-Line Applications Research Corporation (OAR).
7 *  All rights assigned to U.S. Government, 1994.
8 *
9 *  This material may be reproduced by or for the U.S. Government pursuant
10 *  to the copyright license under the clause at DFARS 252.227-7013.  This
11 *  notice must appear in all copies of this file and its derivatives.
12 *
13 *  $Id$
14 */
15
16#include <rtems/system.h>
[3a4ae6c]17#include <rtems/rtems/status.h>
18#include <rtems/rtems/support.h>
19#include <rtems/rtems/modes.h>
[5e9b32b]20#include <rtems/score/object.h>
21#include <rtems/score/stack.h>
22#include <rtems/score/states.h>
[3a4ae6c]23#include <rtems/rtems/tasks.h>
[5e9b32b]24#include <rtems/score/thread.h>
25#include <rtems/score/threadq.h>
26#include <rtems/score/tod.h>
27#include <rtems/score/userext.h>
28#include <rtems/score/wkspace.h>
29#include <rtems/score/apiext.h>
30#include <rtems/score/sysstate.h>
[3a4ae6c]31
32/*PAGE
33 *
34 *  _RTEMS_tasks_Create_extension
35 *
36 *  XXX
37 */
38
39boolean _RTEMS_tasks_Create_extension(
40  Thread_Control *executing,
41  Thread_Control *created
42)
43{
44  RTEMS_API_Control *api;
45
46  api = _Workspace_Allocate( sizeof( RTEMS_API_Control ) );
47
48  if ( !api )
49    return FALSE;
50
51  created->API_Extensions[ THREAD_API_RTEMS ] = api;
52 
53  api->pending_events = EVENT_SETS_NONE_PENDING;
54  _ASR_Initialize( &api->Signal );
55  return TRUE;
56}
57
58/*PAGE
59 *
60 *  _RTEMS_tasks_Start_extension
61 *
62 *  XXX
63 */
64 
65User_extensions_routine _RTEMS_tasks_Start_extension(
66  Thread_Control *executing,
67  Thread_Control *started
68)
69{
70  RTEMS_API_Control *api;
71
72  api = started->API_Extensions[ THREAD_API_RTEMS ];
73 
74  api->pending_events = EVENT_SETS_NONE_PENDING;
75
76  _ASR_Initialize( &api->Signal );
77}
78
79/*PAGE
80 *
81 *  _RTEMS_tasks_Delete_extension
82 *
83 *  XXX
84 */
85 
86User_extensions_routine _RTEMS_tasks_Delete_extension(
87  Thread_Control *executing,
88  Thread_Control *deleted
89)
90{
91  (void) _Workspace_Free( deleted->API_Extensions[ THREAD_API_RTEMS ] );
92 
93  deleted->API_Extensions[ THREAD_API_RTEMS ] = NULL;
94}
95
96/*PAGE
97 *
98 *  _RTEMS_tasks_Switch_extension
99 *
100 *  XXX
101 */
102 
[94b3ec59]103void _RTEMS_tasks_Switch_extension(
[3a4ae6c]104  Thread_Control *executing
105)
106{
107  ISR_Level          level;
108  RTEMS_API_Control *api;
109  ASR_Information   *asr;
110  rtems_signal_set   signal_set;
111  Modes_Control      prev_mode;
112
113  api = executing->API_Extensions[ THREAD_API_RTEMS ];
114  asr = &api->Signal;
115 
116  _ISR_Disable( level );
[3652ad35]117    signal_set = asr->signals_posted;
[3a4ae6c]118    asr->signals_posted = 0;
[3652ad35]119  _ISR_Enable( level );
[3a4ae6c]120 
121 
[3652ad35]122  if ( !signal_set ) /* similar to _ASR_Are_signals_pending( asr ) */
123    return;
[3a4ae6c]124 
[3652ad35]125  asr->nest_level += 1;
126  rtems_task_mode( asr->mode_set, RTEMS_ALL_MODE_MASKS, &prev_mode );
127 
128  (*asr->handler)( signal_set );
129
130  asr->nest_level -= 1;
131  rtems_task_mode( prev_mode, RTEMS_ALL_MODE_MASKS, &prev_mode );
[3a4ae6c]132
133}
134
[7af35da5]135API_extensions_Control _RTEMS_tasks_API_extensions = {
[3a4ae6c]136  { NULL, NULL },
137  NULL,                                     /* predriver */
[94b3ec59]138  _RTEMS_tasks_Initialize_user_tasks,       /* postdriver */
139  _RTEMS_tasks_Switch_extension             /* post switch */
[3a4ae6c]140};
141
[7af35da5]142User_extensions_Control _RTEMS_tasks_User_extensions = {
[3a4ae6c]143  { NULL, NULL },
144  { _RTEMS_tasks_Create_extension,            /* create */
145    _RTEMS_tasks_Start_extension,             /* start */
146    _RTEMS_tasks_Start_extension,             /* restart */
147    _RTEMS_tasks_Delete_extension,            /* delete */
148    NULL,                                     /* switch */
149    NULL,                                     /* begin */
150    NULL,                                     /* exitted */
151    NULL                                      /* fatal */
152  }
153};
[ac7d5ef0]154
[5250ff39]155/*PAGE
156 *
157 *  _RTEMS_tasks_Manager_initialization
158 *
159 *  This routine initializes all Task Manager related data structures.
160 *
161 *  Input parameters:
162 *    maximum_tasks       - number of tasks to initialize
163 *
164 *  Output parameters:  NONE
165 */
166
167void _RTEMS_tasks_Manager_initialization(
[3a4ae6c]168  unsigned32                        maximum_tasks,
169  unsigned32                        number_of_initialization_tasks,
170  rtems_initialization_tasks_table *user_tasks
[5250ff39]171)
172{
[3a4ae6c]173
174  _RTEMS_tasks_Number_of_initialization_tasks = number_of_initialization_tasks;
175  _RTEMS_tasks_User_initialization_tasks = user_tasks;
176
177  if ( user_tasks == NULL || number_of_initialization_tasks == 0 )
178    _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, RTEMS_TOO_MANY );
179
[5250ff39]180  _Objects_Initialize_information(
181    &_RTEMS_tasks_Information,
182    OBJECTS_RTEMS_TASKS,
183    TRUE,
184    maximum_tasks,
185    sizeof( Thread_Control ),
186    FALSE,
187    RTEMS_MAXIMUM_NAME_LENGTH,
188    TRUE
189  );
[3a4ae6c]190
191  /*
192   *  Add all the extensions for this API
193   */
194
[7af35da5]195  _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions );
[3a4ae6c]196
[7af35da5]197  _API_extensions_Add( &_RTEMS_tasks_API_extensions );
[3a4ae6c]198
199  /*
200   *  Register the MP Process Packet routine.
201   */
202
203  _MPCI_Register_packet_processor(
204    MP_PACKET_TASKS,
205    _RTEMS_tasks_MP_Process_packet
206  );
207
[5250ff39]208}
209
[ac7d5ef0]210/*PAGE
211 *
212 *  rtems_task_create
213 *
214 *  This directive creates a thread by allocating and initializing a
215 *  thread control block and a stack.  The newly created thread is
216 *  placed in the dormant state.
217 *
218 *  Input parameters:
219 *    name             - user defined thread name
220 *    initial_priority - thread priority
221 *    stack_size       - stack size in bytes
222 *    initial_modes    - initial thread mode
223 *    attribute_set    - thread attributes
224 *    id               - pointer to thread id
225 *
226 *  Output parameters:
227 *    id                - thread id
228 *    RTEMS_SUCCESSFUL - if successful
229 *    error code        - if unsuccessful
230 */
231
232rtems_status_code rtems_task_create(
[3235ad9]233  rtems_name           name,
[ac7d5ef0]234  rtems_task_priority  initial_priority,
235  unsigned32           stack_size,
236  rtems_mode           initial_modes,
237  rtems_attribute      attribute_set,
238  Objects_Id          *id
239)
240{
241  register Thread_Control *the_thread;
[7f6a24ab]242  Objects_MP_Control      *the_global_object = NULL;
243  boolean                  is_fp;
244  boolean                  is_global;
[3a4ae6c]245  boolean                  status;
[ac7d5ef0]246  rtems_attribute          the_attribute_set;
[7f6a24ab]247  Priority_Control         core_priority;
[3a4ae6c]248  RTEMS_API_Control       *api;
249  ASR_Information         *asr;
[7f6a24ab]250 
[ac7d5ef0]251
[3235ad9]252  if ( !rtems_is_name_valid( name ) )
[3a4ae6c]253    return RTEMS_INVALID_NAME;
[ac7d5ef0]254
[7f6a24ab]255  /*
256   *  Core Thread Initialize insures we get the minimum amount of
257   *  stack space.
258   */
259
[ac7d5ef0]260#if 0
261  if ( !_Stack_Is_enough( stack_size ) )
[3a4ae6c]262    return RTEMS_INVALID_SIZE;
[ac7d5ef0]263#endif
264
[7f6a24ab]265  /*
266   *  Validate the RTEMS API priority and convert it to the core priority range.
267   */
[ac7d5ef0]268
[3a4ae6c]269  if ( !_RTEMS_tasks_Priority_is_valid( initial_priority ) )
270    return RTEMS_INVALID_PRIORITY;
[ac7d5ef0]271
[3a4ae6c]272  core_priority = _RTEMS_tasks_Priority_to_Core( initial_priority );
[7f6a24ab]273
[ac7d5ef0]274  /*
275   *  Fix the attribute set to match the attributes which
276   *  this processor (1) requires and (2) is able to support.
277   *  First add in the required flags for attribute_set
278   *  Typically this might include FP if the platform
279   *  or application required all tasks to be fp aware.
280   *  Then turn off the requested bits which are not supported.
281   */
282
283  the_attribute_set = _Attributes_Set( attribute_set, ATTRIBUTES_REQUIRED );
284  the_attribute_set =
285    _Attributes_Clear( the_attribute_set, ATTRIBUTES_NOT_SUPPORTED );
286
[7f6a24ab]287  if ( _Attributes_Is_floating_point( the_attribute_set ) )
288    is_fp = TRUE;
289  else
290    is_fp = FALSE;
291
292  if ( _Attributes_Is_global( the_attribute_set ) ) {
293
294    is_global = TRUE;
295
[3a4ae6c]296    if ( !_System_state_Is_multiprocessing )
297      return RTEMS_MP_NOT_CONFIGURED;
[ac7d5ef0]298
[7f6a24ab]299  } else
300    is_global = FALSE;
301
302  /*
303   *  Make sure system is MP if this task is global
304   */
305
306  /*
307   *  Disable dispatch for protection
308   */
309
310  _Thread_Disable_dispatch();
311
312  /*
313   *  Allocate the thread control block and -- if the task is global --
314   *  allocate a global object control block.
315   *
316   *  NOTE:  This routine does not use the combined allocate and open
317   *         global object routine because this results in a lack of
318   *         control over when memory is allocated and can be freed in
319   *         the event of an error.
320   */
[ac7d5ef0]321
322  the_thread = _RTEMS_tasks_Allocate();
323
324  if ( !the_thread ) {
325    _Thread_Enable_dispatch();
[3a4ae6c]326    return RTEMS_TOO_MANY;
[ac7d5ef0]327  }
328
[7f6a24ab]329  if ( is_global ) {
330    the_global_object = _Objects_MP_Allocate_global_object();
[ac7d5ef0]331
[7f6a24ab]332    if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
333      _RTEMS_tasks_Free( the_thread );
334      _Thread_Enable_dispatch();
[3a4ae6c]335      return RTEMS_TOO_MANY;
[7f6a24ab]336    }
337  }
[ac7d5ef0]338
339  /*
[7f6a24ab]340   *  Initialize the core thread for this task.
[ac7d5ef0]341   */
342
[3a4ae6c]343  status = _Thread_Initialize(
344    &_RTEMS_tasks_Information,
345    the_thread,
346    NULL,
347    stack_size,
348    is_fp,
349    core_priority,
350    _Modes_Is_preempt(initial_modes)   ? TRUE : FALSE,
351    _Modes_Is_timeslice(initial_modes) ? TRUE : FALSE,
352    _Modes_Get_interrupt_level(initial_modes),
353    &name
354  );
[ac7d5ef0]355
[3a4ae6c]356  if ( !status ) {
[7f6a24ab]357    if ( is_global )
358      _Objects_MP_Free_global_object( the_global_object );
[ac7d5ef0]359    _RTEMS_tasks_Free( the_thread );
360    _Thread_Enable_dispatch();
[3a4ae6c]361    return RTEMS_UNSATISFIED;
[ac7d5ef0]362  }
363
[3a4ae6c]364  api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
365  asr = &api->Signal;
366 
367  asr->is_enabled = _Modes_Is_asr_disabled(initial_modes) ? FALSE : TRUE;
368
[7f6a24ab]369  *id = the_thread->Object.id;
[ac7d5ef0]370
[7f6a24ab]371  if ( is_global ) {
[ac7d5ef0]372
[3a4ae6c]373    the_thread->is_global = TRUE;
[ac7d5ef0]374
[7f6a24ab]375    _Objects_MP_Open(
376      &_RTEMS_tasks_Information,
377      the_global_object,
378      name,
379      the_thread->Object.id
380    );
[ac7d5ef0]381
382    _RTEMS_tasks_MP_Send_process_packet(
383      RTEMS_TASKS_MP_ANNOUNCE_CREATE,
384      the_thread->Object.id,
385      name
386    );
387
[7f6a24ab]388   }
389
[ac7d5ef0]390  _Thread_Enable_dispatch();
[3a4ae6c]391  return RTEMS_SUCCESSFUL;
[ac7d5ef0]392}
393
394/*PAGE
395 *
396 *  rtems_task_ident
397 *
398 *  This directive returns the system ID associated with
399 *  the thread name.
400 *
401 *  Input parameters:
402 *    name - user defined thread name
403 *    node - node(s) to be searched
404 *    id   - pointer to thread id
405 *
406 *  Output parameters:
407 *    *id               - thread id
408 *    RTEMS_SUCCESSFUL - if successful
409 *    error code        - if unsuccessful
410 */
411
412rtems_status_code rtems_task_ident(
[3235ad9]413  rtems_name    name,
[ac7d5ef0]414  unsigned32    node,
415  Objects_Id   *id
416)
417{
[3a4ae6c]418  Objects_Name_to_id_errors  status;
419
420  if ( name == OBJECTS_ID_OF_SELF ) {
421    *id = _Thread_Executing->Object.id;
422    return RTEMS_SUCCESSFUL;
423   }
424
425  status = _Objects_Name_to_id( &_RTEMS_tasks_Information, &name, node, id );
[ac7d5ef0]426
[3a4ae6c]427  return _Status_Object_name_errors_to_status[ status ];
[ac7d5ef0]428}
429
430/*PAGE
431 *
432 *  rtems_task_start
433 *
434 *  This directive readies the thread identified by the "id"
435 *  based on its current priorty, to await execution.  A thread
436 *  can be started only from the dormant state.
437 *
438 *  Input parameters:
439 *    id          - thread id
440 *    entry_point - start execution address of thread
441 *    argument    - thread argument
442 *
443 *  Output parameters:
444 *    RTEMS_SUCCESSFUL - if successful
445 *    error code        - if unsuccessful
446 */
447
448rtems_status_code rtems_task_start(
[7f6a24ab]449  rtems_id         id,
[ac7d5ef0]450  rtems_task_entry entry_point,
[7f6a24ab]451  unsigned32       argument
[ac7d5ef0]452)
453{
454  register Thread_Control *the_thread;
455  Objects_Locations        location;
456
457  if ( entry_point == NULL )
[3a4ae6c]458    return RTEMS_INVALID_ADDRESS;
[ac7d5ef0]459
460  the_thread = _Thread_Get( id, &location );
461  switch ( location ) {
462    case OBJECTS_ERROR:
[3a4ae6c]463      return RTEMS_INVALID_ID;
[ac7d5ef0]464    case OBJECTS_REMOTE:
465      _Thread_Dispatch();
[3a4ae6c]466      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
[ac7d5ef0]467    case OBJECTS_LOCAL:
[7f6a24ab]468      if ( _Thread_Start(
469             the_thread, THREAD_START_NUMERIC, entry_point, NULL, argument ) ) {
[ac7d5ef0]470        _Thread_Enable_dispatch();
[3a4ae6c]471        return RTEMS_SUCCESSFUL;
[ac7d5ef0]472      }
473      _Thread_Enable_dispatch();
[3a4ae6c]474      return RTEMS_INCORRECT_STATE;
[ac7d5ef0]475  }
476
[3a4ae6c]477  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
[ac7d5ef0]478}
479
480/*PAGE
481 *
482 *  rtems_task_restart
483 *
484 *  This directive readies the specified thread.  It restores
485 *  the thread environment to the original values established
486 *  at thread creation and start time.  A thread can be restarted
487 *  from any state except the dormant state.
488 *
489 *  Input parameters:
490 *    id       - thread id
491 *    argument - thread argument
492 *
493 *  Output parameters:
494 *    RTEMS_SUCCESSFUL - if successful
495 *    error code        - if unsuccessful
496 */
497
498rtems_status_code rtems_task_restart(
499  Objects_Id id,
500  unsigned32 argument
501)
502{
503  register Thread_Control *the_thread;
[7f6a24ab]504  Objects_Locations        location;
[ac7d5ef0]505
506  the_thread = _Thread_Get( id, &location );
507  switch ( location ) {
508    case OBJECTS_ERROR:
[3a4ae6c]509      return RTEMS_INVALID_ID;
[ac7d5ef0]510    case OBJECTS_REMOTE:
511      _Thread_Dispatch();
[3a4ae6c]512      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
[ac7d5ef0]513    case OBJECTS_LOCAL:
[7f6a24ab]514      if ( _Thread_Restart( the_thread, NULL, argument ) ) {
[ac7d5ef0]515        _Thread_Enable_dispatch();
[3a4ae6c]516        return RTEMS_SUCCESSFUL;
[ac7d5ef0]517      }
518      _Thread_Enable_dispatch();
[3a4ae6c]519      return RTEMS_INCORRECT_STATE;
[ac7d5ef0]520  }
521
[3a4ae6c]522  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
[ac7d5ef0]523}
524
525/*PAGE
526 *
527 *  rtems_task_delete
528 *
529 *  This directive allows a thread to delete itself or the thread
530 *  identified in the id field.  The executive halts execution
531 *  of the thread and frees the thread control block.
532 *
533 *  Input parameters:
534 *    id - thread id
535 *
536 *  Output parameters:
537 *    nothing           - if id is the requesting thread (always succeeds)
538 *    RTEMS_SUCCESSFUL - if successful and id is
539 *                           not the requesting thread
540 *    error code        - if unsuccessful
541 */
542
543rtems_status_code rtems_task_delete(
544  Objects_Id id
545)
546{
547  register Thread_Control *the_thread;
548  Objects_Locations        location;
549
550  the_thread = _Thread_Get( id, &location );
551  switch ( location ) {
552    case OBJECTS_ERROR:
[3a4ae6c]553      return RTEMS_INVALID_ID;
[ac7d5ef0]554    case OBJECTS_REMOTE:
555      _Thread_Dispatch();
[3a4ae6c]556      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
[ac7d5ef0]557    case OBJECTS_LOCAL:
[7f6a24ab]558      _Thread_Close( &_RTEMS_tasks_Information, the_thread );
[ac7d5ef0]559
560      _RTEMS_tasks_Free( the_thread );
561
[3a4ae6c]562      if ( the_thread->is_global ) {
[ac7d5ef0]563
[5250ff39]564        _Objects_MP_Close( &_RTEMS_tasks_Information, the_thread->Object.id );
[ac7d5ef0]565
566        _RTEMS_tasks_MP_Send_process_packet(
567          RTEMS_TASKS_MP_ANNOUNCE_DELETE,
568          the_thread->Object.id,
569          0                                /* Not used */
570        );
571      }
572
573      _Thread_Enable_dispatch();
[3a4ae6c]574      return RTEMS_SUCCESSFUL;
[ac7d5ef0]575  }
576
[3a4ae6c]577  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
[ac7d5ef0]578}
579
580/*PAGE
581 *
582 *  rtems_task_suspend
583 *
584 *  This directive will place the specified thread in the "suspended"
585 *  state.  Note that the suspended state can be in addition to
586 *  other waiting states.
587 *
588 *  Input parameters:
589 *    id - thread id
590 *
591 *  Output parameters:
592 *    RTEMS_SUCCESSFUL - if successful
593 *    error code        - if unsuccessful
594 */
595
596rtems_status_code rtems_task_suspend(
597  Objects_Id id
598)
599{
600  register Thread_Control *the_thread;
601  Objects_Locations               location;
602
603  the_thread = _Thread_Get( id, &location );
604  switch ( location ) {
605    case OBJECTS_ERROR:
[3a4ae6c]606      return RTEMS_INVALID_ID;
[ac7d5ef0]607    case OBJECTS_REMOTE:
[3a4ae6c]608      return _RTEMS_tasks_MP_Send_request_packet(
609        RTEMS_TASKS_MP_SUSPEND_REQUEST,
610        id,
611        0,          /* Not used */
612        0,          /* Not used */
613        0           /* Not used */
[ac7d5ef0]614      );
615    case OBJECTS_LOCAL:
616      if ( !_States_Is_suspended( the_thread->current_state ) ) {
617        _Thread_Set_state( the_thread, STATES_SUSPENDED );
618        _Thread_Enable_dispatch();
[3a4ae6c]619        return RTEMS_SUCCESSFUL;
[ac7d5ef0]620      }
621      _Thread_Enable_dispatch();
[3a4ae6c]622      return RTEMS_ALREADY_SUSPENDED;
[ac7d5ef0]623  }
624
[3a4ae6c]625  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
[ac7d5ef0]626}
627
628/*PAGE
629 *
630 *  rtems_task_resume
631 *
632 *  This directive will remove the specified thread
633 *  from the suspended state.
634 *
635 *  Input parameters:
636 *    id - thread id
637 *
638 *  Output parameters:
639 *    RTEMS_SUCCESSFUL - if successful
640 *    error code        - if unsuccessful
641 */
642
643rtems_status_code rtems_task_resume(
644  Objects_Id id
645)
646{
647  register Thread_Control *the_thread;
648  Objects_Locations        location;
649
650  the_thread = _Thread_Get( id, &location );
651  switch ( location ) {
652    case OBJECTS_ERROR:
[3a4ae6c]653      return RTEMS_INVALID_ID;
[ac7d5ef0]654    case OBJECTS_REMOTE:
655      return(
656        _RTEMS_tasks_MP_Send_request_packet(
657          RTEMS_TASKS_MP_RESUME_REQUEST,
658          id,
659          0,          /* Not used */
660          0,          /* Not used */
661          0           /* Not used */
662        )
663      );
664    case OBJECTS_LOCAL:
665      if ( _States_Is_suspended( the_thread->current_state ) ) {
666        _Thread_Resume( the_thread );
667        _Thread_Enable_dispatch();
[3a4ae6c]668        return RTEMS_SUCCESSFUL;
[ac7d5ef0]669      }
670      _Thread_Enable_dispatch();
[3a4ae6c]671      return RTEMS_INCORRECT_STATE;
[ac7d5ef0]672  }
673
[3a4ae6c]674  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
[ac7d5ef0]675}
676
677/*PAGE
678 *
679 *  rtems_task_set_priority
680 *
681 *  This directive changes the priority of the specified thread.
682 *  The specified thread can be any thread in the system including
683 *  the requesting thread.
684 *
685 *  Input parameters:
686 *    id           - thread id (0 indicates requesting thread)
687 *    new_priority - thread priority (0 indicates current priority)
688 *    old_priority - pointer to previous priority
689 *
690 *  Output parameters:
691 *    old_priority      - previous priority
692 *    RTEMS_SUCCESSFUL - if successful
693 *    error code        - if unsuccessful
694 */
695
696rtems_status_code rtems_task_set_priority(
[7f6a24ab]697  Objects_Id           id,
[ac7d5ef0]698  rtems_task_priority  new_priority,
699  rtems_task_priority *old_priority
700)
701{
702  register Thread_Control *the_thread;
703  Objects_Locations               location;
704
705  if ( new_priority != RTEMS_CURRENT_PRIORITY &&
[3a4ae6c]706       !_RTEMS_tasks_Priority_is_valid( new_priority ) )
707    return RTEMS_INVALID_PRIORITY;
[ac7d5ef0]708
709  the_thread = _Thread_Get( id, &location );
710  switch ( location ) {
711    case OBJECTS_ERROR:
[3a4ae6c]712      return RTEMS_INVALID_ID;
[ac7d5ef0]713    case OBJECTS_REMOTE:
714      _Thread_Executing->Wait.return_argument = old_priority;
715      return(
716        _RTEMS_tasks_MP_Send_request_packet(
717          RTEMS_TASKS_MP_SET_PRIORITY_REQUEST,
718          id,
719          new_priority,
720          0,          /* Not used */
721          0           /* Not used */
722        )
723      );
724    case OBJECTS_LOCAL:
725      *old_priority = the_thread->current_priority;
726      if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
727        the_thread->real_priority = new_priority;
728        if ( the_thread->resource_count == 0 ||
729             the_thread->current_priority > new_priority )
730          _Thread_Change_priority( the_thread, new_priority );
731      }
732      _Thread_Enable_dispatch();
[3a4ae6c]733      return RTEMS_SUCCESSFUL;
[ac7d5ef0]734  }
735
[3a4ae6c]736  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
[ac7d5ef0]737}
738
739/*PAGE
740 *
741 *  rtems_task_mode
742 *
743 *  This directive enables and disables several modes of
744 *  execution for the requesting thread.
745 *
746 *  Input parameters:
747 *    mode_set          - new mode
748 *    mask              - mask
749 *    previous_mode_set - address of previous mode set
750 *
751 *  Output:
752 *    *previous_mode_set - previous mode set
[3a4ae6c]753 *     always return RTEMS_SUCCESSFUL;
[ac7d5ef0]754 */
755
756rtems_status_code rtems_task_mode(
757  rtems_mode  mode_set,
758  rtems_mode  mask,
759  rtems_mode *previous_mode_set
760)
761{
[3a4ae6c]762  Thread_Control     *executing;
763  RTEMS_API_Control  *api;
764  ASR_Information    *asr;
765  boolean             is_asr_enabled = FALSE;
766  boolean             needs_asr_dispatching = FALSE;
767  rtems_mode          old_mode;
768
769  executing     = _Thread_Executing;
770  api = executing->API_Extensions[ THREAD_API_RTEMS ];
771  asr = &api->Signal;
772
773  old_mode  = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;
774  old_mode |= (executing->is_timeslice) ? RTEMS_TIMESLICE : RTEMS_NO_TIMESLICE;
775  old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR;
776  old_mode |= _ISR_Get_level();
777
778  *previous_mode_set = old_mode;
779
780  /*
781   *  These are generic thread scheduling characteristics.
782   */
783
784  if ( mask & RTEMS_PREEMPT_MASK )
785    executing->is_preemptible = _Modes_Is_preempt(mode_set) ? TRUE : FALSE;
786
787  if ( mask & RTEMS_TIMESLICE_MASK )
788    executing->is_timeslice = _Modes_Is_timeslice(mode_set) ? TRUE : FALSE;
789
790  /*
791   *  Set the new interrupt level
792   */
793
794  if ( mask & RTEMS_INTERRUPT_MASK )
795    _Modes_Set_interrupt_level( mode_set );
796
797  /*
798   *  This is specific to the RTEMS API
799   */
800
801  is_asr_enabled = FALSE;
802  needs_asr_dispatching = FALSE;
803
804  if ( mask & RTEMS_ASR_MASK ) {
805    is_asr_enabled = _Modes_Is_asr_disabled( mode_set ) ? FALSE : TRUE;
806    if ( is_asr_enabled != asr->is_enabled ) {
807      asr->is_enabled = is_asr_enabled;
808      _ASR_Swap_signals( asr );
[94b3ec59]809      if ( _ASR_Are_signals_pending( asr ) ) {
[3a4ae6c]810        needs_asr_dispatching = TRUE;
[94b3ec59]811        executing->do_post_task_switch_extension = TRUE;
812      }
[3a4ae6c]813    }
814  }
815
816  if ( _Thread_Evaluate_mode() || needs_asr_dispatching )
[ac7d5ef0]817    _Thread_Dispatch();
[3a4ae6c]818
819  return RTEMS_SUCCESSFUL;
[ac7d5ef0]820}
821
822/*PAGE
823 *
824 *  rtems_task_get_note
825 *
826 *  This directive obtains the note from the specified notepad
827 *  of the specified thread.
828 *
829 *  Input parameters:
830 *    id      - thread id
831 *    notepad - notepad number
832 *    note    - pointer to note
833 *
834 *  Output parameters:
835 *    note              - filled in if successful
836 *    RTEMS_SUCCESSFUL - if successful
837 *    error code        - if unsuccessful
838 */
839
840rtems_status_code rtems_task_get_note(
841  Objects_Id  id,
842  unsigned32  notepad,
843  unsigned32 *note
844)
845{
846  register Thread_Control *the_thread;
847  Objects_Locations        location;
[3a4ae6c]848  RTEMS_API_Control       *api;
[ac7d5ef0]849
850  /*
851   *  NOTE:  There is no check for < RTEMS_NOTEPAD_FIRST because that would
852   *         be checking an unsigned number for being negative.
853   */
854
855  if ( notepad > RTEMS_NOTEPAD_LAST )
[3a4ae6c]856    return RTEMS_INVALID_NUMBER;
[ac7d5ef0]857
858  /*
859   *  Optimize the most likely case to avoid the Thread_Dispatch.
860   */
861
862  if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ||
863       _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) {
[3a4ae6c]864      api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
865      *note = api->Notepads[ notepad ];
866      return RTEMS_SUCCESSFUL;
[ac7d5ef0]867  }
868
869  the_thread = _Thread_Get( id, &location );
870  switch ( location ) {
871    case OBJECTS_ERROR:
[3a4ae6c]872      return RTEMS_INVALID_ID;
[ac7d5ef0]873    case OBJECTS_REMOTE:
874      _Thread_Executing->Wait.return_argument = note;
875
876      return _RTEMS_tasks_MP_Send_request_packet(
877        RTEMS_TASKS_MP_GET_NOTE_REQUEST,
878        id,
879        0,          /* Not used */
880        notepad,
881        0           /* Not used */
882      );
883    case OBJECTS_LOCAL:
[3a4ae6c]884      api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
885      *note = api->Notepads[ notepad ];
[ac7d5ef0]886      _Thread_Enable_dispatch();
[3a4ae6c]887      return RTEMS_SUCCESSFUL;
[ac7d5ef0]888  }
889
[3a4ae6c]890  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
[ac7d5ef0]891}
892
893/*PAGE
894 *
895 * rtems_task_set_note
896 *
897 *  This directive sets the specified notepad contents to the given
898 *  note.
899 *
900 *  Input parameters:
901 *    id      - thread id
902 *    notepad - notepad number
903 *    note    - note value
904 *
905 *  Output parameters:
906 *    RTEMS_SUCCESSFUL - if successful
907 *    error code        - if unsuccessful
908 */
909
910rtems_status_code rtems_task_set_note(
911  Objects_Id id,
912  unsigned32 notepad,
913  unsigned32 note
914)
915{
916  register Thread_Control *the_thread;
917  Objects_Locations        location;
[3a4ae6c]918  RTEMS_API_Control       *api;
[ac7d5ef0]919
920  /*
921   *  NOTE:  There is no check for < RTEMS_NOTEPAD_FIRST because that would
922   *         be checking an unsigned number for being negative.
923   */
924
925  if ( notepad > RTEMS_NOTEPAD_LAST )
[3a4ae6c]926    return RTEMS_INVALID_NUMBER;
[ac7d5ef0]927
928  /*
929   *  Optimize the most likely case to avoid the Thread_Dispatch.
930   */
931
932  if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ||
933       _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) {
[3a4ae6c]934      api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
935      api->Notepads[ notepad ] = note;
936      return RTEMS_SUCCESSFUL;
[ac7d5ef0]937  }
938
939  the_thread = _Thread_Get( id, &location );
940  switch ( location ) {
941    case OBJECTS_ERROR:
[3a4ae6c]942      return RTEMS_INVALID_ID;
[ac7d5ef0]943    case OBJECTS_REMOTE:
944      return _RTEMS_tasks_MP_Send_request_packet(
945        RTEMS_TASKS_MP_SET_NOTE_REQUEST,
946        id,
947        0,          /* Not used */
948        notepad,
949        note
950      );
951
952    case OBJECTS_LOCAL:
[3a4ae6c]953      api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
954      api->Notepads[ notepad ] = note;
[ac7d5ef0]955      _Thread_Enable_dispatch();
[3a4ae6c]956      return RTEMS_SUCCESSFUL;
[ac7d5ef0]957  }
958
[3a4ae6c]959  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
[ac7d5ef0]960}
961
962/*PAGE
963 *
964 *  rtems_task_wake_after
965 *
966 *  This directive suspends the requesting thread for the given amount
967 *  of ticks.
968 *
969 *  Input parameters:
970 *    ticks - number of ticks to wait
971 *
972 *  Output parameters:
973 *    RTEMS_SUCCESSFUL - always successful
974 */
975
976rtems_status_code rtems_task_wake_after(
977  rtems_interval ticks
978)
979{
980  if ( ticks == 0 ) {
981    _Thread_Yield_processor();
982    _Thread_Dispatch();
983  } else {
984    _Thread_Disable_dispatch();
985      _Thread_Set_state( _Thread_Executing, STATES_DELAYING );
986      _Watchdog_Initialize(
987        &_Thread_Executing->Timer,
988        _Thread_Delay_ended,
989        _Thread_Executing->Object.id,
990        NULL
991      );
[8d0b7d96]992      _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
[ac7d5ef0]993    _Thread_Enable_dispatch();
994  }
[3a4ae6c]995  return RTEMS_SUCCESSFUL;
[ac7d5ef0]996}
997
998/*PAGE
999 *
1000 *  rtems_task_wake_when
1001 *
1002 *  This directive blocks the requesting thread until the given date and
1003 *  time is reached.
1004 *
1005 *  Input parameters:
1006 *    time_buffer - pointer to the time and date structure
1007 *
1008 *  Output parameters:
1009 *    RTEMS_SUCCESSFUL - if successful
1010 *    error code        - if unsuccessful
1011 */
1012
1013rtems_status_code rtems_task_wake_when(
1014rtems_time_of_day *time_buffer
1015)
1016{
[3a4ae6c]1017  Watchdog_Interval   seconds;
[ac7d5ef0]1018
1019  if ( !_TOD_Is_set() )
[3a4ae6c]1020    return RTEMS_NOT_DEFINED;
[ac7d5ef0]1021
1022  time_buffer->ticks = 0;
1023
[3a4ae6c]1024  if ( !_TOD_Validate( time_buffer ) )
1025    return RTEMS_INVALID_CLOCK;
[ac7d5ef0]1026
1027  seconds = _TOD_To_seconds( time_buffer );
1028
1029  if ( seconds <= _TOD_Seconds_since_epoch )
[3a4ae6c]1030    return RTEMS_INVALID_CLOCK;
[ac7d5ef0]1031
1032  _Thread_Disable_dispatch();
1033    _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_TIME );
1034    _Watchdog_Initialize(
1035      &_Thread_Executing->Timer,
1036      _Thread_Delay_ended,
1037      _Thread_Executing->Object.id,
1038      NULL
1039    );
[8d0b7d96]1040    _Watchdog_Insert_seconds(
1041      &_Thread_Executing->Timer,
1042      seconds - _TOD_Seconds_since_epoch
1043    );
[ac7d5ef0]1044  _Thread_Enable_dispatch();
[3a4ae6c]1045  return RTEMS_SUCCESSFUL;
[ac7d5ef0]1046}
[3a4ae6c]1047
1048/*PAGE
1049 *
1050 *  _RTEMS_tasks_Initialize_user_tasks
1051 *
1052 *  This routine creates and starts all configured user
1053 *  initialzation threads.
1054 *
1055 *  Input parameters: NONE
1056 *
1057 *  Output parameters:  NONE
1058 */
1059
1060void _RTEMS_tasks_Initialize_user_tasks( void )
1061{
1062  unsigned32                        index;
1063  unsigned32                        maximum;
1064  rtems_id                          id;
1065  rtems_status_code                 return_value;
1066  rtems_initialization_tasks_table *user_tasks;
1067
1068  /*
1069   *  NOTE:  This is slightly different from the Ada implementation.
1070   */
1071
1072  user_tasks = _RTEMS_tasks_User_initialization_tasks;
1073  maximum    = _RTEMS_tasks_Number_of_initialization_tasks;
1074
1075  for ( index=0 ; index < maximum ; index++ ) {
1076    return_value = rtems_task_create(
1077      user_tasks[ index ].name,
1078      user_tasks[ index ].initial_priority,
1079      user_tasks[ index ].stack_size,
1080      user_tasks[ index ].mode_set,
1081      user_tasks[ index ].attribute_set,
1082      &id
1083    );
1084
1085    if ( !rtems_is_status_successful( return_value ) )
1086      _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, return_value );
1087
1088    return_value = rtems_task_start(
1089      id,
1090      user_tasks[ index ].entry_point,
1091      user_tasks[ index ].argument
1092    );
1093
1094    if ( !rtems_is_status_successful( return_value ) )
1095      _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, return_value );
1096  }
1097}
1098
Note: See TracBrowser for help on using the repository browser.