source: rtems/cpukit/rtems/src/tasks.c @ ea5df0e

4.104.114.84.95
Last change on this file since ea5df0e was 3652ad35, checked in by Joel Sherrill <joel.sherrill@…>, on 09/19/95 at 14:53:29

Minor bug fixes to get all targets compilable and running. The
single biggest changes were the expansion of the workspace size
macro to include other types of objects and the increase in the
minimum stack size for most CPUs.

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