source: rtems/c/src/lib/libcpu/powerpc/new-exceptions/cpu.c @ 38b59a6

4.115
Last change on this file since 38b59a6 was 38b59a6, checked in by Sebastian Huber <sebastian.huber@…>, on 05/02/14 at 08:31:09

score: Implement forced thread migration

The current implementation of task migration in RTEMS has some
implications with respect to the interrupt latency. It is crucial to
preserve the system invariant that a task can execute on at most one
processor in the system at a time. This is accomplished with a boolean
indicator in the task context. The processor architecture specific
low-level task context switch code will mark that a task context is no
longer executing and waits that the heir context stopped execution
before it restores the heir context and resumes execution of the heir
task. So there is one point in time in which a processor is without a
task. This is essential to avoid cyclic dependencies in case multiple
tasks migrate at once. Otherwise some supervising entity is necessary to
prevent life-locks. Such a global supervisor would lead to scalability
problems so this approach is not used. Currently the thread dispatch is
performed with interrupts disabled. So in case the heir task is
currently executing on another processor then this prolongs the time of
disabled interrupts since one processor has to wait for another
processor to make progress.

It is difficult to avoid this issue with the interrupt latency since
interrupts normally store the context of the interrupted task on its
stack. In case a task is marked as not executing we must not use its
task stack to store such an interrupt context. We cannot use the heir
stack before it stopped execution on another processor. So if we enable
interrupts during this transition we have to provide an alternative task
independent stack for this time frame. This issue needs further
investigation.

  • Property mode set to 100644
File size: 4.2 KB
Line 
1/*
2 *  PowerPC CPU Dependent Source
3 *
4 *  Author:     Andrew Bray <andy@i-cubed.co.uk>
5 *
6 *  COPYRIGHT (c) 1995 by i-cubed ltd.
7 *
8 *  To anyone who acknowledges that this file is provided "AS IS"
9 *  without any express or implied warranty:
10 *      permission to use, copy, modify, and distribute this file
11 *      for any purpose is hereby granted without fee, provided that
12 *      the above copyright notice and this notice appears in all
13 *      copies, and that the name of i-cubed limited not be used in
14 *      advertising or publicity pertaining to distribution of the
15 *      software without specific, written prior permission.
16 *      i-cubed limited makes no representations about the suitability
17 *      of this software for any purpose.
18 *
19 *  Derived from c/src/exec/cpu/no_cpu/cpu.c:
20 *
21 *  COPYRIGHT (c) 1989-1997.
22 *  On-Line Applications Research Corporation (OAR).
23 *
24 *  The license and distribution terms for this file may be found in
25 *  the file LICENSE in this distribution or at
26 *  http://www.rtems.org/license/LICENSE.
27 */
28
29#include <string.h>
30
31#include <rtems/system.h>
32#include <rtems/score/isr.h>
33#include <rtems/score/context.h>
34#include <rtems/score/thread.h>
35#include <rtems/score/interr.h>
36#include <rtems/score/cpu.h>
37#include <rtems/score/tls.h>
38#include <rtems/powerpc/powerpc.h>
39
40/*  _CPU_Initialize
41 *
42 *  This routine performs processor dependent initialization.
43 *
44 *  INPUT PARAMETERS: NONE
45 */
46
47void _CPU_Initialize(void)
48{
49  /* Do nothing */
50#ifdef __ALTIVEC__
51  _CPU_Initialize_altivec();
52#endif
53}
54
55/*PAGE
56 *
57 *  _CPU_Context_Initialize
58 */
59
60void _CPU_Context_Initialize(
61  Context_Control  *the_context,
62  uint32_t         *stack_base,
63  uint32_t          size,
64  uint32_t          new_level,
65  void             *entry_point,
66  bool              is_fp,
67  void             *tls_area
68)
69{
70  ppc_context *the_ppc_context;
71  uint32_t   msr_value;
72  uint32_t   sp;
73
74  sp = (uint32_t)stack_base + size - PPC_MINIMUM_STACK_FRAME_SIZE;
75
76  sp &= ~(CPU_STACK_ALIGNMENT-1);
77
78  *((uint32_t*)sp) = 0;
79
80  _CPU_MSR_GET( msr_value );
81
82  /*
83   * Setting the interrupt mask here is not strictly necessary
84   * since the IRQ level will be established from _Thread_Handler()
85   * again, as soon as the task starts execution.
86   * Because we have to establish a defined state anyways we
87   * can as well leave this code here.
88   * I.e., simply (and unconditionally) saying
89   *
90   *   msr_value &= ~ppc_interrupt_get_disable_mask();
91   *
92   * would be an alternative.
93   */
94
95  if (!(new_level & CPU_MODES_INTERRUPT_MASK)) {
96    msr_value |= ppc_interrupt_get_disable_mask();
97  }
98  else {
99    msr_value &= ~ppc_interrupt_get_disable_mask();
100  }
101
102  /*
103   *  The FP bit of the MSR should only be enabled if this is a floating
104   *  point task.  Unfortunately, the vfprintf_r routine in newlib
105   *  ends up pushing a floating point register regardless of whether or
106   *  not a floating point number is being printed.  Serious restructuring
107   *  of vfprintf.c will be required to avoid this behavior.  At this
108   *  time (7 July 1997), this restructuring is not being done.
109   */
110
111  /* Make sure integer tasks have no FPU access in order to
112   * catch violations. Gcc may implicitely use the FPU and
113   * data corruption may happen.
114   * Since we set the_contex->msr using our current MSR,
115   * we must make sure MSR_FP is off if (!is_fp)...
116   * Unfortunately, this means that users of vfprintf_r have to use FP
117   * tasks or fix vfprintf. Furthermore, users of int-only tasks
118   * must prevent gcc from using the FPU (currently -msoft-float is the
119   * only way...)
120   */
121  if ( is_fp )
122    msr_value |= PPC_MSR_FP;
123  else
124    msr_value &= ~PPC_MSR_FP;
125
126  memset( the_context, 0, sizeof( *the_context ) );
127
128  the_ppc_context = ppc_get_context( the_context );
129  the_ppc_context->gpr1 = sp;
130  the_ppc_context->msr = msr_value;
131  the_ppc_context->lr = (uint32_t) entry_point;
132
133#ifdef RTEMS_SMP
134  the_ppc_context->is_executing = false;
135#endif
136
137#ifdef __ALTIVEC__
138  _CPU_Context_initialize_altivec( the_ppc_context );
139#endif
140
141  if ( tls_area != NULL ) {
142    void *tls_block = _TLS_TCB_before_TLS_block_initialize( tls_area );
143
144    the_ppc_context->gpr2 = (uint32_t) tls_block + 0x7000;
145  } else {
146    register uint32_t gpr2 __asm__("2");
147
148    the_ppc_context->gpr2 = gpr2;
149  }
150}
Note: See TracBrowser for help on using the repository browser.