source: rtems/cpukit/score/cpu/arm/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.1 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreCPU
5 *
6 * @brief ARM architecture support implementation.
7 */
8
9/*
10 *  COPYRIGHT (c) 2000 Canon Research Centre France SA.
11 *  Emmanuel Raguet, mailto:raguet@crf.canon.fr
12 *
13 *  Copyright (c) 2002 Advent Networks, Inc
14 *      Jay Monkman <jmonkman@adventnetworks.com>
15 *
16 *  Copyright (c) 2007 Ray xu <rayx.cn@gmail.com>
17 *
18 *  Copyright (c) 2009-2011 embedded brains GmbH
19 *
20 *  The license and distribution terms for this file may be
21 *  found in the file LICENSE in this distribution or at
22 *  http://www.rtems.org/license/LICENSE.
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <rtems/system.h>
30#include <rtems.h>
31#include <rtems/bspIo.h>
32#include <rtems/score/isr.h>
33#include <rtems/score/wkspace.h>
34#include <rtems/score/thread.h>
35#include <rtems/score/tls.h>
36#include <rtems/score/cpu.h>
37
38#ifdef ARM_MULTILIB_VFP_D32
39  RTEMS_STATIC_ASSERT(
40    offsetof( Context_Control, register_d8 ) == ARM_CONTEXT_CONTROL_D8_OFFSET,
41    ARM_CONTEXT_CONTROL_D8_OFFSET
42  );
43#endif
44
45#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
46  RTEMS_STATIC_ASSERT(
47    offsetof( Context_Control, thread_id )
48      == ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET,
49    ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET
50  );
51#endif
52
53#ifdef RTEMS_SMP
54  RTEMS_STATIC_ASSERT(
55    offsetof( Context_Control, is_executing )
56      == ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET,
57    ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET
58  );
59#endif
60
61RTEMS_STATIC_ASSERT(
62  sizeof( CPU_Exception_frame ) == ARM_EXCEPTION_FRAME_SIZE,
63  ARM_EXCEPTION_FRAME_SIZE
64);
65
66RTEMS_STATIC_ASSERT(
67  offsetof( CPU_Exception_frame, register_sp )
68    == ARM_EXCEPTION_FRAME_REGISTER_SP_OFFSET,
69  ARM_EXCEPTION_FRAME_REGISTER_SP_OFFSET
70);
71
72RTEMS_STATIC_ASSERT(
73  sizeof( ARM_VFP_context ) == ARM_VFP_CONTEXT_SIZE,
74  ARM_VFP_CONTEXT_SIZE
75);
76
77#ifdef ARM_MULTILIB_ARCH_V4
78
79/*
80 * This variable can be used to change the running mode of the execution
81 * contexts.
82 */
83uint32_t arm_cpu_mode = 0x13;
84
85void _CPU_Context_Initialize(
86  Context_Control *the_context,
87  void *stack_area_begin,
88  size_t stack_area_size,
89  uint32_t new_level,
90  void (*entry_point)( void ),
91  bool is_fp,
92  void *tls_area
93)
94{
95  the_context->register_sp = (uint32_t) stack_area_begin + stack_area_size;
96  the_context->register_lr = (uint32_t) entry_point;
97  the_context->register_cpsr = ( ( new_level != 0 ) ? ARM_PSR_I : 0 )
98    | arm_cpu_mode;
99
100#ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER
101  the_context->thread_id = (uint32_t) tls_area;
102#endif
103
104#ifdef RTEMS_SMP
105  the_context->is_executing = false;
106#endif
107
108  if ( tls_area != NULL ) {
109    _TLS_TCB_at_area_begin_initialize( tls_area );
110  }
111}
112
113/* Preprocessor magic for stringification of x */
114#define _CPU_ISR_LEVEL_DO_STRINGOF( x) #x
115#define _CPU_ISR_LEVEL_STRINGOF( x) _CPU_ISR_LEVEL_DO_STRINGOF( x)
116
117void _CPU_ISR_Set_level( uint32_t level )
118{
119  uint32_t arm_switch_reg;
120
121  level = ( level != 0 ) ? ARM_PSR_I : 0;
122
123  __asm__ volatile (
124    ARM_SWITCH_TO_ARM
125    "mrs %[arm_switch_reg], cpsr\n"
126    "bic %[arm_switch_reg], #" _CPU_ISR_LEVEL_STRINGOF( ARM_PSR_I ) "\n"
127    "orr %[arm_switch_reg], %[level]\n"
128    "msr cpsr, %0\n"
129    ARM_SWITCH_BACK
130    : [arm_switch_reg] "=&r" (arm_switch_reg)
131    : [level] "r" (level)
132  );
133}
134
135uint32_t _CPU_ISR_Get_level( void )
136{
137  ARM_SWITCH_REGISTERS;
138  uint32_t level;
139
140  __asm__ volatile (
141    ARM_SWITCH_TO_ARM
142    "mrs %[level], cpsr\n"
143    "and %[level], #" _CPU_ISR_LEVEL_STRINGOF( ARM_PSR_I ) "\n"
144    ARM_SWITCH_BACK
145    : [level] "=&r" (level) ARM_SWITCH_ADDITIONAL_OUTPUT
146  );
147
148  return ( level & ARM_PSR_I ) != 0;
149}
150
151void _CPU_ISR_install_vector(
152  uint32_t vector,
153  proc_ptr new_handler,
154  proc_ptr *old_handler
155)
156{
157  /* Redirection table starts at the end of the vector table */
158  volatile uint32_t *table = (volatile uint32_t *) (MAX_EXCEPTIONS * 4);
159
160  uint32_t current_handler = table [vector];
161
162  /* The current handler is now the old one */
163  if (old_handler != NULL) {
164    *old_handler = (proc_ptr) current_handler;
165  }
166
167  /* Write only if necessary to avoid writes to a maybe read-only memory */
168  if (current_handler != (uint32_t) new_handler) {
169    table [vector] = (uint32_t) new_handler;
170  }
171}
172
173void _CPU_Initialize( void )
174{
175  /* Do nothing */
176}
177
178#endif /* ARM_MULTILIB_ARCH_V4 */
Note: See TracBrowser for help on using the repository browser.