source: rtems/doc/porting/taskcontext.t @ 0765f9b

4.104.114.84.95
Last change on this file since 0765f9b was 0660b4f8, checked in by Joel Sherrill <joel.sherrill@…>, on 11/16/99 at 19:50:56

Changed copyright date to 1999.

  • Property mode set to 100644
File size: 19.2 KB
Line 
1@c
2@c  COPYRIGHT (c) 1988-1999.
3@c  On-Line Applications Research Corporation (OAR).
4@c  All rights reserved.
5@c
6@c  $Id$
7@c
8
9@chapter Task Context Management
10
11@section Introduction
12
13XXX
14
15@section Task Stacks
16
17XXX
18
19@subsection Direction of Stack Growth
20
21The CPU_STACK_GROWS_UP macro is set based upon the answer to the following
22question: Does the stack grow up (toward higher addresses) or down (toward
23lower addresses)?  If the stack grows upward in memory, then this macro
24should be set to TRUE.  Otherwise, it should be set to FALSE to indicate
25that the stack grows downward toward smaller addresses.
26
27The following illustrates how the CPU_STACK_GROWS_UP macro is set:
28
29@example
30#define CPU_STACK_GROWS_UP               TRUE
31@end example
32
33@subsection Minimum Task Stack Size
34
35The CPU_STACK_MINIMUM_SIZE macro should be set to the minimum size of each
36task stack.  This size is specified as the number of bytes.  This minimum
37stack size should be large enough to run all RTEMS tests.  The minimum
38stack size is chosen such that a "reasonable" small application should not
39have any problems.  Choosing a minimum stack size that is too small will
40result in the RTEMS tests "blowing" their stack and not executing
41properly.
42
43There are many reasons a task could require a stack size larger than the
44minimum.  For example, a task could have a very deep call path or declare
45large data structures on the stack.  Tasks which utilize C++ exceptions
46tend to require larger stacks as do Ada tasks.
47
48The following illustrates setting the minimum stack size to 4 kilobytes
49per task.
50
51@example
52#define CPU_STACK_MINIMUM_SIZE          (1024*4)
53@end example
54
55@subsection Stack Alignment Requirements
56
57The CPU_STACK_ALIGNMENT macro is set to indicate the byte alignment
58requirement for the stack.  This alignment requirement may be stricter
59than that for the data types alignment specified by CPU_ALIGNMENT.  If the
60CPU_ALIGNMENT is strict enough for the stack, then this should be set to
610.
62
63The following illustrates how the CPU_STACK_ALIGNMENT macro should be set
64when there are no special requirements:
65
66@example
67#define CPU_STACK_ALIGNMENT        0
68@end example
69
70NOTE:  This must be a power of 2 either 0 or greater than CPU_ALIGNMENT. [XXX is this true?]
71
72@section Task Context
73
74Associated with each task is a context that distinguishes it from other
75tasks in the system and logically gives it its own scratch pad area for
76computations.  In addition, when an interrupt occurs some processor
77context information must be saved and restored.  This is managed in RTEMS
78as three items:
79
80@itemize @bullet
81
82@item Basic task level context (e.g. the Context_Control structure)
83
84@item Floating point task context (e.g. Context_Control_fp structure)
85
86@item Interrupt level context (e.g.  the Context_Control_interrupt
87structure)
88
89@end itemize
90
91The integer and floating point context structures and the routines that
92manipulate them are discussed in detail in this section, while the
93interrupt level context structure is discussed in the XXX.
94
95Additionally, if the GNU debugger gdb is to be made aware of RTEMS tasks
96for this CPU, then care should be used in designing the context area.
97
98@example
99typedef struct @{
100    unsigned32 special_interrupt_register;
101@} CPU_Interrupt_frame;
102@end example
103
104
105@subsection Basic Context Data Structure
106
107The Context_Control data structure contains the basic integer context of a
108task.  In addition, this context area contains stack and frame pointers,
109processor status register(s), and any other registers that are normally
110altered by compiler generated code.  In addition, this context must
111contain the processor interrupt level since the processor interrupt level
112is maintained on a per-task basis.  This is necessary to support the
113interrupt level portion of the task mode as provided by the Classic RTEMS
114API.
115
116On some processors, it is cost-effective to save only the callee preserved
117registers during a task context switch.  This means that the ISR code
118needs to save those registers which do not persist across function calls. 
119It is not mandatory to make this distinctions between the caller/callee
120saves registers for the purpose of minimizing context saved during task
121switch and on interrupts.  If the cost of saving extra registers is
122minimal, simplicity is the choice.  Save the same context on interrupt
123entry as for tasks in this case.
124
125The Context_Control data structure should be defined such that the order
126of elements results in the simplest, most efficient implementation of XXX. 
127A typical implementation starts with a definition such as the following:
128
129@example
130typedef struct @{
131    unsigned32 some_integer_register;
132    unsigned32 another_integer_register;
133    unsigned32 some_system_register;
134@} Context_Control;
135@end example
136
137@subsection Initializing a Context
138
139The _CPU_Context_Initialize routine initializes the context to a state
140suitable for starting a task after a context restore operation. 
141Generally, this involves:
142
143@itemize @bullet
144
145@item  setting a starting address,
146
147@item  preparing the stack,
148
149@item  preparing the stack and frame pointers,
150
151@item  setting the proper interrupt level in the context, and
152
153@item  initializing the floating point context
154
155@end itemize
156
157This routine generally does not set any unnecessary register in the
158context.  The state of the "general data" registers is undefined at task
159start time. The _CPU_Context_initialize routine is prototyped as follows:
160
161@example
162void _CPU_Context_Initialize(
163    Context_Control *_the_context,
164    void            *_stack_base,
165    unsigned32       _size,
166    unsigned32       _isr,
167    void            *_entry_point,
168    unsigned32       _is_fp
169);
170@end example
171
172This is_fp parameter is TRUE if the thread is to be a floating point
173thread.  This is typically only used on CPUs where the FPU may be easily
174disabled by software such as on the SPARC where the PSR contains an enable
175FPU bit.  The use of an FPU enable bit allows RTEMS to ensure that a
176non-floating point task is unable to access the FPU.  This guarantees that
177a deferred floating point context switch is safe.
178
179XXX explain other parameters and check prototype
180
181@subsection Performing a Context Switch
182
183The _CPU_Context_switch performs a normal non-FP context switch from the
184context of the current executing thread to the context of the heir thread.
185
186@example
187void _CPU_Context_switch(
188  Context_Control  *run,
189  Context_Control  *heir
190);
191@end example
192
193@subsection Restoring a Context
194
195The _CPU_Context_restore routine is generally used only to restart the
196currently executing thread (i.e. self) in an efficient manner.  In many
197ports, it can simply be a label in _CPU_Context_switch. It may be
198unnecessary to reload some registers.
199
200@example
201void _CPU_Context_restore(
202  Context_Control *new_context
203);
204@end example
205
206@subsection Restarting the Currently Executing Task
207
208The _CPU_Context_Restart_self is responsible for somehow restarting the
209currently executing task.  If you are lucky when porting RTEMS, then all
210that is necessary is restoring the context.  Otherwise, there will need to
211be a routine that does something special in this case.  Performing a
212_CPU_Context_Restore on the currently executing task after reinitializing
213that context should work on most ports.  It will not work if restarting
214self conflicts with the stack frame assumptions of restoring a context.
215
216The following is an implementation of _CPU_Context_Restart_self that can
217be used when no special handling is required for this case.
218
219@example
220#define _CPU_Context_Restart_self( _the_context ) \
221   _CPU_Context_restore( (_the_context) )
222@end example
223
224XXX find a port which does not do it this way and include it here
225
226@section Floating Point Context
227
228@subsection CPU_HAS_FPU Macro Definition
229
230The CPU_HAS_FPU macro is set based on the answer to the question: Does the
231CPU have hardware floating point?  If the CPU has an FPU, then this should
232be set to TRUE.  Otherwise, it should be set to FALSE.  The primary
233implication of setting this macro to TRUE is that it indicates that tasks
234may have floating point contexts.  In the Classic API, this means that the
235RTEMS_FLOATING_POINT task attribute specified as part of rtems_task_create
236is supported on this CPU.  If CPU_HAS_FPU is set to FALSE, then no tasks
237or threads may be floating point and the RTEMS_FLOATING_POINT task
238attribute is ignored.  On an API such as POSIX where all threads
239implicitly have a floating point context, then the setting of this macro
240determines whether every POSIX thread has a floating point context.
241
242The following example illustrates how the CPU_HARDWARE_FP (XXX macro name
243is varying) macro is set based on the CPU family dependent macro.
244
245@example
246#if ( THIS_CPU_FAMILY_HAS_FPU == 1 ) /* where THIS_CPU_FAMILY */
247                                     /* might be M68K */
248#define CPU_HARDWARE_FP     TRUE
249#else
250#define CPU_HARDWARE_FP     FALSE
251#endif
252@end example
253
254The macro name THIS_CPU_FAMILY_HAS_FPU should be made CPU specific.  It
255indicates whether or not this CPU model has FP support.  For example, the
256definition of the i386ex and i386sx CPU models would set I386_HAS_FPU to
257FALSE to indicate that these CPU models are i386's without an i387 and
258wish to leave floating point support out of RTEMS when built for the
259i386_nofp processor model.  On a CPU with a built-in FPU like the i486,
260this would be defined as TRUE.
261
262On some processor families, the setting of the THIS_CPU_FAMILY_HAS_FPU
263macro may be derived from compiler predefinitions.  This can be used when
264the compiler distinguishes the individual CPU models for this CPU family
265as distinctly as RTEMS requires.  Often RTEMS needs to need more about the
266CPU model than the compiler because of differences at the system level
267such as caching, interrupt structure.
268
269@subsection CPU_ALL_TASKS_ARE_FP Macro Setting
270
271The CPU_ALL_TASKS_ARE_FP macro is set to TRUE or FALSE based upon the
272answer to the following question: Are all tasks RTEMS_FLOATING_POINT tasks
273implicitly?  If this macro is set TRUE, then all tasks and threads are
274assumed to have a floating point context.  In the Classic API, this is
275equivalent to setting the RTEMS_FLOATING_POINT task attribute on all
276rtems_task_create calls.  If the CPU_ALL_TASKS_ARE_FP macro is set to
277FALSE, then the RTEMS_FLOATING_POINT task attribute in the Classic API is
278honored.
279
280The rationale for this macro is that if a function that an application
281developer would not think utilize the FP unit DOES, then one can not
282easily predict which tasks will use the FP hardware. In this case, this
283option should be TRUE.  So far, the only CPU families for which this macro
284has been to TRUE are the HP PA-RISC and PowerPC.  For the HP PA-RISC, the
285HP C compiler and gcc both implicitly use the floating point registers to
286perform integer multiplies.  For the PowerPC, this feature macro is set to
287TRUE because the printf routine saves a floating point register whether or
288not a floating point number is actually printed.  If the newlib
289implementation of printf were restructured to avoid this, then the PowerPC
290port would not have to have this option set to TRUE.
291
292The following example illustrates how the CPU_ALL_TASKS_ARE_FP is set on
293the PowerPC.  On this CPU family, this macro is set to TRUE if the CPU
294model has hardware floating point.
295
296@example
297#if (CPU_HARDWARE_FP == TRUE)
298#define CPU_ALL_TASKS_ARE_FP     TRUE
299#else
300#define CPU_ALL_TASKS_ARE_FP     FALSE
301#endif
302@end example
303
304NOTE: If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
305
306@subsection CPU_USE_DEFERRED_FP_SWITCH Macro Setting
307
308The CPU_USE_DEFERRED_FP_SWITCH macro is set based upon the answer to the
309following question:  Should the saving of the floating point registers be
310deferred until a context switch is made to another different floating
311point task?  If the floating point context will not be stored until
312necessary, then this macro should be set to TRUE.  When set to TRUE, the
313floating point context of a task will remain in the floating point
314registers and not disturbed until another floating point task is switched
315to.
316
317If the CPU_USE_DEFERRED_FP_SWITCH is set to FALSE, then the floating point
318context is saved each time a floating point task is switched out and
319restored when the next floating point task is restored.  The state of the
320floating point registers between those two operations is not specified.
321
322There are a couple of known cases where the port should not defer saving
323the floating point context.  The first case is when the compiler generates
324instructions that use the FPU when floating point is not actually used. 
325This occurs on the HP PA-RISC for example when an integer multiply is
326performed.  On the PowerPC, the printf routine includes a save of a
327floating point register to support printing floating point numbers even if
328the path that actually prints the floating point number is not invoked. 
329In both of these cases, deferred floating point context switches can not
330be used.  If the floating point context has to be saved as part of
331interrupt dispatching, then it may also be necessary to disable deferred
332context switches.
333
334Setting this flag to TRUE results in using a different algorithm for
335deciding when to save and restore the floating point context.  The
336deferred FP switch algorithm minimizes the number of times the FP context
337is saved and restored.  The FP context is not saved until a context switch
338is made to another, different FP task.  Thus in a system with only one FP
339task, the FP context will never be saved or restored.
340
341The following illustrates setting the CPU_USE_DEFERRED_FP_SWITCH macro on
342a processor family such as the M68K or i386 which can use deferred
343floating point context switches.
344
345@example
346#define CPU_USE_DEFERRED_FP_SWITCH       TRUE
347@end example
348
349@subsection Floating Point Context Data Structure
350
351The Context_Control_fp contains the per task information for the floating
352point unit.  The organization of this structure may be a list of floating
353point registers along with any floating point control and status registers
354or it simply consist of an array of a fixed number of bytes.  Defining the
355floating point context area as an array of bytes is done when the floating
356point context is dumped by a "FP save context" type instruction and the
357format is either not completely defined by the CPU documentation or the
358format is not critical for the implementation of the floating point
359context switch routines.  In this case, there is no need to figure out the
360exact format -- only the size.  Of course, although this is enough
361information for RTEMS, it is probably not enough for a debugger such as
362gdb.  But that is another problem.
363
364@example
365typedef struct @{
366    double      some_float_register;
367@} Context_Control_fp;
368@end example
369
370
371On some CPUs with hardware floating point support, the Context_Control_fp
372structure will not be used.
373
374@subsection Size of Floating Point Context Macro
375
376The CPU_CONTEXT_FP_SIZE macro is set to the size of the floating point
377context area. On some CPUs this will not be a "sizeof" because the format
378of the floating point area is not defined -- only the size is.  This is
379usually on CPUs with a "floating point save context" instruction.  In
380general, though it is easier to define the structure as a "sizeof"
381operation and define the Context_Control_fp structure to be an area of
382bytes of the required size in this case.
383
384@example
385#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
386@end example
387
388@subsection Start of Floating Point Context Area Macro
389
390The _CPU_Context_Fp_start macro is used in the XXX routine and allows the initial pointer into a  floating point context area (used to save the floating point context) to be at an arbitrary place in the floating point context area.  This is necessary because some FP units are designed to have their context saved as a stack which grows into lower addresses.  Other FP units can be saved by simply moving registers into offsets from the base of the context area.  Finally some FP units provide a "dump context" instruction which could fill in from high to low or low to high based on the whim of the CPU designers.  Regardless, the address at which that floating point context area pointer should start within the actual floating point context area varies between ports and this macro provides a clean way of addressing this.
391
392This is a common implementation of the _CPU_Context_Fp_start routine which
393is suitable for many processors.  In particular, RISC processors tend to
394use this implementation since the floating point context is saved as a
395sequence of store operations.
396
397@example
398#define _CPU_Context_Fp_start( _base, _offset ) \
399   ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
400@end example
401
402In contrast, the m68k treats the floating point context area as a stack
403which grows downward in memory.  Thus the following implementation of
404_CPU_Context_Fp_start is used in that port:
405
406
407@example
408XXX insert m68k version here
409@end example
410
411@subsection Initializing a Floating Point Context
412
413The _CPU_Context_Initialize_fp routine initializes the floating point
414context area passed to it to. There are a few standard ways in which to
415initialize the floating point context.  The simplest, and least
416deterministic behaviorally, is to do nothing.  This leaves the FPU in a
417random state and is generally not a suitable way to implement this
418routine.  The second common implementation is to place a "null FP status
419word" into some status/control register in the FPU.  This mechanism is
420simple and works on many FPUs.  Another common way is to initialize the
421FPU to a known state during _CPU_Initialize and save the context (using
422_CPU_Context_save_fp_context) into the special floating point context
423_CPU_Null_fp_context.  Then all that is required to initialize a floating
424point context is to copy _CPU_Null_fp_context to the destination floating
425point context passed to it.  The following example implementation shows
426how to accomplish this:
427
428@example
429#define _CPU_Context_Initialize_fp( _destination ) \
430  @{ \
431   *((Context_Control_fp *) *((void **) _destination)) = \
432       _CPU_Null_fp_context; \
433  @}
434@end example
435
436The _CPU_Null_fp_context is optional.  A port need only include this variable when it uses the above mechanism to initialize a floating point context.  This is typically done on CPUs where it is difficult to generate an "uninitialized" FP context.  If the port requires this variable, then it is declared as follows:
437
438@example
439Context_Control_fp  _CPU_Null_fp_context;
440@end example
441
442
443@subsection Saving a Floating Point Context
444
445The _CPU_Context_save_fp_context routine is responsible for saving the FP
446context at *fp_context_ptr.  If the point to load the FP context from is
447changed then the pointer is modified by this routine.
448
449Sometimes a macro implementation of this is in cpu.h which dereferences
450the ** and a similarly named routine in this file is passed something like
451a (Context_Control_fp *).  The general rule on making this decision is to
452avoid writing assembly language.
453
454@example
455void _CPU_Context_save_fp(
456  void **fp_context_ptr
457)
458@end example
459
460@subsection Restoring a Floating Point Context
461
462The _CPU_Context_restore_fp_context is responsible for restoring the FP
463context at *fp_context_ptr.  If the point to load the FP context from is
464changed then the pointer is modified by this routine.
465
466Sometimes a macro implementation of this is in cpu.h which dereferences
467the ** and a similarly named routine in this file is passed something like
468a (Context_Control_fp *).  The general rule on making this decision is to
469avoid writing assembly language.
470
471@example
472void _CPU_Context_restore_fp(
473  void **fp_context_ptr
474);
475@end example
476
Note: See TracBrowser for help on using the repository browser.