source: rtems/c/src/exec/rtems/src/tasks.c @ 7a035ebc

4.104.114.84.95
Last change on this file since 7a035ebc was 7a035ebc, checked in by Joel Sherrill <joel.sherrill@…>, on 08/21/98 at 16:54:17

Added system task attribute to allow one to create a task with "0" priority
via the user api.

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