source: rtems/cpukit/rtems/src/tasks.c @ 3a4ae6c

4.104.114.84.95
Last change on this file since 3a4ae6c was 3a4ae6c, checked in by Joel Sherrill <joel.sherrill@…>, on 09/11/95 at 19:35:39

The word "RTEMS" almost completely removed from the core.

Configuration Table Template file added and all tests
modified to use this. All gvar.h and conftbl.h files
removed from test directories.

Configuration parameter maximum_devices added.

Core semaphore and mutex handlers added and RTEMS API Semaphore
Manager updated to reflect this.

Initialization sequence changed to invoke API specific initialization
routines. Initialization tasks table now owned by RTEMS Tasks Manager.

Added user extension for post-switch.

Utilized user extensions to implement API specific functionality
like signal dispatching.

Added extensions to the System Initialization Thread so that an
API can register a function to be invoked while the system
is being initialized. These are largely equivalent to the
pre-driver and post-driver hooks.

Added the Modules file oar-go32_p5, modified oar-go32, and modified
the file make/custom/go32.cfg to look at an environment varable which
determines what CPU model is being used.

All BSPs updated to reflect named devices and clock driver's IOCTL
used by the Shared Memory Driver. Also merged clock isr into
main file and removed ckisr.c where possible.

Updated spsize to reflect new and moved variables.

Makefiles for the executive source and include files updated to show
break down of files into Core, RTEMS API, and Neither.

Header and inline files installed into subdirectory based on whether
logically in the Core or a part of the RTEMS API.

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