source: rtems/cpukit/rtems/src/tasks.c @ 98e4ebf5

4.104.114.84.95
Last change on this file since 98e4ebf5 was 98e4ebf5, checked in by Joel Sherrill <joel.sherrill@…>, on 10/08/97 at 15:45:54

Fixed typo in the pointer to the license terms.

  • Property mode set to 100644
File size: 27.3 KB
Line 
1/*
2 *  RTEMS Task Manager
3 *
4 *
5 *  COPYRIGHT (c) 1989-1997.
6 *  On-Line Applications Research Corporation (OAR).
7 *  Copyright assigned to U.S. Government, 1994.
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.OARcorp.com/rtems/license.html.
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.