source: rtems/c/src/exec/rtems/src/tasks.c @ cb1b853d

4.104.114.84.95
Last change on this file since cb1b853d was cb1b853d, checked in by Joel Sherrill <joel.sherrill@…>, on 06/18/98 at 19:01:57

All task delete API level services were incorrectly assuming that the
task to be deleted was created via the same API (i.e. were of the object
class created by this API). For example, a POSIX thread calling
the rtems_task_delete(SELF) directive would incorrectly update the RTEMS
object local pointer table.

Jennifer discovered this when moving tests implemented in C using the
Classic RTEMS API into a tree of Ada tests. The Ada tests were implicitly
using POSIX services. This lead to some unexpected behavior.

  • 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   *  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  Objects_Information     *the_information;
559
560  the_thread = _Thread_Get( id, &location );
561  switch ( location ) {
562    case OBJECTS_ERROR:
563      return RTEMS_INVALID_ID;
564    case OBJECTS_REMOTE:
565      _Thread_Dispatch();
566      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
567    case OBJECTS_LOCAL:
568      the_information = _Objects_Get_information( the_thread->Object.id );
569
570      if ( !the_information ) {
571        _Thread_Enable_dispatch();
572        return RTEMS_INVALID_ID;
573        /* This should never happen if _Thread_Get() works right */
574      }
575 
576      _Thread_Close( the_information, the_thread );
577
578      _RTEMS_tasks_Free( the_thread );
579
580      if ( the_thread->is_global ) {
581
582        _Objects_MP_Close( &_RTEMS_tasks_Information, the_thread->Object.id );
583
584        _RTEMS_tasks_MP_Send_process_packet(
585          RTEMS_TASKS_MP_ANNOUNCE_DELETE,
586          the_thread->Object.id,
587          0                                /* Not used */
588        );
589      }
590
591      _Thread_Enable_dispatch();
592      return RTEMS_SUCCESSFUL;
593  }
594
595  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
596}
597
598/*PAGE
599 *
600 *  rtems_task_suspend
601 *
602 *  This directive will place the specified thread in the "suspended"
603 *  state.  Note that the suspended state can be in addition to
604 *  other waiting states.
605 *
606 *  Input parameters:
607 *    id - thread id
608 *
609 *  Output parameters:
610 *    RTEMS_SUCCESSFUL - if successful
611 *    error code        - if unsuccessful
612 */
613
614rtems_status_code rtems_task_suspend(
615  Objects_Id id
616)
617{
618  register Thread_Control *the_thread;
619  Objects_Locations               location;
620
621  the_thread = _Thread_Get( id, &location );
622  switch ( location ) {
623    case OBJECTS_ERROR:
624      return RTEMS_INVALID_ID;
625    case OBJECTS_REMOTE:
626      return _RTEMS_tasks_MP_Send_request_packet(
627        RTEMS_TASKS_MP_SUSPEND_REQUEST,
628        id,
629        0,          /* Not used */
630        0,          /* Not used */
631        0           /* Not used */
632      );
633    case OBJECTS_LOCAL:
634      if ( !_States_Is_suspended( the_thread->current_state ) ) {
635        _Thread_Set_state( the_thread, STATES_SUSPENDED );
636        _Thread_Enable_dispatch();
637        return RTEMS_SUCCESSFUL;
638      }
639      _Thread_Enable_dispatch();
640      return RTEMS_ALREADY_SUSPENDED;
641  }
642
643  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
644}
645
646/*PAGE
647 *
648 *  rtems_task_resume
649 *
650 *  This directive will remove the specified thread
651 *  from the suspended state.
652 *
653 *  Input parameters:
654 *    id - thread id
655 *
656 *  Output parameters:
657 *    RTEMS_SUCCESSFUL - if successful
658 *    error code        - if unsuccessful
659 */
660
661rtems_status_code rtems_task_resume(
662  Objects_Id id
663)
664{
665  register Thread_Control *the_thread;
666  Objects_Locations        location;
667
668  the_thread = _Thread_Get( id, &location );
669  switch ( location ) {
670    case OBJECTS_ERROR:
671      return RTEMS_INVALID_ID;
672    case OBJECTS_REMOTE:
673      return(
674        _RTEMS_tasks_MP_Send_request_packet(
675          RTEMS_TASKS_MP_RESUME_REQUEST,
676          id,
677          0,          /* Not used */
678          0,          /* Not used */
679          0           /* Not used */
680        )
681      );
682    case OBJECTS_LOCAL:
683      if ( _States_Is_suspended( the_thread->current_state ) ) {
684        _Thread_Resume( the_thread );
685        _Thread_Enable_dispatch();
686        return RTEMS_SUCCESSFUL;
687      }
688      _Thread_Enable_dispatch();
689      return RTEMS_INCORRECT_STATE;
690  }
691
692  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
693}
694
695/*PAGE
696 *
697 *  rtems_task_set_priority
698 *
699 *  This directive changes the priority of the specified thread.
700 *  The specified thread can be any thread in the system including
701 *  the requesting thread.
702 *
703 *  Input parameters:
704 *    id           - thread id (0 indicates requesting thread)
705 *    new_priority - thread priority (0 indicates current priority)
706 *    old_priority - pointer to previous priority
707 *
708 *  Output parameters:
709 *    old_priority      - previous priority
710 *    RTEMS_SUCCESSFUL - if successful
711 *    error code        - if unsuccessful
712 */
713
714rtems_status_code rtems_task_set_priority(
715  Objects_Id           id,
716  rtems_task_priority  new_priority,
717  rtems_task_priority *old_priority
718)
719{
720  register Thread_Control *the_thread;
721  Objects_Locations               location;
722
723  if ( new_priority != RTEMS_CURRENT_PRIORITY &&
724       !_RTEMS_tasks_Priority_is_valid( new_priority ) )
725    return RTEMS_INVALID_PRIORITY;
726
727  the_thread = _Thread_Get( id, &location );
728  switch ( location ) {
729    case OBJECTS_ERROR:
730      return RTEMS_INVALID_ID;
731    case OBJECTS_REMOTE:
732      _Thread_Executing->Wait.return_argument = old_priority;
733      return(
734        _RTEMS_tasks_MP_Send_request_packet(
735          RTEMS_TASKS_MP_SET_PRIORITY_REQUEST,
736          id,
737          new_priority,
738          0,          /* Not used */
739          0           /* Not used */
740        )
741      );
742    case OBJECTS_LOCAL:
743      *old_priority = the_thread->current_priority;
744      if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
745        the_thread->real_priority = new_priority;
746        if ( the_thread->resource_count == 0 ||
747             the_thread->current_priority > new_priority )
748          _Thread_Change_priority( the_thread, new_priority, FALSE );
749      }
750      _Thread_Enable_dispatch();
751      return RTEMS_SUCCESSFUL;
752  }
753
754  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
755}
756
757/*PAGE
758 *
759 *  rtems_task_mode
760 *
761 *  This directive enables and disables several modes of
762 *  execution for the requesting thread.
763 *
764 *  Input parameters:
765 *    mode_set          - new mode
766 *    mask              - mask
767 *    previous_mode_set - address of previous mode set
768 *
769 *  Output:
770 *    *previous_mode_set - previous mode set
771 *     always return RTEMS_SUCCESSFUL;
772 */
773
774rtems_status_code rtems_task_mode(
775  rtems_mode  mode_set,
776  rtems_mode  mask,
777  rtems_mode *previous_mode_set
778)
779{
780  Thread_Control     *executing;
781  RTEMS_API_Control  *api;
782  ASR_Information    *asr;
783  boolean             is_asr_enabled = FALSE;
784  boolean             needs_asr_dispatching = FALSE;
785  rtems_mode          old_mode;
786
787  executing     = _Thread_Executing;
788  api = executing->API_Extensions[ THREAD_API_RTEMS ];
789  asr = &api->Signal;
790
791  old_mode  = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;
792
793  if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE )
794    old_mode |= RTEMS_NO_TIMESLICE;
795  else
796    old_mode |= RTEMS_TIMESLICE;
797
798  old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR;
799  old_mode |= _ISR_Get_level();
800
801  *previous_mode_set = old_mode;
802
803  /*
804   *  These are generic thread scheduling characteristics.
805   */
806
807  if ( mask & RTEMS_PREEMPT_MASK )
808    executing->is_preemptible = _Modes_Is_preempt(mode_set) ? TRUE : FALSE;
809
810  if ( mask & RTEMS_TIMESLICE_MASK ) {
811    if ( _Modes_Is_timeslice(mode_set) )
812      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
813    else
814      executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
815  }
816
817  /*
818   *  Set the new interrupt level
819   */
820
821  if ( mask & RTEMS_INTERRUPT_MASK )
822    _Modes_Set_interrupt_level( mode_set );
823
824  /*
825   *  This is specific to the RTEMS API
826   */
827
828  is_asr_enabled = FALSE;
829  needs_asr_dispatching = FALSE;
830
831  if ( mask & RTEMS_ASR_MASK ) {
832    is_asr_enabled = _Modes_Is_asr_disabled( mode_set ) ? FALSE : TRUE;
833    if ( is_asr_enabled != asr->is_enabled ) {
834      asr->is_enabled = is_asr_enabled;
835      _ASR_Swap_signals( asr );
836      if ( _ASR_Are_signals_pending( asr ) ) {
837        needs_asr_dispatching = TRUE;
838        executing->do_post_task_switch_extension = TRUE;
839      }
840    }
841  }
842
843  if ( _Thread_Evaluate_mode() || needs_asr_dispatching )
844    _Thread_Dispatch();
845
846  return RTEMS_SUCCESSFUL;
847}
848
849/*PAGE
850 *
851 *  rtems_task_get_note
852 *
853 *  This directive obtains the note from the specified notepad
854 *  of the specified thread.
855 *
856 *  Input parameters:
857 *    id      - thread id
858 *    notepad - notepad number
859 *    note    - pointer to note
860 *
861 *  Output parameters:
862 *    note              - filled in if successful
863 *    RTEMS_SUCCESSFUL - if successful
864 *    error code        - if unsuccessful
865 */
866
867rtems_status_code rtems_task_get_note(
868  Objects_Id  id,
869  unsigned32  notepad,
870  unsigned32 *note
871)
872{
873  register Thread_Control *the_thread;
874  Objects_Locations        location;
875  RTEMS_API_Control       *api;
876
877  /*
878   *  NOTE:  There is no check for < RTEMS_NOTEPAD_FIRST because that would
879   *         be checking an unsigned number for being negative.
880   */
881
882  if ( notepad > RTEMS_NOTEPAD_LAST )
883    return RTEMS_INVALID_NUMBER;
884
885  /*
886   *  Optimize the most likely case to avoid the Thread_Dispatch.
887   */
888
889  if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ||
890       _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) {
891      api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
892      *note = api->Notepads[ notepad ];
893      return RTEMS_SUCCESSFUL;
894  }
895
896  the_thread = _Thread_Get( id, &location );
897  switch ( location ) {
898    case OBJECTS_ERROR:
899      return RTEMS_INVALID_ID;
900    case OBJECTS_REMOTE:
901      _Thread_Executing->Wait.return_argument = note;
902
903      return _RTEMS_tasks_MP_Send_request_packet(
904        RTEMS_TASKS_MP_GET_NOTE_REQUEST,
905        id,
906        0,          /* Not used */
907        notepad,
908        0           /* Not used */
909      );
910    case OBJECTS_LOCAL:
911      api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
912      *note = api->Notepads[ notepad ];
913      _Thread_Enable_dispatch();
914      return RTEMS_SUCCESSFUL;
915  }
916
917  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
918}
919
920/*PAGE
921 *
922 * rtems_task_set_note
923 *
924 *  This directive sets the specified notepad contents to the given
925 *  note.
926 *
927 *  Input parameters:
928 *    id      - thread id
929 *    notepad - notepad number
930 *    note    - note value
931 *
932 *  Output parameters:
933 *    RTEMS_SUCCESSFUL - if successful
934 *    error code        - if unsuccessful
935 */
936
937rtems_status_code rtems_task_set_note(
938  Objects_Id id,
939  unsigned32 notepad,
940  unsigned32 note
941)
942{
943  register Thread_Control *the_thread;
944  Objects_Locations        location;
945  RTEMS_API_Control       *api;
946
947  /*
948   *  NOTE:  There is no check for < RTEMS_NOTEPAD_FIRST because that would
949   *         be checking an unsigned number for being negative.
950   */
951
952  if ( notepad > RTEMS_NOTEPAD_LAST )
953    return RTEMS_INVALID_NUMBER;
954
955  /*
956   *  Optimize the most likely case to avoid the Thread_Dispatch.
957   */
958
959  if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ||
960       _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) {
961      api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
962      api->Notepads[ notepad ] = note;
963      return RTEMS_SUCCESSFUL;
964  }
965
966  the_thread = _Thread_Get( id, &location );
967  switch ( location ) {
968    case OBJECTS_ERROR:
969      return RTEMS_INVALID_ID;
970    case OBJECTS_REMOTE:
971      return _RTEMS_tasks_MP_Send_request_packet(
972        RTEMS_TASKS_MP_SET_NOTE_REQUEST,
973        id,
974        0,          /* Not used */
975        notepad,
976        note
977      );
978
979    case OBJECTS_LOCAL:
980      api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
981      api->Notepads[ notepad ] = note;
982      _Thread_Enable_dispatch();
983      return RTEMS_SUCCESSFUL;
984  }
985
986  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
987}
988
989/*PAGE
990 *
991 *  rtems_task_wake_after
992 *
993 *  This directive suspends the requesting thread for the given amount
994 *  of ticks.
995 *
996 *  Input parameters:
997 *    ticks - number of ticks to wait
998 *
999 *  Output parameters:
1000 *    RTEMS_SUCCESSFUL - always successful
1001 */
1002
1003rtems_status_code rtems_task_wake_after(
1004  rtems_interval ticks
1005)
1006{
1007  if ( ticks == 0 ) {
1008    _Thread_Yield_processor();
1009    _Thread_Dispatch();
1010  } else {
1011    _Thread_Disable_dispatch();
1012      _Thread_Set_state( _Thread_Executing, STATES_DELAYING );
1013      _Watchdog_Initialize(
1014        &_Thread_Executing->Timer,
1015        _Thread_Delay_ended,
1016        _Thread_Executing->Object.id,
1017        NULL
1018      );
1019      _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
1020    _Thread_Enable_dispatch();
1021  }
1022  return RTEMS_SUCCESSFUL;
1023}
1024
1025/*PAGE
1026 *
1027 *  rtems_task_wake_when
1028 *
1029 *  This directive blocks the requesting thread until the given date and
1030 *  time is reached.
1031 *
1032 *  Input parameters:
1033 *    time_buffer - pointer to the time and date structure
1034 *
1035 *  Output parameters:
1036 *    RTEMS_SUCCESSFUL - if successful
1037 *    error code        - if unsuccessful
1038 */
1039
1040rtems_status_code rtems_task_wake_when(
1041rtems_time_of_day *time_buffer
1042)
1043{
1044  Watchdog_Interval   seconds;
1045
1046  if ( !_TOD_Is_set )
1047    return RTEMS_NOT_DEFINED;
1048
1049  time_buffer->ticks = 0;
1050
1051  if ( !_TOD_Validate( time_buffer ) )
1052    return RTEMS_INVALID_CLOCK;
1053
1054  seconds = _TOD_To_seconds( time_buffer );
1055
1056  if ( seconds <= _TOD_Seconds_since_epoch )
1057    return RTEMS_INVALID_CLOCK;
1058
1059  _Thread_Disable_dispatch();
1060    _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_TIME );
1061    _Watchdog_Initialize(
1062      &_Thread_Executing->Timer,
1063      _Thread_Delay_ended,
1064      _Thread_Executing->Object.id,
1065      NULL
1066    );
1067    _Watchdog_Insert_seconds(
1068      &_Thread_Executing->Timer,
1069      seconds - _TOD_Seconds_since_epoch
1070    );
1071  _Thread_Enable_dispatch();
1072  return RTEMS_SUCCESSFUL;
1073}
1074
1075/*PAGE
1076 *
1077 *  _RTEMS_tasks_Initialize_user_tasks
1078 *
1079 *  This routine creates and starts all configured user
1080 *  initialzation threads.
1081 *
1082 *  Input parameters: NONE
1083 *
1084 *  Output parameters:  NONE
1085 */
1086
1087void _RTEMS_tasks_Initialize_user_tasks( void )
1088{
1089  unsigned32                        index;
1090  unsigned32                        maximum;
1091  rtems_id                          id;
1092  rtems_status_code                 return_value;
1093  rtems_initialization_tasks_table *user_tasks;
1094
1095  /*
1096   *  NOTE:  This is slightly different from the Ada implementation.
1097   */
1098
1099  user_tasks = _RTEMS_tasks_User_initialization_tasks;
1100  maximum    = _RTEMS_tasks_Number_of_initialization_tasks;
1101
1102  if ( !user_tasks || maximum == 0 )
1103    return;
1104
1105  for ( index=0 ; index < maximum ; index++ ) {
1106    return_value = rtems_task_create(
1107      user_tasks[ index ].name,
1108      user_tasks[ index ].initial_priority,
1109      user_tasks[ index ].stack_size,
1110      user_tasks[ index ].mode_set,
1111      user_tasks[ index ].attribute_set,
1112      &id
1113    );
1114
1115    if ( !rtems_is_status_successful( return_value ) )
1116      _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, return_value );
1117
1118    return_value = rtems_task_start(
1119      id,
1120      user_tasks[ index ].entry_point,
1121      user_tasks[ index ].argument
1122    );
1123
1124    if ( !rtems_is_status_successful( return_value ) )
1125      _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, return_value );
1126  }
1127}
1128
Note: See TracBrowser for help on using the repository browser.