source: rtems/cpukit/score/include/rtems/score/percpu.h @ bec4730

4.115
Last change on this file since bec4730 was bec4730, checked in by Sebastian Huber <sebastian.huber@…>, on 06/30/14 at 10:55:50

score: Add PER_CPU_OFFSET_EXECUTING

Add PER_CPU_OFFSET_HEIR. Move Per_CPU_Control::executing and
Per_CPU_Control::heir for easy offset calculation.

  • Property mode set to 100644
File size: 18.2 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.org/license/LICENSE.
15 */
16
17#ifndef _RTEMS_PERCPU_H
18#define _RTEMS_PERCPU_H
19
20#include <rtems/score/cpu.h>
21
22#if defined( ASM )
23  #include <rtems/asm.h>
24#else
25  #include <rtems/score/assert.h>
26  #include <rtems/score/isrlevel.h>
27  #include <rtems/score/smp.h>
28  #include <rtems/score/smplock.h>
29  #include <rtems/score/timestamp.h>
30#endif
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36#if defined( RTEMS_SMP )
37  /*
38   * This ensures that on SMP configurations the individual per-CPU controls
39   * are on different cache lines to prevent false sharing.  This define can be
40   * used in assembler code to easily get the per-CPU control for a particular
41   * processor.
42   */
43  #if defined( RTEMS_PROFILING )
44    #define PER_CPU_CONTROL_SIZE_LOG2 8
45  #else
46    #define PER_CPU_CONTROL_SIZE_LOG2 7
47  #endif
48
49  #define PER_CPU_CONTROL_SIZE ( 1 << PER_CPU_CONTROL_SIZE_LOG2 )
50#endif
51
52#if !defined( ASM )
53
54#ifndef __THREAD_CONTROL_DEFINED__
55#define __THREAD_CONTROL_DEFINED__
56typedef struct Thread_Control_struct Thread_Control;
57#endif
58
59struct Scheduler_Context;
60
61/**
62 *  @defgroup PerCPU RTEMS Per CPU Information
63 *
64 *  @ingroup Score
65 *
66 *  This defines the per CPU state information required by RTEMS
67 *  and the BSP.  In an SMP configuration, there will be multiple
68 *  instances of this data structure -- one per CPU -- and the
69 *  current CPU number will be used as the index.
70 */
71
72/**@{*/
73
74#if defined( RTEMS_SMP )
75
76#if CPU_USE_DEFERRED_FP_SWITCH == TRUE
77  #error "deferred FP switch not implemented for SMP"
78#endif
79
80/**
81 * @brief State of a processor.
82 *
83 * The processor state controls the life cycle of processors at the lowest
84 * level.  No multi-threading or other high-level concepts matter here.
85 *
86 * State changes must be initiated via _Per_CPU_State_change().  This function
87 * may not return in case someone requested a shutdown.  The
88 * _SMP_Send_message() function will be used to notify other processors about
89 * state changes if the other processor is in the up state.
90 *
91 * Due to the sequential nature of the basic system initialization one
92 * processor has a special role.  It is the processor executing the boot_card()
93 * function.  This processor is called the boot processor.  All other
94 * processors are called secondary.
95 *
96 * @dot
97 * digraph states {
98 *   i [label="PER_CPU_STATE_INITIAL"];
99 *   rdy [label="PER_CPU_STATE_READY_TO_START_MULTITASKING"];
100 *   reqsm [label="PER_CPU_STATE_REQUEST_START_MULTITASKING"];
101 *   u [label="PER_CPU_STATE_UP"];
102 *   s [label="PER_CPU_STATE_SHUTDOWN"];
103 *   i -> rdy [label="processor\ncompleted initialization"];
104 *   rdy -> reqsm [label="boot processor\ncompleted initialization"];
105 *   reqsm -> u [label="processor\nstarts multitasking"];
106 *   i -> s;
107 *   rdy -> s;
108 *   reqsm -> s;
109 *   u -> s;
110 * }
111 * @enddot
112 */
113typedef enum {
114  /**
115   * @brief The per CPU controls are initialized to zero.
116   *
117   * The boot processor executes the sequential boot code in this state.  The
118   * secondary processors should perform their basic initialization now and
119   * change into the PER_CPU_STATE_READY_TO_START_MULTITASKING state once this
120   * is complete.
121   */
122  PER_CPU_STATE_INITIAL,
123
124  /**
125   * @brief Processor is ready to start multitasking.
126   *
127   * The secondary processor performed its basic initialization and is ready to
128   * receive inter-processor interrupts.  Interrupt delivery must be disabled
129   * in this state, but requested inter-processor interrupts must be recorded
130   * and must be delivered once the secondary processor enables interrupts for
131   * the first time.  The boot processor will wait for all secondary processors
132   * to change into this state.  In case a secondary processor does not reach
133   * this state the system will not start.  The secondary processors wait now
134   * for a change into the PER_CPU_STATE_REQUEST_START_MULTITASKING state set
135   * by the boot processor once all secondary processors reached the
136   * PER_CPU_STATE_READY_TO_START_MULTITASKING state.
137   */
138  PER_CPU_STATE_READY_TO_START_MULTITASKING,
139
140  /**
141   * @brief Multitasking start of processor is requested.
142   *
143   * The boot processor completed system initialization and is about to perform
144   * a context switch to its heir thread.  Secondary processors should now
145   * issue a context switch to the heir thread.  This normally enables
146   * interrupts on the processor for the first time.
147   */
148  PER_CPU_STATE_REQUEST_START_MULTITASKING,
149
150  /**
151   * @brief Normal multitasking state.
152   */
153  PER_CPU_STATE_UP,
154
155  /**
156   * @brief This is the terminal state.
157   */
158  PER_CPU_STATE_SHUTDOWN
159} Per_CPU_State;
160
161#endif /* defined( RTEMS_SMP ) */
162
163/**
164 * @brief Per-CPU statistics.
165 */
166typedef struct {
167#if defined( RTEMS_PROFILING )
168  /**
169   * @brief The thread dispatch disabled begin instant in CPU counter ticks.
170   *
171   * This value is used to measure the time of disabled thread dispatching.
172   */
173  CPU_Counter_ticks thread_dispatch_disabled_instant;
174
175  /**
176   * @brief The maximum time of disabled thread dispatching in CPU counter
177   * ticks.
178   */
179  CPU_Counter_ticks max_thread_dispatch_disabled_time;
180
181  /**
182   * @brief The maximum time spent to process a single sequence of nested
183   * interrupts in CPU counter ticks.
184   *
185   * This is the time interval between the change of the interrupt nest level
186   * from zero to one and the change back from one to zero.
187   */
188  CPU_Counter_ticks max_interrupt_time;
189
190  /**
191   * @brief The maximum interrupt delay in CPU counter ticks if supported by
192   * the hardware.
193   */
194  CPU_Counter_ticks max_interrupt_delay;
195
196  /**
197   * @brief Count of times when the thread dispatch disable level changes from
198   * zero to one in thread context.
199   *
200   * This value may overflow.
201   */
202  uint64_t thread_dispatch_disabled_count;
203
204  /**
205   * @brief Total time of disabled thread dispatching in CPU counter ticks.
206   *
207   * The average time of disabled thread dispatching is the total time of
208   * disabled thread dispatching divided by the thread dispatch disabled
209   * count.
210   *
211   * This value may overflow.
212   */
213  uint64_t total_thread_dispatch_disabled_time;
214
215  /**
216   * @brief Count of times when the interrupt nest level changes from zero to
217   * one.
218   *
219   * This value may overflow.
220   */
221  uint64_t interrupt_count;
222
223  /**
224   * @brief Total time of interrupt processing in CPU counter ticks.
225   *
226   * The average time of interrupt processing is the total time of interrupt
227   * processing divided by the interrupt count.
228   *
229   * This value may overflow.
230   */
231  uint64_t total_interrupt_time;
232#endif /* defined( RTEMS_PROFILING ) */
233} Per_CPU_Stats;
234
235/**
236 *  @brief Per CPU Core Structure
237 *
238 *  This structure is used to hold per core state information.
239 */
240typedef struct Per_CPU_Control {
241  /**
242   * @brief CPU port specific control.
243   */
244  CPU_Per_CPU_control cpu_per_cpu;
245
246  #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \
247      (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
248    /**
249     * This contains a pointer to the lower range of the interrupt stack for
250     * this CPU.  This is the address allocated and freed.
251     */
252    void  *interrupt_stack_low;
253
254    /**
255     * This contains a pointer to the interrupt stack pointer for this CPU.
256     * It will be loaded at the beginning on an ISR.
257     */
258    void  *interrupt_stack_high;
259  #endif
260
261  /**
262   *  This contains the current interrupt nesting level on this
263   *  CPU.
264   */
265  uint32_t isr_nest_level;
266
267  /**
268   * @brief The thread dispatch critical section nesting counter which is used
269   * to prevent context switches at inopportune moments.
270   */
271  volatile uint32_t thread_dispatch_disable_level;
272
273  /**
274   * @brief This is the thread executing on this processor.
275   *
276   * This field is not protected by a lock.  The only writer is this processor.
277   *
278   * On SMP configurations a thread may be registered as executing on more than
279   * one processor in case a thread migration is in progress.  On SMP
280   * configurations use _Thread_Is_executing_on_a_processor() to figure out if
281   * a thread context is executing on a processor.
282   */
283  Thread_Control *executing;
284
285  /**
286   * @brief This is the heir thread for this processor.
287   *
288   * This field is not protected by a lock.  The only writer after multitasking
289   * start is the scheduler owning this processor.  This processor will set the
290   * dispatch necessary indicator to false, before it reads the heir.  This
291   * field is used in combination with the dispatch necessary indicator.
292   *
293   * A thread can be a heir on at most one processor in the system.
294   *
295   * @see _Thread_Get_heir_and_make_it_executing().
296   */
297  Thread_Control *heir;
298
299  /**
300   * @brief This is set to true when this processor needs to run the
301   * dispatcher.
302   *
303   * It is volatile since interrupts may alter this flag.
304   *
305   * This field is not protected by a lock.  There are two writers after
306   * multitasking start.  The scheduler owning this processor sets this
307   * indicator to true, after it updated the heir field.  This processor sets
308   * this indicator to false, before it reads the heir.  This field is used in
309   * combination with the heir field.
310   *
311   * @see _Thread_Get_heir_and_make_it_executing().
312   */
313  volatile bool dispatch_necessary;
314
315  /** This is the time of the last context switch on this CPU. */
316  Timestamp_Control time_of_last_context_switch;
317
318  #if defined( RTEMS_SMP )
319    /**
320     * @brief This lock protects some parts of the low-level thread dispatching.
321     *
322     * We must use a ticket lock here since we cannot transport a local context
323     * through the context switch.
324     *
325     * @see _Thread_Dispatch().
326     */
327    SMP_ticket_lock_Control Lock;
328
329    /**
330     * @brief Lock statistics context for the per-CPU lock.
331     */
332    SMP_lock_Stats_context Lock_stats_context;
333
334    /**
335     * @brief Context for the Giant lock acquire and release pair of this
336     * processor.
337     */
338    SMP_lock_Context Giant_lock_context;
339
340    /**
341     * @brief Bit field for SMP messages.
342     *
343     * This bit field is not protected locks.  Atomic operations are used to
344     * set and get the message bits.
345     */
346    Atomic_Ulong message;
347
348    /**
349     * @brief The scheduler context of the scheduler owning this processor.
350     */
351    const struct Scheduler_Context *scheduler_context;
352
353    /**
354     * @brief Indicates the current state of the CPU.
355     *
356     * This field is protected by the _Per_CPU_State_lock lock.
357     *
358     * @see _Per_CPU_State_change().
359     */
360    Per_CPU_State state;
361
362    /**
363     * @brief Indicates if the processor has been successfully started via
364     * _CPU_SMP_Start_processor().
365     */
366    bool started;
367  #endif
368
369  Per_CPU_Stats Stats;
370} Per_CPU_Control;
371
372#if defined( RTEMS_SMP )
373typedef struct {
374  Per_CPU_Control per_cpu;
375  char unused_space_for_cache_line_alignment
376    [ PER_CPU_CONTROL_SIZE - sizeof( Per_CPU_Control ) ];
377} Per_CPU_Control_envelope;
378#else
379typedef struct {
380  Per_CPU_Control per_cpu;
381} Per_CPU_Control_envelope;
382#endif
383
384/**
385 *  @brief Set of Per CPU Core Information
386 *
387 *  This is an array of per CPU core information.
388 */
389extern Per_CPU_Control_envelope _Per_CPU_Information[] CPU_STRUCTURE_ALIGNMENT;
390
391#if defined( RTEMS_SMP )
392#define _Per_CPU_Acquire( cpu ) \
393  _SMP_ticket_lock_Acquire( \
394    &( cpu )->Lock, \
395    &( cpu )->Lock_stats_context \
396  )
397#else
398#define _Per_CPU_Acquire( cpu ) \
399  do { \
400    (void) ( cpu ); \
401  } while ( 0 )
402#endif
403
404#if defined( RTEMS_SMP )
405#define _Per_CPU_Release( cpu ) \
406  _SMP_ticket_lock_Release( \
407    &( cpu )->Lock, \
408    &( cpu )->Lock_stats_context \
409  )
410#else
411#define _Per_CPU_Release( cpu ) \
412  do { \
413    (void) ( cpu ); \
414  } while ( 0 )
415#endif
416
417#if defined( RTEMS_SMP )
418#define _Per_CPU_ISR_disable_and_acquire( cpu, isr_cookie ) \
419  do { \
420    _ISR_Disable_without_giant( isr_cookie ); \
421    _Per_CPU_Acquire( cpu ); \
422  } while ( 0 )
423#else
424#define _Per_CPU_ISR_disable_and_acquire( cpu, isr_cookie ) \
425  do { \
426    _ISR_Disable( isr_cookie ); \
427    (void) ( cpu ); \
428  } while ( 0 )
429#endif
430
431#if defined( RTEMS_SMP )
432#define _Per_CPU_Release_and_ISR_enable( cpu, isr_cookie ) \
433  do { \
434    _Per_CPU_Release( cpu ); \
435    _ISR_Enable_without_giant( isr_cookie ); \
436  } while ( 0 )
437#else
438#define _Per_CPU_Release_and_ISR_enable( cpu, isr_cookie ) \
439  do { \
440    (void) ( cpu ); \
441    _ISR_Enable( isr_cookie ); \
442  } while ( 0 )
443#endif
444
445#if defined( RTEMS_SMP )
446#define _Per_CPU_Acquire_all( isr_cookie ) \
447  do { \
448    uint32_t ncpus = _SMP_Get_processor_count(); \
449    uint32_t cpu; \
450    _ISR_Disable( isr_cookie ); \
451    for ( cpu = 0 ; cpu < ncpus ; ++cpu ) { \
452      _Per_CPU_Acquire( _Per_CPU_Get_by_index( cpu ) ); \
453    } \
454  } while ( 0 )
455#else
456#define _Per_CPU_Acquire_all( isr_cookie ) \
457  _ISR_Disable( isr_cookie )
458#endif
459
460#if defined( RTEMS_SMP )
461#define _Per_CPU_Release_all( isr_cookie ) \
462  do { \
463    uint32_t ncpus = _SMP_Get_processor_count(); \
464    uint32_t cpu; \
465    for ( cpu = 0 ; cpu < ncpus ; ++cpu ) { \
466      _Per_CPU_Release( _Per_CPU_Get_by_index( cpu ) ); \
467    } \
468    _ISR_Enable( isr_cookie ); \
469  } while ( 0 )
470#else
471#define _Per_CPU_Release_all( isr_cookie ) \
472  _ISR_Enable( isr_cookie )
473#endif
474
475/*
476 * If we get the current processor index in a context which allows thread
477 * dispatching, then we may already run on another processor right after the
478 * read instruction.  There are very few cases in which this makes sense (here
479 * we can use _Per_CPU_Get_snapshot()).  All other places must use
480 * _Per_CPU_Get() so that we can add checks for RTEMS_DEBUG.
481 */
482#if defined( _CPU_Get_current_per_CPU_control )
483  #define _Per_CPU_Get_snapshot() _CPU_Get_current_per_CPU_control()
484#else
485  #define _Per_CPU_Get_snapshot() \
486    ( &_Per_CPU_Information[ _SMP_Get_current_processor() ].per_cpu )
487#endif
488
489#if defined( RTEMS_SMP )
490static inline Per_CPU_Control *_Per_CPU_Get( void )
491{
492  Per_CPU_Control *cpu_self = _Per_CPU_Get_snapshot();
493
494  _Assert(
495    cpu_self->thread_dispatch_disable_level != 0 || _ISR_Get_level() != 0
496  );
497
498  return cpu_self;
499}
500#else
501#define _Per_CPU_Get() _Per_CPU_Get_snapshot()
502#endif
503
504static inline Per_CPU_Control *_Per_CPU_Get_by_index( uint32_t index )
505{
506  return &_Per_CPU_Information[ index ].per_cpu;
507}
508
509static inline uint32_t _Per_CPU_Get_index( const Per_CPU_Control *cpu )
510{
511  const Per_CPU_Control_envelope *per_cpu_envelope =
512    ( const Per_CPU_Control_envelope * ) cpu;
513
514  return ( uint32_t ) ( per_cpu_envelope - &_Per_CPU_Information[ 0 ] );
515}
516
517static inline bool _Per_CPU_Is_processor_started(
518  const Per_CPU_Control *cpu
519)
520{
521#if defined( RTEMS_SMP )
522  return cpu->started;
523#else
524  (void) cpu;
525
526  return true;
527#endif
528}
529
530#if defined( RTEMS_SMP )
531
532static inline void _Per_CPU_Send_interrupt( const Per_CPU_Control *cpu )
533{
534  _CPU_SMP_Send_interrupt( _Per_CPU_Get_index( cpu ) );
535}
536
537/**
538 *  @brief Allocate and Initialize Per CPU Structures
539 *
540 *  This method allocates and initialize the per CPU structure.
541 */
542void _Per_CPU_Initialize(void);
543
544void _Per_CPU_State_change(
545  Per_CPU_Control *cpu,
546  Per_CPU_State new_state
547);
548
549/**
550 * @brief Waits for a processor to change into a non-initial state.
551 *
552 * This function should be called only in _CPU_SMP_Start_processor() if
553 * required by the CPU port or BSP.
554 *
555 * @code
556 * bool _CPU_SMP_Start_processor(uint32_t cpu_index)
557 * {
558 *   uint32_t timeout = 123456;
559 *
560 *   start_the_processor(cpu_index);
561 *
562 *   return _Per_CPU_State_wait_for_non_initial_state(cpu_index, timeout);
563 * }
564 * @endcode
565 *
566 * @param[in] cpu_index The processor index.
567 * @param[in] timeout_in_ns The timeout in nanoseconds.  Use a value of zero to
568 * wait forever if necessary.
569 *
570 * @retval true The processor is in a non-initial state.
571 * @retval false The timeout expired before the processor reached a non-initial
572 * state.
573 */
574bool _Per_CPU_State_wait_for_non_initial_state(
575  uint32_t cpu_index,
576  uint32_t timeout_in_ns
577);
578
579#endif /* defined( RTEMS_SMP ) */
580
581/*
582 * On a non SMP system, the _SMP_Get_current_processor() is defined to 0.
583 * Thus when built for non-SMP, there should be no performance penalty.
584 */
585#define _Thread_Dispatch_disable_level \
586  _Per_CPU_Get()->thread_dispatch_disable_level
587#define _Thread_Heir \
588  _Per_CPU_Get()->heir
589#define _Thread_Executing \
590  _Per_CPU_Get()->executing
591#define _ISR_Nest_level \
592  _Per_CPU_Get()->isr_nest_level
593#define _CPU_Interrupt_stack_low \
594  _Per_CPU_Get()->interrupt_stack_low
595#define _CPU_Interrupt_stack_high \
596  _Per_CPU_Get()->interrupt_stack_high
597#define _Thread_Dispatch_necessary \
598  _Per_CPU_Get()->dispatch_necessary
599#define _Thread_Time_of_last_context_switch \
600  _Per_CPU_Get()->time_of_last_context_switch
601
602/**@}*/
603
604#endif /* !defined( ASM ) */
605
606#if defined( ASM ) || defined( _RTEMS_PERCPU_DEFINE_OFFSETS )
607
608#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \
609    (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
610  /*
611   *  If this CPU target lets RTEMS allocates the interrupt stack, then
612   *  we need to have places in the per CPU table to hold them.
613   */
614  #define PER_CPU_INTERRUPT_STACK_LOW \
615    CPU_PER_CPU_CONTROL_SIZE
616  #define PER_CPU_INTERRUPT_STACK_HIGH \
617    PER_CPU_INTERRUPT_STACK_LOW + CPU_SIZEOF_POINTER
618  #define PER_CPU_END_STACK             \
619    PER_CPU_INTERRUPT_STACK_HIGH + CPU_SIZEOF_POINTER
620
621  #define INTERRUPT_STACK_LOW \
622    (SYM(_Per_CPU_Information) + PER_CPU_INTERRUPT_STACK_LOW)
623  #define INTERRUPT_STACK_HIGH \
624    (SYM(_Per_CPU_Information) + PER_CPU_INTERRUPT_STACK_HIGH)
625#else
626  #define PER_CPU_END_STACK \
627    CPU_PER_CPU_CONTROL_SIZE
628#endif
629
630/*
631 *  These are the offsets of the required elements in the per CPU table.
632 */
633#define PER_CPU_ISR_NEST_LEVEL \
634  PER_CPU_END_STACK
635#define PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL \
636  PER_CPU_ISR_NEST_LEVEL + 4
637#define PER_CPU_OFFSET_EXECUTING \
638  PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL + 4
639#define PER_CPU_OFFSET_HEIR \
640  PER_CPU_OFFSET_EXECUTING + CPU_SIZEOF_POINTER
641#define PER_CPU_DISPATCH_NEEDED \
642  PER_CPU_OFFSET_HEIR + CPU_SIZEOF_POINTER
643
644#define THREAD_DISPATCH_DISABLE_LEVEL \
645  (SYM(_Per_CPU_Information) + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)
646#define ISR_NEST_LEVEL \
647  (SYM(_Per_CPU_Information) + PER_CPU_ISR_NEST_LEVEL)
648#define DISPATCH_NEEDED \
649  (SYM(_Per_CPU_Information) + PER_CPU_DISPATCH_NEEDED)
650
651#endif /* defined( ASM ) || defined( _RTEMS_PERCPU_DEFINE_OFFSETS ) */
652
653#ifdef __cplusplus
654}
655#endif
656
657#endif
658/* end of include file */
Note: See TracBrowser for help on using the repository browser.