source: rtems/cpukit/rtems/src/tasks.c @ 5a909149

4.104.114.84.95
Last change on this file since 5a909149 was 5a909149, checked in by Joel Sherrill <joel.sherrill@…>, on May 7, 1999 at 5:09:20 PM

Made all calls to _Thread_Yield_processor consistent in how they are
wrapped by calls to _Thread_Enable_dispatch and _Thread_Disable_dispatch.

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