summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/threadhandler.c
blob: d3755f4466ef6a80793892c47a903bcb320c2b3d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
 *  Thread Handler
 *
 *
 *  COPYRIGHT (c) 1989-1999.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in found in the file LICENSE in this distribution or at
 *  http://www.OARcorp.com/rtems/license.html.
 *
 *  $Id$
 */

#include <rtems/system.h>
#include <rtems/score/apiext.h>
#include <rtems/score/context.h>
#include <rtems/score/interr.h>
#include <rtems/score/isr.h>
#include <rtems/score/object.h>
#include <rtems/score/priority.h>
#include <rtems/score/states.h>
#include <rtems/score/sysstate.h>
#include <rtems/score/thread.h>
#include <rtems/score/threadq.h>
#include <rtems/score/userext.h>
#include <rtems/score/wkspace.h>

/*PAGE
 *
 *  _Thread_Handler
 *
 *  This routine is the "primal" entry point for all threads.
 *  _Context_Initialize() dummies up the thread's initial context
 *  to cause the first Context_Switch() to jump to _Thread_Handler().
 *
 *  This routine is the default thread exitted error handler.  It is
 *  returned to when a thread exits.  The configured fatal error handler
 *  is invoked to process the exit.
 *
 *  NOTE:
 *
 *  On entry, it is assumed all interrupts are blocked and that this
 *  routine needs to set the initial isr level.  This may or may not 
 *  actually be needed by the context switch routine and as a result
 *  interrupts may already be at there proper level.  Either way,
 *  setting the initial isr level properly here is safe.
 *  
 *  Currently this is only really needed for the posix port,
 *  ref: _Context_Switch in unix/cpu.c
 *
 *  Input parameters:   NONE
 *
 *  Output parameters:  NONE
 */

void _Thread_Handler( void )
{
  ISR_Level  level;
  Thread_Control *executing;
#ifdef USE_INIT_FINI
  static char doneConstructors;
  char doneCons;
#endif
 
  executing = _Thread_Executing;
 
  /*
   * have to put level into a register for those cpu's that use
   * inline asm here
   */
 
  level = executing->Start.isr_level;
  _ISR_Set_level(level);

#ifdef USE_INIT_FINI
  doneCons = doneConstructors;
  doneConstructors = 1;
#endif

  /*
   * Take care that 'begin' extensions get to complete before
   * 'switch' extensions can run.  This means must keep dispatch
   * disabled until all 'begin' extensions complete.
   */
 
  _User_extensions_Thread_begin( executing );
 
  /*
   *  At this point, the dispatch disable level BETTER be 1.
   */

  _Thread_Enable_dispatch();
#ifdef USE_INIT_FINI
  if (!doneCons)
    _init ();
#endif
 
  switch ( executing->Start.prototype ) {
    case THREAD_START_NUMERIC:
      executing->Wait.return_argument = 
        (*(Thread_Entry_numeric) executing->Start.entry_point)(
          executing->Start.numeric_argument
      );
      break;
    case THREAD_START_POINTER:
      executing->Wait.return_argument =
        (*(Thread_Entry_pointer) executing->Start.entry_point)(
          executing->Start.pointer_argument
        );
      break;
    case THREAD_START_BOTH_POINTER_FIRST:
      executing->Wait.return_argument = 
         (*(Thread_Entry_both_pointer_first) executing->Start.entry_point)( 
           executing->Start.pointer_argument,
           executing->Start.numeric_argument
         );
      break;
    case THREAD_START_BOTH_NUMERIC_FIRST:
      executing->Wait.return_argument = 
         (*(Thread_Entry_both_numeric_first) executing->Start.entry_point)( 
           executing->Start.numeric_argument,
           executing->Start.pointer_argument
         );
      break;
  }

  /*
   *  In the switch above, the return code from the user thread body
   *  was placed in return_argument.  This assumed that if it returned
   *  anything (which is not supporting in all APIs), then it would be 
   *  able to fit in a (void *).
   */

  _User_extensions_Thread_exitted( executing );

  _Internal_error_Occurred(
    INTERNAL_ERROR_CORE,
    TRUE,
    INTERNAL_ERROR_THREAD_EXITTED
  );
}