source: rtems/c/src/exec/rtems/src/tasks.c @ 03f2154e

4.104.114.84.95
Last change on this file since 03f2154e was dab057a, checked in by Joel Sherrill <joel.sherrill@…>, on 03/08/97 at 03:51:09

Modified calls to _Thread_Change_priority to take a third argument. The new
argument indicates whether the task is to be placed at the head or tail of
its priority fifo when it is lowering its own priority. POSIX normally
follows the RTEMS API conventions but GNAT expects that all lowering of
a task's priority by the task itself will result in being placed at the
head of the priority FIFO. Normally, this would only occur as the result
of lose of inherited priority.

The RTEMS API always puts tasks at the end of their priority group except
upon loss of inherited priority.

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