source: rtems/c/src/exec/score/src/thread.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: 24.4 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/core/context.h>
18#include <rtems/core/interr.h>
19#include <rtems/core/intthrd.h>
20#include <rtems/core/isr.h>
21#include <rtems/core/object.h>
22#include <rtems/core/priority.h>
23#include <rtems/core/states.h>
24#include <rtems/core/thread.h>
25#include <rtems/core/threadq.h>
26#include <rtems/core/userext.h>
27#include <rtems/core/wkspace.h>
28
29/*PAGE
30 *
31 *  _Thread_Handler_initialization
32 *
33 *  This routine initializes all thread manager related data structures.
34 *
35 *  Input parameters:
36 *    ticks_per_timeslice - clock ticks per quantum
37 *    maximum_proxies     - number of proxies to initialize
38 *
39 *  Output parameters:  NONE
40 */
41
42void _Thread_Handler_initialization(
43  unsigned32   ticks_per_timeslice,
44  unsigned32   maximum_extensions,
45  unsigned32   maximum_proxies
46)
47{
48  unsigned32 index;
49
50  _Context_Switch_necessary = FALSE;
51  _Thread_Executing         = NULL;
52  _Thread_Heir              = NULL;
53  _Thread_Allocated_fp      = NULL;
54
55  _Thread_Maximum_extensions = maximum_extensions;
56
57  _Thread_Ticks_remaining_in_timeslice = ticks_per_timeslice;
58  _Thread_Ticks_per_timeslice          = ticks_per_timeslice;
59
60  _Thread_Ready_chain = _Workspace_Allocate_or_fatal_error(
61    (PRIORITY_MAXIMUM + 1) * sizeof(Chain_Control)
62  );
63
64  for ( index=0; index <= PRIORITY_MAXIMUM ; index++ )
65    _Chain_Initialize_empty( &_Thread_Ready_chain[ index ] );
66
67  _Thread_MP_Handler_initialization( maximum_proxies );
68}
69
70/*PAGE
71 *
72 *  _Thread_Start_multitasking
73 *
74 *  This kernel routine readies the requested thread, the thread chain
75 *  is adjusted.  A new heir thread may be selected.
76 *
77 *  Input parameters:
78 *    system_thread - pointer to system initialization thread control block
79 *    idle_thread   - pointer to idle thread control block
80 *
81 *  Output parameters:  NONE
82 *
83 *  NOTE:  This routine uses the "blocking" heir selection mechanism.
84 *         This insures the correct heir after a thread restart.
85 *
86 *  INTERRUPT LATENCY:
87 *    ready chain
88 *    select heir
89 */
90
91void _Thread_Start_multitasking(
92  Thread_Control *system_thread,
93  Thread_Control *idle_thread
94)
95{
96
97   _Thread_Executing  =
98   _Thread_Heir       =
99   _Thread_MP_Receive = system_thread;
100
101   /*
102    *  Scheduling will not work "correctly" until the above
103    *  statements have been executed.
104    */
105
106   _Thread_Ready( system_thread );
107   _Thread_Ready( idle_thread );
108
109   _Context_Switch_necessary = FALSE;
110
111   _Context_Switch( &_Thread_BSP_context, &system_thread->Registers );
112
113}
114
115/*PAGE
116 *
117 *  _Thread_Dispatch
118 *
119 *  This kernel routine determines if a dispatch is needed, and if so
120 *  dispatches to the heir thread.  Once the heir is running an attempt
121 *  is made to dispatch any ASRs.
122 *
123 *  ALTERNATE ENTRY POINTS:
124 *    void _Thread_Enable_dispatch();
125 *
126 *  Input parameters:  NONE
127 *
128 *  Output parameters:  NONE
129 *
130 *  INTERRUPT LATENCY:
131 *    dispatch thread
132 *    no dispatch thread
133 */
134
135#if ( CPU_INLINE_ENABLE_DISPATCH == FALSE )
136void _Thread_Enable_dispatch( void )
137{
138  if ( --_Thread_Dispatch_disable_level )
139    return;
140  _Thread_Dispatch();
141}
142#endif
143
144void _Thread_Dispatch( void )
145{
146  Thread_Control   *executing;
147  Thread_Control   *heir;
148  ISR_Level         level;
149
150  executing   = _Thread_Executing;
151  _ISR_Disable( level );
152  while ( _Context_Switch_necessary == TRUE ) {
153    heir = _Thread_Heir;
154    _Thread_Dispatch_disable_level = 1;
155    _Context_Switch_necessary = FALSE;
156    _Thread_Executing = heir;
157    _ISR_Enable( level );
158
159    _User_extensions_Thread_switch( executing, heir );
160
161    _Thread_Ticks_remaining_in_timeslice = _Thread_Ticks_per_timeslice;
162
163    /*
164     *  If the CPU has hardware floating point, then we must address saving
165     *  and restoring it as part of the context switch.
166     *
167     *  The second conditional compilation section selects the algorithm used
168     *  to context switch between floating point tasks.  The deferred algorithm
169     *  can be significantly better in a system with few floating point tasks
170     *  because it reduces the total number of save and restore FP context
171     *  operations.  However, this algorithm can not be used on all CPUs due
172     *  to unpredictable use of FP registers by some compilers for integer
173     *  operations.
174     */
175
176#if ( CPU_HARDWARE_FP == TRUE )
177#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
178    if ( (heir->fp_context != NULL) && !_Thread_Is_allocated_fp( heir ) ) {
179      if ( _Thread_Allocated_fp != NULL )
180        _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
181      _Context_Restore_fp( &heir->fp_context );
182      _Thread_Allocated_fp = heir;
183    }
184#else
185    if ( executing->fp_context != NULL )
186      _Context_Save_fp( &executing->fp_context );
187
188    if ( heir->fp_context != NULL )
189      _Context_Restore_fp( &heir->fp_context );
190#endif
191#endif
192
193    _Context_Switch( &executing->Registers, &heir->Registers );
194
195    executing = _Thread_Executing;
196
197    _ISR_Disable( level );
198  }
199
200  _Thread_Dispatch_disable_level = 0;
201
202  _ISR_Enable( level );
203
204  _User_extensions_Thread_post_switch( executing );
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  (void) _Workspace_Free( the_thread->Start.fp_context );
468
469  if ( the_thread->Start.stack )
470    (void) _Workspace_Free( the_thread->Start.stack );
471
472  if ( the_thread->extensions )
473    (void) _Workspace_Free( the_thread->extensions );
474}
475
476/*PAGE
477 *
478 *  _Thread_Ready
479 *
480 *  This kernel routine readies the requested thread, the thread chain
481 *  is adjusted.  A new heir thread may be selected.
482 *
483 *  Input parameters:
484 *    the_thread - pointer to thread control block
485 *
486 *  Output parameters:  NONE
487 *
488 *  NOTE:  This routine uses the "blocking" heir selection mechanism.
489 *         This insures the correct heir after a thread restart.
490 *
491 *  INTERRUPT LATENCY:
492 *    ready chain
493 *    select heir
494 */
495
496void _Thread_Ready(
497  Thread_Control *the_thread
498)
499{
500  ISR_Level              level;
501  Thread_Control *heir;
502
503  _ISR_Disable( level );
504
505  the_thread->current_state = STATES_READY;
506
507  _Priority_Add_to_bit_map( &the_thread->Priority_map );
508
509  _Chain_Append_unprotected( the_thread->ready, &the_thread->Object.Node );
510
511  _ISR_Flash( level );
512
513  _Thread_Calculate_heir();
514
515  heir = _Thread_Heir;
516
517  if ( !_Thread_Is_executing( heir ) && _Thread_Executing->is_preemptible )
518    _Context_Switch_necessary = TRUE;
519
520  _ISR_Enable( level );
521}
522
523/*PAGE
524 *
525 *  _Thread_Clear_state
526 *
527 *  This kernel routine clears the appropriate states in the
528 *  requested thread.  The thread ready chain is adjusted if
529 *  necessary and the Heir thread is set accordingly.
530 *
531 *  Input parameters:
532 *    the_thread - pointer to thread control block
533 *    state      - state set to clear
534 *
535 *  Output parameters:  NONE
536 *
537 *  INTERRUPT LATENCY:
538 *    priority map
539 *    select heir
540 */
541
542void _Thread_Clear_state(
543  Thread_Control *the_thread,
544  States_Control  state
545)
546{
547  ISR_Level level;
548
549  _ISR_Disable( level );
550    the_thread->current_state =
551      _States_Clear( state, the_thread->current_state );
552
553    if ( _States_Is_ready( the_thread->current_state ) ) {
554
555      _Priority_Add_to_bit_map( &the_thread->Priority_map );
556
557      _Chain_Append_unprotected( the_thread->ready, &the_thread->Object.Node );
558
559      _ISR_Flash( level );
560
561      if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
562        _Thread_Heir = the_thread;
563        if ( _Thread_Executing->is_preemptible ||
564             the_thread->current_priority == 0 )
565          _Context_Switch_necessary = TRUE;
566      }
567    }
568  _ISR_Enable( level );
569}
570
571/*PAGE
572 *
573 * _Thread_Set_state
574 *
575 * This kernel routine sets the requested state in the THREAD.  The
576 * THREAD chain is adjusted if necessary.
577 *
578 * Input parameters:
579 *   the_thread   - pointer to thread control block
580 *   state - state to be set
581 *
582 * Output parameters:  NONE
583 *
584 *  INTERRUPT LATENCY:
585 *    ready chain
586 *    select map
587 */
588
589void _Thread_Set_state(
590  Thread_Control *the_thread,
591  States_Control         state
592)
593{
594  ISR_Level             level;
595  Chain_Control *ready;
596
597  ready = the_thread->ready;
598  _ISR_Disable( level );
599  if ( !_States_Is_ready( the_thread->current_state ) ) {
600    the_thread->current_state =
601       _States_Set( state, the_thread->current_state );
602    _ISR_Enable( level );
603    return;
604  }
605
606  the_thread->current_state = state;
607
608  if ( _Chain_Has_only_one_node( ready ) ) {
609
610    _Chain_Initialize_empty( ready );
611    _Priority_Remove_from_bit_map( &the_thread->Priority_map );
612
613  } else
614    _Chain_Extract_unprotected( &the_thread->Object.Node );
615
616  _ISR_Flash( level );
617
618  if ( _Thread_Is_heir( the_thread ) )
619     _Thread_Calculate_heir();
620
621  if ( _Thread_Is_executing( the_thread ) )
622    _Context_Switch_necessary = TRUE;
623
624  _ISR_Enable( level );
625}
626
627/*PAGE
628 *
629 *  _Thread_Set_transient
630 *
631 *  This kernel routine places the requested thread in the transient state
632 *  which will remove it from the ready queue, if necessary.  No
633 *  rescheduling is necessary because it is assumed that the transient
634 *  state will be cleared before dispatching is enabled.
635 *
636 *  Input parameters:
637 *    the_thread - pointer to thread control block
638 *
639 *  Output parameters:  NONE
640 *
641 *  INTERRUPT LATENCY:
642 *    only case
643 */
644
645void _Thread_Set_transient(
646  Thread_Control *the_thread
647)
648{
649  ISR_Level             level;
650  unsigned32            old_state;
651  Chain_Control *ready;
652
653  ready = the_thread->ready;
654  _ISR_Disable( level );
655
656  old_state = the_thread->current_state;
657  the_thread->current_state = _States_Set( STATES_TRANSIENT, old_state );
658
659  if ( _States_Is_ready( old_state ) ) {
660    if ( _Chain_Has_only_one_node( ready ) ) {
661
662      _Chain_Initialize_empty( ready );
663      _Priority_Remove_from_bit_map( &the_thread->Priority_map );
664
665    } else
666      _Chain_Extract_unprotected( &the_thread->Object.Node );
667  }
668
669  _ISR_Enable( level );
670
671}
672
673/*PAGE
674 *
675 *  _Thread_Reset_timeslice
676 *
677 *  This routine will remove the running thread from the ready chain
678 *  and place it immediately at the rear of this chain and then the
679 *  timeslice counter is reset.  The heir THREAD will be updated if
680 *  the running is also the currently the heir.
681 *
682 *  Input parameters:   NONE
683 *
684 *  Output parameters:  NONE
685 *
686 *  INTERRUPT LATENCY:
687 *    ready chain
688 *    select heir
689 */
690
691void _Thread_Reset_timeslice( void )
692{
693  ISR_Level              level;
694  Thread_Control *executing;
695  Chain_Control  *ready;
696
697  executing = _Thread_Executing;
698  ready     = executing->ready;
699  _ISR_Disable( level );
700    if ( _Chain_Has_only_one_node( ready ) ) {
701      _Thread_Ticks_remaining_in_timeslice = _Thread_Ticks_per_timeslice;
702      _ISR_Enable( level );
703      return;
704    }
705    _Chain_Extract_unprotected( &executing->Object.Node );
706    _Chain_Append_unprotected( ready, &executing->Object.Node );
707
708  _ISR_Flash( level );
709
710    if ( _Thread_Is_heir( executing ) )
711      _Thread_Heir = (Thread_Control *) ready->first;
712
713    _Context_Switch_necessary = TRUE;
714
715  _ISR_Enable( level );
716}
717
718/*PAGE
719 *
720 *  _Thread_Tickle_timeslice
721 *
722 *  This scheduler routine determines if timeslicing is enabled
723 *  for the currently executing thread and, if so, updates the
724 *  timeslice count and checks for timeslice expiration.
725 *
726 *  Input parameters:   NONE
727 *
728 *  Output parameters:  NONE
729 */
730
731void _Thread_Tickle_timeslice( void )
732{
733  if ( !_Thread_Executing->is_timeslice  ||
734       !_Thread_Executing->is_preemptible ||
735       !_States_Is_ready( _Thread_Executing->current_state ) )
736    return;
737
738  if ( --_Thread_Ticks_remaining_in_timeslice == 0 ) {
739      _Thread_Reset_timeslice();
740  }
741}
742
743/*PAGE
744 *
745 *  _Thread_Yield_processor
746 *
747 *  This kernel routine will remove the running THREAD from the ready chain
748 *  and place it immediatly at the rear of this chain.  Reset timeslice
749 *  and yield the processor functions both use this routine, therefore if
750 *  reset is TRUE and this is the only thread on the chain then the
751 *  timeslice counter is reset.  The heir THREAD will be updated if the
752 *  running is also the currently the heir.
753 *
754 *  Input parameters:   NONE
755 *
756 *  Output parameters:  NONE
757 *
758 *  INTERRUPT LATENCY:
759 *    ready chain
760 *    select heir
761 */
762
763void _Thread_Yield_processor( void )
764{
765  ISR_Level       level;
766  Thread_Control *executing;
767  Chain_Control  *ready;
768
769  executing = _Thread_Executing;
770  ready     = executing->ready;
771  _ISR_Disable( level );
772    if ( !_Chain_Has_only_one_node( ready ) ) {
773      _Chain_Extract_unprotected( &executing->Object.Node );
774      _Chain_Append_unprotected( ready, &executing->Object.Node );
775
776      _ISR_Flash( level );
777
778      if ( _Thread_Is_heir( executing ) )
779        _Thread_Heir = (Thread_Control *) ready->first;
780      _Context_Switch_necessary = TRUE;
781    }
782    else if ( !_Thread_Is_heir( executing ) )
783      _Context_Switch_necessary = TRUE;
784
785  _ISR_Enable( level );
786}
787
788/*PAGE
789 *
790 *  _Thread_Load_environment
791 *
792 *  Load starting environment for another thread from its start area in the
793 *  thread.  Only called from t_restart and t_start.
794 *
795 *  Input parameters:
796 *    the_thread - thread control block pointer
797 *
798 *  Output parameters:  NONE
799 */
800
801void _Thread_Load_environment(
802  Thread_Control *the_thread
803)
804{
805  if ( the_thread->Start.fp_context ) {
806    the_thread->fp_context = the_thread->Start.fp_context;
807    _Context_Initialize_fp( &the_thread->fp_context );
808  }
809
810  the_thread->is_preemptible = the_thread->Start.is_preemptible;
811  the_thread->is_timeslice   = the_thread->Start.is_timeslice;
812
813  _Context_Initialize(
814    &the_thread->Registers,
815    the_thread->Start.Initial_stack.area,
816    the_thread->Start.Initial_stack.size,
817    the_thread->Start.isr_level,
818    _Thread_Handler
819  );
820
821}
822
823/*PAGE
824 *
825 *  _Thread_Handler
826 *
827 *  This routine is the default thread exitted error handler.  It is
828 *  returned to when a thread exits.  The configured fatal error handler
829 *  is invoked to process the exit.
830 *
831 *  Input parameters:   NONE
832 *
833 *  Output parameters:  NONE
834 */
835
836void _Thread_Handler( void )
837{
838  Thread_Control *executing;
839
840  executing = _Thread_Executing;
841
842  /*
843   * Take care that 'begin' extensions get to complete before
844   * 'switch' extensions can run.  This means must keep dispatch
845   * disabled until all 'begin' extensions complete.
846   */
847 
848  _User_extensions_Thread_begin( executing );
849 
850  /*
851   *  At this point, the dispatch disable level BETTER be 1.
852   */
853
854  _Thread_Enable_dispatch();
855 
856  switch ( executing->Start.prototype ) {
857    case THREAD_START_NUMERIC:
858      (*executing->Start.entry_point)( executing->Start.numeric_argument );
859      break;
860    case THREAD_START_POINTER:
861      (*executing->Start.entry_point)( executing->Start.pointer_argument );
862      break;
863    case THREAD_START_BOTH_POINTER_FIRST:
864      (*executing->Start.entry_point)(
865        executing->Start.pointer_argument,
866        executing->Start.numeric_argument
867      );
868      break;
869    case THREAD_START_BOTH_NUMERIC_FIRST:
870      (*executing->Start.entry_point)(
871        executing->Start.numeric_argument,
872        executing->Start.pointer_argument
873      );
874      break;
875  }
876
877  _User_extensions_Thread_exitted( executing );
878
879  _Internal_error_Occurred(
880    INTERNAL_ERROR_CORE,
881    TRUE,
882    INTERNAL_ERROR_THREAD_EXITTED
883  );
884}
885
886/*PAGE
887 *
888 *  _Thread_Delay_ended
889 *
890 *  This routine processes a thread whose delay period has ended.
891 *  It is called by the watchdog handler.
892 *
893 *  Input parameters:
894 *    id - thread id
895 *
896 *  Output parameters: NONE
897 */
898
899void _Thread_Delay_ended(
900  Objects_Id  id,
901  void       *ignored
902)
903{
904  Thread_Control    *the_thread;
905  Objects_Locations  location;
906
907  the_thread = _Thread_Get( id, &location );
908  switch ( location ) {
909    case OBJECTS_ERROR:
910    case OBJECTS_REMOTE:  /* impossible */
911      break;
912    case OBJECTS_LOCAL:
913      _Thread_Unblock( the_thread );
914      _Thread_Unnest_dispatch();
915      break;
916  }
917}
918
919/*PAGE
920 *
921 *  _Thread_Change_priority
922 *
923 *  This kernel routine changes the priority of the thread.  The
924 *  thread chain is adjusted if necessary.
925 *
926 *  Input parameters:
927 *    the_thread   - pointer to thread control block
928 *    new_priority - ultimate priority
929 *
930 *  Output parameters:  NONE
931 *
932 *  INTERRUPT LATENCY:
933 *    ready chain
934 *    select heir
935 */
936
937void _Thread_Change_priority(
938  Thread_Control   *the_thread,
939  Priority_Control  new_priority
940)
941{
942  ISR_Level level;
943
944  _Thread_Set_transient( the_thread );
945
946  if ( the_thread->current_priority != new_priority )
947    _Thread_Set_priority( the_thread, new_priority );
948
949  _ISR_Disable( level );
950
951  the_thread->current_state =
952    _States_Clear( STATES_TRANSIENT, the_thread->current_state );
953
954  if ( ! _States_Is_ready( the_thread->current_state ) ) {
955    _ISR_Enable( level );
956    return;
957  }
958
959  _Priority_Add_to_bit_map( &the_thread->Priority_map );
960  _Chain_Append_unprotected( the_thread->ready, &the_thread->Object.Node );
961
962  _ISR_Flash( level );
963
964  _Thread_Calculate_heir();
965
966  if ( !_Thread_Is_executing_also_the_heir() &&
967       _Thread_Executing->is_preemptible )
968    _Context_Switch_necessary = TRUE;
969
970  _ISR_Enable( level );
971}
972
973/*PAGE
974 *
975 * _Thread_Set_priority
976 *
977 * This directive enables and disables several modes of
978 * execution for the requesting thread.
979 *
980 *  Input parameters:
981 *    the_thread   - pointer to thread priority
982 *    new_priority - new priority
983 *
984 *  Output: NONE
985 */
986
987void _Thread_Set_priority(
988  Thread_Control   *the_thread,
989  Priority_Control  new_priority
990)
991{
992  the_thread->current_priority = new_priority;
993  the_thread->ready            = &_Thread_Ready_chain[ new_priority ];
994
995  _Priority_Initialize_information( &the_thread->Priority_map, new_priority );
996}
997
998/*PAGE
999 *
1000 *  _Thread_Evaluate_mode
1001 *
1002 *  XXX
1003 */
1004
1005boolean _Thread_Evaluate_mode( void )
1006{
1007  Thread_Control     *executing;
1008
1009  executing = _Thread_Executing;
1010
1011  if ( !_States_Is_ready( executing->current_state ) ||
1012       ( !_Thread_Is_heir( executing ) && executing->is_preemptible ) ) {
1013    _Context_Switch_necessary = TRUE;
1014    return TRUE;
1015  }
1016
1017  return FALSE;
1018}
1019
1020/*PAGE
1021 *
1022 *  _Thread_Get
1023 *
1024 *  NOTE:  If we are not using static inlines, this must be a real
1025 *         subroutine call.
1026 *
1027 *  NOTE:  XXX... This routine may be able to be optimized.
1028 */
1029
1030#ifndef USE_INLINES
1031
1032STATIC INLINE Thread_Control *_Thread_Get (
1033  Objects_Id           id,
1034  Objects_Locations   *location
1035)
1036{
1037  Objects_Classes      the_class;
1038  Objects_Information *information;
1039 
1040  if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ) {
1041    _Thread_Disable_dispatch();
1042    *location = OBJECTS_LOCAL;
1043    return( _Thread_Executing );
1044  }
1045 
1046  the_class = _Objects_Get_class( id );
1047 
1048  if ( the_class > OBJECTS_CLASSES_LAST ) {
1049    *location = OBJECTS_ERROR;
1050    return (Thread_Control *) 0;
1051  }
1052 
1053  information = _Objects_Information_table[ the_class ];
1054 
1055  if ( !information || !information->is_thread ) {
1056    *location = OBJECTS_ERROR;
1057    return (Thread_Control *) 0;
1058  }
1059 
1060  return (Thread_Control *) _Objects_Get( information, id, location );
1061}
1062#endif
Note: See TracBrowser for help on using the repository browser.