source: rtems/cpukit/score/src/thread.c @ 7f6a24ab

4.104.114.84.95
Last change on this file since 7f6a24ab was 7f6a24ab, checked in by Joel Sherrill <joel.sherrill@…>, on 08/28/95 at 15:30:29

Added unused priority ceiling parameter to rtems_semaphore_create.

Rearranged code to created thread handler routines to initialize,
start, restart, and "close/delete" a thread.

Made internal threads their own object class. This now uses the
thread support routines for starting and initializing a thread.

Insured deleted tasks are freed to the Inactive pool associated with the
correct Information block.

Added an RTEMS API specific data area to the thread control block.

Beginnings of removing the word "rtems" from the core.

  • Property mode set to 100644
File size: 25.7 KB
Line 
1/*
2 *  Thread Handler
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/config.h>
18#include <rtems/context.h>
19#include <rtems/fatal.h>
20#include <rtems/init.h>
21#include <rtems/intthrd.h>
22#include <rtems/isr.h>
23#include <rtems/modes.h>
24#include <rtems/object.h>
25#include <rtems/priority.h>
26#include <rtems/states.h>
27#include <rtems/thread.h>
28#include <rtems/userext.h>
29#include <rtems/wkspace.h>
30
31/*PAGE
32 *
33 *  _Thread_Handler_initialization
34 *
35 *  This routine initializes all thread manager related data structures.
36 *
37 *  Input parameters:
38 *    ticks_per_timeslice - clock ticks per quantum
39 *    maximum_proxies     - number of proxies to initialize
40 *
41 *  Output parameters:  NONE
42 */
43
44void _Thread_Handler_initialization(
45  unsigned32   ticks_per_timeslice,
46  unsigned32   maximum_proxies
47)
48{
49  unsigned32 index;
50
51  _Context_Switch_necessary = FALSE;
52  _Thread_Executing         = NULL;
53  _Thread_Heir              = NULL;
54  _Thread_Allocated_fp      = NULL;
55
56  _Thread_Ticks_remaining_in_timeslice = ticks_per_timeslice;
57  _Thread_Ticks_per_timeslice          = ticks_per_timeslice;
58
59  _Thread_Ready_chain = _Workspace_Allocate_or_fatal_error(
60    (RTEMS_MAXIMUM_PRIORITY + 1) * sizeof(Chain_Control)
61  );
62
63  for ( index=0; index <= RTEMS_MAXIMUM_PRIORITY ; index++ )
64    _Chain_Initialize_empty( &_Thread_Ready_chain[ index ] );
65
66  _Thread_MP_Handler_initialization( maximum_proxies );
67}
68
69/*PAGE
70 *
71 *  _Thread_Start_multitasking
72 *
73 *  This kernel routine readies the requested thread, the thread chain
74 *  is adjusted.  A new heir thread may be selected.
75 *
76 *  Input parameters:
77 *    system_thread - pointer to system initialization thread control block
78 *    idle_thread   - pointer to idle thread control block
79 *
80 *  Output parameters:  NONE
81 *
82 *  NOTE:  This routine uses the "blocking" heir selection mechanism.
83 *         This insures the correct heir after a thread restart.
84 *
85 *  INTERRUPT LATENCY:
86 *    ready chain
87 *    select heir
88 */
89
90void _Thread_Start_multitasking(
91  Thread_Control *system_thread,
92  Thread_Control *idle_thread
93)
94{
95
96   _Thread_Executing  =
97   _Thread_Heir       =
98   _Thread_MP_Receive = system_thread;
99
100   /*
101    *  Scheduling will not work "correctly" until the above
102    *  statements have been executed.
103    */
104
105   _Thread_Ready( system_thread );
106   _Thread_Ready( idle_thread );
107
108   _Context_Switch_necessary = FALSE;
109
110   _Context_Switch( &_Thread_BSP_context, &system_thread->Registers );
111
112}
113
114/*PAGE
115 *
116 *  _Thread_Dispatch
117 *
118 *  This kernel routine determines if a dispatch is needed, and if so
119 *  dispatches to the heir thread.  Once the heir is running an attempt
120 *  is made to dispatch any ASRs.
121 *
122 *  ALTERNATE ENTRY POINTS:
123 *    void _Thread_Enable_dispatch();
124 *
125 *  Input parameters:  NONE
126 *
127 *  Output parameters:  NONE
128 *
129 *  INTERRUPT LATENCY:
130 *    dispatch thread
131 *    no dispatch thread
132 */
133
134#if ( CPU_INLINE_ENABLE_DISPATCH == FALSE )
135void _Thread_Enable_dispatch( void )
136{
137  if ( --_Thread_Dispatch_disable_level )
138    return;
139  _Thread_Dispatch();
140}
141#endif
142
143void _Thread_Dispatch( void )
144{
145  Thread_Control   *executing;
146  Thread_Control   *heir;
147  ISR_Level         level;
148  rtems_signal_set  signal_set;
149  Modes_Control     previous_mode;
150
151  executing   = _Thread_Executing;
152  _ISR_Disable( level );
153  while ( _Context_Switch_necessary == TRUE ) {
154    heir = _Thread_Heir;
155    _Thread_Dispatch_disable_level = 1;
156    _Context_Switch_necessary = FALSE;
157    _Thread_Executing = heir;
158    _ISR_Enable( level );
159
160    _User_extensions_Task_switch( executing, heir );
161
162    _Thread_Ticks_remaining_in_timeslice = _Thread_Ticks_per_timeslice;
163
164    /*
165     *  If the CPU has hardware floating point, then we must address saving
166     *  and restoring it as part of the context switch.
167     *
168     *  The second conditional compilation section selects the algorithm used
169     *  to context switch between floating point tasks.  The deferred algorithm
170     *  can be significantly better in a system with few floating point tasks
171     *  because it reduces the total number of save and restore FP context
172     *  operations.  However, this algorithm can not be used on all CPUs due
173     *  to unpredictable use of FP registers by some compilers for integer
174     *  operations.
175     */
176
177#if ( CPU_HARDWARE_FP == TRUE )
178#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
179    if ( (heir->fp_context != NULL) && !_Thread_Is_allocated_fp( heir ) ) {
180      if ( _Thread_Allocated_fp != NULL )
181        _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
182      _Context_Restore_fp( &heir->fp_context );
183      _Thread_Allocated_fp = heir;
184    }
185#else
186    if ( executing->fp_context != NULL )
187      _Context_Save_fp( &executing->fp_context );
188
189    if ( heir->fp_context != NULL )
190      _Context_Restore_fp( &heir->fp_context );
191#endif
192#endif
193
194    _Context_Switch( &executing->Registers, &heir->Registers );
195
196    executing = _Thread_Executing;
197    _ISR_Disable( level );
198  }
199
200  _Thread_Dispatch_disable_level = 0;
201
202  if ( _ASR_Are_signals_pending( &executing->RTEMS_API->Signal ) ) {
203    signal_set = executing->RTEMS_API->Signal.signals_posted;
204    executing->RTEMS_API->Signal.signals_posted = 0;
205    _ISR_Enable( level );
206
207    executing->RTEMS_API->Signal.nest_level += 1;
208    if (_Thread_Change_mode( executing->RTEMS_API->Signal.mode_set,
209                                RTEMS_ALL_MODE_MASKS, &previous_mode ))
210        _Thread_Dispatch();
211
212    (*executing->RTEMS_API->Signal.handler)( signal_set );
213
214    executing->RTEMS_API->Signal.nest_level -= 1;
215    if (_Thread_Change_mode( previous_mode,
216                                RTEMS_ALL_MODE_MASKS, &previous_mode ))
217        _Thread_Dispatch();
218  }
219  else
220    _ISR_Enable( level );
221}
222
223/*PAGE
224 *
225 *  _Thread_Initialize
226 *
227 *  XXX
228 */
229
230boolean _Thread_Initialize(
231  Objects_Information *information,
232  Thread_Control      *the_thread,
233  void                *stack_area,    /* NULL if to be allocated */
234  unsigned32           stack_size,    /* insure it is >= min */
235  boolean              is_fp,         /* TRUE if thread uses FP */
236  Priority_Control     priority,
237  Modes_Control        mode,
238  Objects_Name         name
239 
240)
241{
242  unsigned32           actual_stack_size;
243  void                *stack;
244  void                *fp_area;
245
246  /*
247   *  Allocate and Initialize the stack for this thread.
248   */
249
250  if ( !_Stack_Is_enough( stack_size ) )
251    actual_stack_size = RTEMS_MINIMUM_STACK_SIZE;
252  else
253    actual_stack_size = stack_size;
254
255  actual_stack_size = _Stack_Adjust_size( actual_stack_size );
256  stack             = stack_area;
257
258  if ( !stack ) {
259    stack = _Workspace_Allocate( actual_stack_size );
260 
261    if ( !stack )
262      return FALSE;
263
264    the_thread->Start.stack = stack;
265  } else
266    the_thread->Start.stack = NULL;
267
268  _Stack_Initialize(
269     &the_thread->Start.Initial_stack,
270     stack,
271     actual_stack_size
272  );
273
274  /*
275   *  Allocate the floating point area for this thread
276   */
277 
278  if ( is_fp ) {
279
280    fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
281    if ( !fp_area ) {
282      (void) _Workspace_Free( stack );
283      return FALSE;
284    }
285    fp_area = _Context_Fp_start( fp_area, 0 );
286
287  } else
288    fp_area = NULL;
289
290  the_thread->fp_context       = fp_area;
291  the_thread->Start.fp_context = fp_area;
292 
293/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
294  /*
295   *  Allocate and initialize the RTEMS API specific information
296   */
297 
298  the_thread->RTEMS_API = _Workspace_Allocate( sizeof( RTEMS_API_Control ) );
299 
300  if ( !the_thread->RTEMS_API ) {
301/* XXX when in task_create
302    _RTEMS_tasks_Free( the_thread );
303    _Objects_MP_Free_global_object( the_global_object );
304
305    _Thread_Enable_dispatch();
306    return( RTEMS_UNSATISFIED );
307*/
308      (void) _Workspace_Free( stack );
309      (void) _Workspace_Free( fp_area );
310      return FALSE;
311 
312  }
313 
314  the_thread->RTEMS_API->is_global              = FALSE;
315  the_thread->RTEMS_API->pending_events         = EVENT_SETS_NONE_PENDING;
316  _ASR_Initialize( &the_thread->RTEMS_API->Signal );
317
318  /* XXX should not be here .... */
319 
320/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
321
322  /*
323   *  General initialization
324   */
325
326  the_thread->current_state          = STATES_DORMANT;
327  the_thread->current_modes          = mode;
328  the_thread->resource_count         = 0;
329  the_thread->real_priority          = priority;
330  the_thread->Start.initial_priority = priority;
331  the_thread->Start.initial_modes    = mode;
332 
333  _Thread_Set_priority( the_thread, priority );
334
335  /*
336   *  Open the object
337   */
338
339  _Objects_Open( information, &the_thread->Object, name );
340
341  /*
342   *  Invoke create extensions
343   */
344
345  _User_extensions_Task_create( the_thread );
346  /* XXX if this fails ... */
347
348  return TRUE;
349}
350
351/*
352 *  _Thread_Start
353 *
354 *  DESCRIPTION:
355 *
356 *  XXX
357 */
358 
359boolean _Thread_Start(
360  Thread_Control       *the_thread,
361  Thread_Start_types    the_prototype,
362  void                 *entry_point,
363  void                 *pointer_argument,
364  unsigned32            numeric_argument
365)
366{
367  if ( _States_Is_dormant( the_thread->current_state ) ) {
368 
369    the_thread->Start.entry_point      = entry_point;
370   
371    the_thread->Start.prototype        = the_prototype;
372    the_thread->Start.pointer_argument = pointer_argument;
373    the_thread->Start.numeric_argument = numeric_argument;
374 
375    _Thread_Load_environment( the_thread );
376 
377    _Thread_Ready( the_thread );
378 
379    _User_extensions_Task_start( the_thread );
380 
381    return TRUE;
382  }
383 
384  return FALSE;
385 
386}
387
388/*
389 *  _Thread_Restart
390 *
391 *  DESCRIPTION:
392 *
393 *  XXX
394 */
395 
396boolean _Thread_Restart(
397  Thread_Control      *the_thread,
398  void                *pointer_argument,
399  unsigned32           numeric_argument
400)
401{
402  if ( !_States_Is_dormant( the_thread->current_state ) ) {
403 
404    _Thread_Set_transient( the_thread );
405    the_thread->resource_count = 0;
406    the_thread->current_modes  = the_thread->Start.initial_modes;
407
408    the_thread->Start.pointer_argument = pointer_argument;
409    the_thread->Start.numeric_argument = numeric_argument;
410 
411    if ( !_Thread_queue_Extract_with_proxy( the_thread ) ) {
412 
413      if ( _Watchdog_Is_active( &the_thread->Timer ) )
414        (void) _Watchdog_Remove( &the_thread->Timer );
415    }
416
417    if ( the_thread->current_priority != the_thread->Start.initial_priority ) {
418      the_thread->real_priority = the_thread->Start.initial_priority;
419      _Thread_Set_priority( the_thread, the_thread->Start.initial_priority );
420    }
421 
422    _Thread_Load_environment( the_thread );
423 
424    _Thread_Ready( the_thread );
425 
426    _User_extensions_Task_restart( the_thread );
427 
428    if ( _Thread_Is_executing ( the_thread ) )
429      _Thread_Restart_self();
430 
431    return TRUE;
432  }
433 
434  return FALSE;
435}
436
437/*
438 *  _Thread_Close
439 *
440 *  DESCRIPTION:
441 *
442 *  XXX
443 */
444 
445void _Thread_Close(
446  Objects_Information  *information,
447  Thread_Control       *the_thread
448)
449{
450  _Objects_Close( information, &the_thread->Object );
451 
452  _Thread_Set_state( the_thread, STATES_TRANSIENT );
453 
454  if ( !_Thread_queue_Extract_with_proxy( the_thread ) ) {
455 
456    if ( _Watchdog_Is_active( &the_thread->Timer ) )
457      (void) _Watchdog_Remove( &the_thread->Timer );
458  }
459
460  _User_extensions_Task_delete( the_thread );
461 
462#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
463  if ( _Thread_Is_allocated_fp( the_thread ) )
464    _Thread_Deallocate_fp();
465#endif
466  the_thread->fp_context = NULL;
467
468  (void) _Workspace_Free( the_thread->Start.fp_context );
469
470  if ( the_thread->Start.stack )
471    (void) _Workspace_Free( the_thread->Start.stack );
472}
473
474/*PAGE
475 *
476 *  _Thread_Ready
477 *
478 *  This kernel routine readies the requested thread, the thread chain
479 *  is adjusted.  A new heir thread may be selected.
480 *
481 *  Input parameters:
482 *    the_thread - pointer to thread control block
483 *
484 *  Output parameters:  NONE
485 *
486 *  NOTE:  This routine uses the "blocking" heir selection mechanism.
487 *         This insures the correct heir after a thread restart.
488 *
489 *  INTERRUPT LATENCY:
490 *    ready chain
491 *    select heir
492 */
493
494void _Thread_Ready(
495  Thread_Control *the_thread
496)
497{
498  ISR_Level              level;
499  Thread_Control *heir;
500
501  _ISR_Disable( level );
502
503  the_thread->current_state = STATES_READY;
504
505  _Priority_Add_to_bit_map( &the_thread->Priority_map );
506
507  _Chain_Append_unprotected( the_thread->ready, &the_thread->Object.Node );
508
509  _ISR_Flash( level );
510
511  _Thread_Calculate_heir();
512
513  heir = _Thread_Heir;
514
515  if ( !_Thread_Is_executing( heir ) &&
516        _Modes_Is_preempt( _Thread_Executing->current_modes ) )
517    _Context_Switch_necessary = TRUE;
518
519  _ISR_Enable( level );
520}
521
522/*PAGE
523 *
524 *  _Thread_Clear_state
525 *
526 *  This kernel routine clears the appropriate states in the
527 *  requested thread.  The thread ready chain is adjusted if
528 *  necessary and the Heir thread is set accordingly.
529 *
530 *  Input parameters:
531 *    the_thread - pointer to thread control block
532 *    state      - state set to clear
533 *
534 *  Output parameters:  NONE
535 *
536 *  INTERRUPT LATENCY:
537 *    priority map
538 *    select heir
539 */
540
541void _Thread_Clear_state(
542  Thread_Control *the_thread,
543  States_Control  state
544)
545{
546  ISR_Level level;
547
548  _ISR_Disable( level );
549    the_thread->current_state =
550      _States_Clear( state, the_thread->current_state );
551
552    if ( _States_Is_ready( the_thread->current_state ) ) {
553
554      _Priority_Add_to_bit_map( &the_thread->Priority_map );
555
556      _Chain_Append_unprotected( the_thread->ready, &the_thread->Object.Node );
557
558      _ISR_Flash( level );
559
560      if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
561        _Thread_Heir = the_thread;
562        if ( _Modes_Is_preempt( _Thread_Executing->current_modes ) ||
563             the_thread->current_priority == 0 )
564          _Context_Switch_necessary = TRUE;
565      }
566    }
567  _ISR_Enable( level );
568}
569
570/*PAGE
571 *
572 * _Thread_Set_state
573 *
574 * This kernel routine sets the requested state in the THREAD.  The
575 * THREAD chain is adjusted if necessary.
576 *
577 * Input parameters:
578 *   the_thread   - pointer to thread control block
579 *   state - state to be set
580 *
581 * Output parameters:  NONE
582 *
583 *  INTERRUPT LATENCY:
584 *    ready chain
585 *    select map
586 */
587
588void _Thread_Set_state(
589  Thread_Control *the_thread,
590  States_Control         state
591)
592{
593  ISR_Level             level;
594  Chain_Control *ready;
595
596  ready = the_thread->ready;
597  _ISR_Disable( level );
598  if ( !_States_Is_ready( the_thread->current_state ) ) {
599    the_thread->current_state =
600       _States_Set( state, the_thread->current_state );
601    _ISR_Enable( level );
602    return;
603  }
604
605  the_thread->current_state = state;
606
607  if ( _Chain_Has_only_one_node( ready ) ) {
608
609    _Chain_Initialize_empty( ready );
610    _Priority_Remove_from_bit_map( &the_thread->Priority_map );
611
612  } else
613    _Chain_Extract_unprotected( &the_thread->Object.Node );
614
615  _ISR_Flash( level );
616
617  if ( _Thread_Is_heir( the_thread ) )
618     _Thread_Calculate_heir();
619
620  if ( _Thread_Is_executing( the_thread ) )
621    _Context_Switch_necessary = TRUE;
622
623  _ISR_Enable( level );
624}
625
626/*PAGE
627 *
628 *  _Thread_Set_transient
629 *
630 *  This kernel routine places the requested thread in the transient state
631 *  which will remove it from the ready queue, if necessary.  No
632 *  rescheduling is necessary because it is assumed that the transient
633 *  state will be cleared before dispatching is enabled.
634 *
635 *  Input parameters:
636 *    the_thread - pointer to thread control block
637 *
638 *  Output parameters:  NONE
639 *
640 *  INTERRUPT LATENCY:
641 *    only case
642 */
643
644void _Thread_Set_transient(
645  Thread_Control *the_thread
646)
647{
648  ISR_Level             level;
649  unsigned32            old_state;
650  Chain_Control *ready;
651
652  ready = the_thread->ready;
653  _ISR_Disable( level );
654
655  old_state = the_thread->current_state;
656  the_thread->current_state = _States_Set( STATES_TRANSIENT, old_state );
657
658  if ( _States_Is_ready( old_state ) ) {
659    if ( _Chain_Has_only_one_node( ready ) ) {
660
661      _Chain_Initialize_empty( ready );
662      _Priority_Remove_from_bit_map( &the_thread->Priority_map );
663
664    } else
665      _Chain_Extract_unprotected( &the_thread->Object.Node );
666  }
667
668  _ISR_Enable( level );
669
670}
671
672/*PAGE
673 *
674 *  _Thread_Reset_timeslice
675 *
676 *  This routine will remove the running thread from the ready chain
677 *  and place it immediately at the rear of this chain and then the
678 *  timeslice counter is reset.  The heir THREAD will be updated if
679 *  the running is also the currently the heir.
680 *
681 *  Input parameters:   NONE
682 *
683 *  Output parameters:  NONE
684 *
685 *  INTERRUPT LATENCY:
686 *    ready chain
687 *    select heir
688 */
689
690void _Thread_Reset_timeslice( void )
691{
692  ISR_Level              level;
693  Thread_Control *executing;
694  Chain_Control  *ready;
695
696  executing = _Thread_Executing;
697  ready     = executing->ready;
698  _ISR_Disable( level );
699    if ( _Chain_Has_only_one_node( ready ) ) {
700      _Thread_Ticks_remaining_in_timeslice = _Thread_Ticks_per_timeslice;
701      _ISR_Enable( level );
702      return;
703    }
704    _Chain_Extract_unprotected( &executing->Object.Node );
705    _Chain_Append_unprotected( ready, &executing->Object.Node );
706
707  _ISR_Flash( level );
708
709    if ( _Thread_Is_heir( executing ) )
710      _Thread_Heir = (Thread_Control *) ready->first;
711
712    _Context_Switch_necessary = TRUE;
713
714  _ISR_Enable( level );
715}
716
717/*PAGE
718 *
719 *  _Thread_Tickle_timeslice
720 *
721 *  This scheduler routine determines if timeslicing is enabled
722 *  for the currently executing thread and, if so, updates the
723 *  timeslice count and checks for timeslice expiration.
724 *
725 *  Input parameters:   NONE
726 *
727 *  Output parameters:  NONE
728 */
729
730void _Thread_Tickle_timeslice( void )
731{
732  if ( ( _Modes_Is_timeslice(_Thread_Executing->current_modes) )  &&
733       ( _States_Is_ready( _Thread_Executing->current_state ) ) &&
734       ( --_Thread_Ticks_remaining_in_timeslice == 0 ) ) {
735      _Thread_Reset_timeslice();
736  }
737}
738
739/*PAGE
740 *
741 *  _Thread_Yield_processor
742 *
743 *  This kernel routine will remove the running THREAD from the ready chain
744 *  and place it immediatly at the rear of this chain.  Reset timeslice
745 *  and yield the processor functions both use this routine, therefore if
746 *  reset is TRUE and this is the only thread on the chain then the
747 *  timeslice counter is reset.  The heir THREAD will be updated if the
748 *  running is also the currently the heir.
749 *
750 *  Input parameters:   NONE
751 *
752 *  Output parameters:  NONE
753 *
754 *  INTERRUPT LATENCY:
755 *    ready chain
756 *    select heir
757 */
758
759void _Thread_Yield_processor( void )
760{
761  ISR_Level       level;
762  Thread_Control *executing;
763  Chain_Control  *ready;
764
765  executing = _Thread_Executing;
766  ready     = executing->ready;
767  _ISR_Disable( level );
768    if ( !_Chain_Has_only_one_node( ready ) ) {
769      _Chain_Extract_unprotected( &executing->Object.Node );
770      _Chain_Append_unprotected( ready, &executing->Object.Node );
771
772      _ISR_Flash( level );
773
774      if ( _Thread_Is_heir( executing ) )
775        _Thread_Heir = (Thread_Control *) ready->first;
776      _Context_Switch_necessary = TRUE;
777    }
778    else if ( !_Thread_Is_heir( executing ) )
779      _Context_Switch_necessary = TRUE;
780
781  _ISR_Enable( level );
782}
783
784/*PAGE
785 *
786 *  _Thread_Load_environment
787 *
788 *  Load starting environment for another thread from its start area in the
789 *  thread.  Only called from t_restart and t_start.
790 *
791 *  Input parameters:
792 *    the_thread - thread control block pointer
793 *
794 *  Output parameters:  NONE
795 */
796
797void _Thread_Load_environment(
798  Thread_Control *the_thread
799)
800{
801  if ( the_thread->Start.fp_context ) {
802    the_thread->fp_context = the_thread->Start.fp_context;
803    _Context_Initialize_fp( &the_thread->fp_context );
804  }
805
806  _Context_Initialize(
807    &the_thread->Registers,
808    the_thread->Start.Initial_stack.area,
809    the_thread->Start.Initial_stack.size,
810    _Modes_Get_interrupt_level( the_thread->Start.initial_modes ),
811    _Thread_Handler
812  );
813
814}
815
816/*PAGE
817 *
818 *  _Thread_Handler
819 *
820 *  This routine is the default thread exitted error handler.  It is
821 *  returned to when a thread exits.  The configured fatal error handler
822 *  is invoked to process the exit.
823 *
824 *  Input parameters:   NONE
825 *
826 *  Output parameters:  NONE
827 */
828
829void _Thread_Handler( void )
830{
831  Thread_Control *executing;
832
833  executing = _Thread_Executing;
834
835  /*
836   * Take care that 'begin' extensions get to complete before
837   * 'switch' extensions can run.  This means must keep dispatch
838   * disabled until all 'begin' extensions complete.
839   */
840 
841  _User_extensions_Task_begin( executing );
842 
843  /*
844   *  At this point, the dispatch disable level BETTER be 1.
845   */
846
847  _Thread_Enable_dispatch();
848 
849  switch (  executing->Start.prototype ) {
850    case THREAD_START_NUMERIC:
851      (*executing->Start.entry_point)( executing->Start.numeric_argument );
852      break;
853    case THREAD_START_POINTER:
854      (*executing->Start.entry_point)( executing->Start.pointer_argument );
855      break;
856    case THREAD_START_BOTH_POINTER_FIRST:
857      (*executing->Start.entry_point)(
858        executing->Start.pointer_argument,
859        executing->Start.numeric_argument
860      );
861      break;
862    case THREAD_START_BOTH_NUMERIC_FIRST:
863      (*executing->Start.entry_point)(
864        executing->Start.numeric_argument,
865        executing->Start.pointer_argument
866      );
867      break;
868  }
869
870  _User_extensions_Task_exitted( executing );
871
872  rtems_fatal_error_occurred( RTEMS_TASK_EXITTED );
873}
874
875/*PAGE
876 *
877 *  _Thread_Delay_ended
878 *
879 *  This routine processes a thread whose delay period has ended.
880 *  It is called by the watchdog handler.
881 *
882 *  Input parameters:
883 *    id - thread id
884 *
885 *  Output parameters: NONE
886 */
887
888void _Thread_Delay_ended(
889  Objects_Id  id,
890  void       *ignored
891)
892{
893  Thread_Control    *the_thread;
894  Objects_Locations  location;
895
896  the_thread = _Thread_Get( id, &location );
897  switch ( location ) {
898    case OBJECTS_ERROR:
899    case OBJECTS_REMOTE:  /* impossible */
900      break;
901    case OBJECTS_LOCAL:
902      _Thread_Unblock( the_thread );
903      _Thread_Unnest_dispatch();
904      break;
905  }
906}
907
908/*PAGE
909 *
910 *  _Thread_Change_priority
911 *
912 *  This kernel routine changes the priority of the thread.  The
913 *  thread chain is adjusted if necessary.
914 *
915 *  Input parameters:
916 *    the_thread   - pointer to thread control block
917 *    new_priority - ultimate priority
918 *
919 *  Output parameters:  NONE
920 *
921 *  INTERRUPT LATENCY:
922 *    ready chain
923 *    select heir
924 */
925
926void _Thread_Change_priority(
927  Thread_Control   *the_thread,
928  Priority_Control  new_priority
929)
930{
931  ISR_Level level;
932
933  _Thread_Set_transient( the_thread );
934
935  if ( the_thread->current_priority != new_priority )
936    _Thread_Set_priority( the_thread, new_priority );
937
938  _ISR_Disable( level );
939
940  the_thread->current_state =
941    _States_Clear( STATES_TRANSIENT, the_thread->current_state );
942
943  if ( ! _States_Is_ready( the_thread->current_state ) ) {
944    _ISR_Enable( level );
945    return;
946  }
947
948  _Priority_Add_to_bit_map( &the_thread->Priority_map );
949  _Chain_Append_unprotected( the_thread->ready, &the_thread->Object.Node );
950
951  _ISR_Flash( level );
952
953  _Thread_Calculate_heir();
954
955  if ( !_Thread_Is_executing_also_the_heir() &&
956       _Modes_Is_preempt(_Thread_Executing->current_modes) )
957    _Context_Switch_necessary = TRUE;
958
959  _ISR_Enable( level );
960}
961
962/*PAGE
963 *
964 * _Thread_Set_priority
965 *
966 * This directive enables and disables several modes of
967 * execution for the requesting thread.
968 *
969 *  Input parameters:
970 *    the_thread   - pointer to thread priority
971 *    new_priority - new priority
972 *
973 *  Output: NONE
974 */
975
976void _Thread_Set_priority(
977  Thread_Control   *the_thread,
978  Priority_Control  new_priority
979)
980{
981  the_thread->current_priority = new_priority;
982  the_thread->ready            = &_Thread_Ready_chain[ new_priority ];
983
984  _Priority_Initialize_information( &the_thread->Priority_map, new_priority );
985}
986
987/*PAGE
988 *
989 *  _Thread_Change_mode
990 *
991 *  This routine enables and disables several modes of
992 *  execution for the requesting thread.
993 *
994 *  Input parameters:
995 *    mode         - new mode
996 *    mask         - mask
997 *    old_mode_set - address of previous mode
998 *
999 *  Output:
1000 *    *old_mode_set - previous mode
1001 *     returns TRUE if scheduling necessary
1002 *
1003 *  INTERRUPT LATENCY:
1004 *    only one case
1005 */
1006
1007boolean _Thread_Change_mode(
1008  Modes_Control  new_mode_set,
1009  Modes_Control  mask,
1010  Modes_Control *old_mode_set
1011)
1012{
1013  Modes_Control   changed;
1014  Modes_Control   threads_new_mode_set;
1015  Thread_Control *executing;
1016  boolean         need_dispatch;
1017
1018  executing     = _Thread_Executing;
1019  *old_mode_set = executing->current_modes;
1020
1021  _Modes_Change( executing->current_modes,
1022                   new_mode_set, mask, &threads_new_mode_set, &changed );
1023
1024  _Modes_Set_interrupt_level( threads_new_mode_set );
1025
1026  if ( _Modes_Mask_changed( changed, RTEMS_ASR_MASK ) )
1027    _ASR_Swap_signals( &executing->RTEMS_API->Signal );
1028
1029  executing->current_modes = threads_new_mode_set;
1030  need_dispatch = TRUE;
1031
1032  if ( !_States_Is_ready( executing->current_state ) ||
1033       ( !_Thread_Is_heir( executing ) &&
1034         _Modes_Is_preempt(threads_new_mode_set) ) )
1035
1036     _Context_Switch_necessary = TRUE;
1037
1038  else if ( !_ASR_Are_signals_pending( &executing->RTEMS_API->Signal ) )
1039
1040    need_dispatch = FALSE;
1041
1042  return need_dispatch;
1043}
1044
1045/*PAGE
1046 *
1047 *  _Thread_Get
1048 *
1049 *  NOTE:  If we are not using static inlines, this must be a real
1050 *         subroutine call.
1051 *
1052 *  NOTE:  XXX... This routine may be able to be optimized.
1053 */
1054
1055#ifndef USE_INLINES
1056
1057STATIC INLINE Thread_Control *_Thread_Get (
1058  Objects_Id           id,
1059  Objects_Locations   *location
1060)
1061{
1062  Objects_Classes      the_class;
1063  Objects_Information *information;
1064 
1065  if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ) {
1066    _Thread_Disable_dispatch();
1067    *location = OBJECTS_LOCAL;
1068    return( _Thread_Executing );
1069  }
1070 
1071  the_class = rtems_get_class( id );
1072 
1073  if ( the_class > OBJECTS_CLASSES_LAST ) {
1074    *location = OBJECTS_ERROR;
1075    return (Thread_Control *) 0;
1076  }
1077 
1078  information = _Objects_Information_table[ the_class ];
1079 
1080  if ( !information || !information->is_thread ) {
1081    *location = OBJECTS_ERROR;
1082    return (Thread_Control *) 0;
1083  }
1084 
1085  return (Thread_Control *) _Objects_Get( information, id, location );
1086}
1087#endif
Note: See TracBrowser for help on using the repository browser.