source: rtems/cpukit/score/include/rtems/score/percpu.h @ 39e51758

4.115
Last change on this file since 39e51758 was 39e51758, checked in by Sebastian Huber <sebastian.huber@…>, on 06/14/13 at 12:00:38

smp: Add and use _CPU_SMP_Get_current_processor()

Add and use _SMP_Get_current_processor() and
rtems_smp_get_current_processor().

Delete bsp_smp_interrupt_cpu().

Change type of current processor index from int to uint32_t to match
_SMP_Processor_count type.

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/**
2 *  @file  rtems/score/percpu.h
3 *
4 *  This include file defines the per CPU information required
5 *  by RTEMS.
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2011.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 */
16
17#ifndef _RTEMS_PERCPU_H
18#define _RTEMS_PERCPU_H
19
20#include <rtems/score/cpu.h>
21
22#ifdef ASM
23  #include <rtems/asm.h>
24#else
25  #include <rtems/score/isrlevel.h>
26  #include <rtems/score/timestamp.h>
27  #include <rtems/score/smplock.h>
28  #include <rtems/score/smp.h>
29#endif
30
31/**
32 *  @defgroup PerCPU RTEMS Per CPU Information
33 *
34 *  @ingroup Score
35 *
36 *  This defines the per CPU state information required by RTEMS
37 *  and the BSP.  In an SMP configuration, there will be multiple
38 *  instances of this data structure -- one per CPU -- and the
39 *  current CPU number will be used as the index.
40 */
41
42/**@{*/
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48#ifndef ASM
49#include <rtems/score/timestamp.h>
50
51#ifndef __THREAD_CONTROL_DEFINED__
52#define __THREAD_CONTROL_DEFINED__
53typedef struct Thread_Control_struct Thread_Control;
54#endif
55
56#ifdef RTEMS_SMP
57
58typedef enum {
59  /**
60   * @brief The per CPU controls are initialized to zero.
61   *
62   * In this state the only valid field of the per CPU controls for secondary
63   * processors is the per CPU state.  The secondary processors should perform
64   * their basic initialization now and change into the
65   * PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING state once this is complete.
66   *
67   * The owner of the per CPU state field is the secondary processor in this
68   * state.
69   */
70  PER_CPU_STATE_BEFORE_INITIALIZATION,
71
72  /**
73   * @brief Secondary processor is ready to begin multitasking.
74   *
75   * The secondary processor performed its basic initialization and is ready to
76   * receive inter-processor interrupts.  Interrupt delivery must be disabled
77   * in this state, but requested inter-processor interrupts must be recorded
78   * and must be delivered once the secondary processor enables interrupts for
79   * the first time.  The main processor will wait for all secondary processors
80   * to change into this state.  In case a secondary processor does not reach
81   * this state the system will not start.  The secondary processors wait now
82   * for a change into the PER_CPU_STATE_BEGIN_MULTITASKING state set by the
83   * main processor once all secondary processors reached the
84   * PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING state.
85   *
86   * The owner of the per CPU state field is the main processor in this state.
87   */
88  PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING,
89
90  /**
91   * @brief Multitasking begin of secondary processor is requested.
92   *
93   * The main processor completed system initialization and is about to perform
94   * a context switch to its heir thread.  Secondary processors should now
95   * issue a context switch to the heir thread.  This normally enables
96   * interrupts on the processor for the first time.
97   *
98   * The owner of the per CPU state field is the secondary processor in this
99   * state.
100   */
101  PER_CPU_STATE_BEGIN_MULTITASKING,
102
103  /**
104   * @brief Normal multitasking state.
105   *
106   * The owner of the per CPU state field is the secondary processor in this
107   * state.
108   */
109  PER_CPU_STATE_UP,
110
111  /**
112   * @brief This is the terminal state.
113   *
114   * The owner of the per CPU state field is the secondary processor in this
115   * state.
116   */
117  PER_CPU_STATE_SHUTDOWN
118} Per_CPU_State;
119
120#endif /* RTEMS_SMP */
121
122/**
123 *  @brief Per CPU Core Structure
124 *
125 *  This structure is used to hold per core state information.
126 */
127typedef struct {
128  #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \
129      (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
130    /**
131     * This contains a pointer to the lower range of the interrupt stack for
132     * this CPU.  This is the address allocated and freed.
133     */
134    void  *interrupt_stack_low;
135
136    /**
137     * This contains a pointer to the interrupt stack pointer for this CPU.
138     * It will be loaded at the beginning on an ISR.
139     */
140    void  *interrupt_stack_high;
141  #endif
142
143  /**
144   *  This contains the current interrupt nesting level on this
145   *  CPU.
146   */
147  uint32_t isr_nest_level;
148
149  /** This is set to true when this CPU needs to run the dispatcher. */
150  volatile bool dispatch_necessary;
151
152  /** This is the thread executing on this CPU. */
153  Thread_Control *executing;
154
155  /** This is the heir thread for this this CPU. */
156  Thread_Control *heir;
157
158  /** This is the time of the last context switch on this CPU. */
159  Timestamp_Control time_of_last_context_switch;
160
161  #if defined(RTEMS_SMP)
162    /** This element is used to lock this structure */
163    SMP_lock_Control lock;
164
165    /**
166     *  This is the request for the interrupt.
167     *
168     *  @note This may become a chain protected by atomic instructions.
169     */
170    uint32_t message;
171
172    /**
173     * @brief Indicates the current state of the CPU.
174     *
175     * This field is not protected by a lock.
176     *
177     * @see _Per_CPU_Change_state() and _Per_CPU_Wait_for_state().
178     */
179    Per_CPU_State state;
180  #endif
181} Per_CPU_Control;
182#endif
183
184#if defined(ASM) || defined(_RTEMS_PERCPU_DEFINE_OFFSETS)
185
186#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \
187    (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
188  /*
189   *  If this CPU target lets RTEMS allocates the interrupt stack, then
190   *  we need to have places in the per CPU table to hold them.
191   */
192  #define PER_CPU_INTERRUPT_STACK_LOW \
193    0
194  #define PER_CPU_INTERRUPT_STACK_HIGH \
195    PER_CPU_INTERRUPT_STACK_LOW + CPU_SIZEOF_POINTER
196  #define PER_CPU_END_STACK             \
197    PER_CPU_INTERRUPT_STACK_HIGH + CPU_SIZEOF_POINTER
198
199  #define INTERRUPT_STACK_LOW \
200    (SYM(_Per_CPU_Information) + PER_CPU_INTERRUPT_STACK_LOW)
201  #define INTERRUPT_STACK_HIGH \
202    (SYM(_Per_CPU_Information) + PER_CPU_INTERRUPT_STACK_HIGH)
203#else
204  #define PER_CPU_END_STACK \
205    0
206#endif
207
208/*
209 *  These are the offsets of the required elements in the per CPU table.
210 */
211#define PER_CPU_ISR_NEST_LEVEL \
212  PER_CPU_END_STACK
213#define PER_CPU_DISPATCH_NEEDED \
214  PER_CPU_ISR_NEST_LEVEL + 4
215
216#define ISR_NEST_LEVEL \
217  (SYM(_Per_CPU_Information) + PER_CPU_ISR_NEST_LEVEL)
218#define DISPATCH_NEEDED \
219  (SYM(_Per_CPU_Information) + PER_CPU_DISPATCH_NEEDED)
220
221#endif /* defined(ASM) || defined(_RTEMS_PERCPU_DEFINE_OFFSETS) */
222
223#ifndef ASM
224
225/**
226 *  @brief Set of Per CPU Core Information
227 *
228 *  This is an array of per CPU core information.
229 */
230extern Per_CPU_Control _Per_CPU_Information[] CPU_STRUCTURE_ALIGNMENT;
231
232#if defined(RTEMS_SMP)
233/**
234 *  @brief Set of Pointers to Per CPU Core Information
235 *
236 *  This is an array of pointers to each CPU's per CPU data structure.
237 *  It should be simpler to retrieve this pointer in assembly language
238 *  that to calculate the array offset.
239 */
240extern Per_CPU_Control *_Per_CPU_Information_p[];
241
242/**
243 *  @brief Initialize SMP Handler
244 *
245 *  This method initialize the SMP Handler.
246 */
247void _SMP_Handler_initialize(void);
248
249/**
250 *  @brief Allocate and Initialize Per CPU Structures
251 *
252 *  This method allocates and initialize the per CPU structure.
253 */
254void _Per_CPU_Initialize(void);
255
256void _Per_CPU_Change_state(
257  Per_CPU_Control *per_cpu,
258  Per_CPU_State new_state
259);
260
261void _Per_CPU_Wait_for_state(
262  const Per_CPU_Control *per_cpu,
263  Per_CPU_State desired_state
264);
265
266#define _Per_CPU_Lock_acquire( per_cpu, isr_cookie ) \
267  _SMP_lock_ISR_disable_and_acquire( &( per_cpu )->lock, isr_cookie )
268
269#define _Per_CPU_Lock_release( per_cpu, isr_cookie ) \
270  _SMP_lock_Release_and_ISR_enable( &( per_cpu )->lock, isr_cookie )
271
272#endif
273
274/*
275 * On a non SMP system, the _SMP_Get_current_processor() is defined to 0.
276 * Thus when built for non-SMP, there should be no performance penalty.
277 */
278#define _Thread_Heir \
279  _Per_CPU_Information[_SMP_Get_current_processor()].heir
280#define _Thread_Executing \
281  _Per_CPU_Information[_SMP_Get_current_processor()].executing
282#define _ISR_Nest_level \
283  _Per_CPU_Information[_SMP_Get_current_processor()].isr_nest_level
284#define _CPU_Interrupt_stack_low \
285  _Per_CPU_Information[_SMP_Get_current_processor()].interrupt_stack_low
286#define _CPU_Interrupt_stack_high \
287  _Per_CPU_Information[_SMP_Get_current_processor()].interrupt_stack_high
288#define _Thread_Dispatch_necessary \
289  _Per_CPU_Information[_SMP_Get_current_processor()].dispatch_necessary
290#define _Thread_Time_of_last_context_switch \
291  _Per_CPU_Information[_SMP_Get_current_processor()].time_of_last_context_switch
292
293#endif  /* ASM */
294
295#ifdef __cplusplus
296}
297#endif
298
299/**@}*/
300
301#endif
302/* end of include file */
Note: See TracBrowser for help on using the repository browser.