source: rtems/c/src/exec/score/src/thread.c @ 744d2878

4.104.114.84.95
Last change on this file since 744d2878 was 744d2878, checked in by Joel Sherrill <joel.sherrill@…>, on 02/14/96 at 18:48:39

removed arguments from _Thread_Start_multitasking

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