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

5
Last change on this file since ccc92b8 was ccc92b8, checked in by Sebastian Huber <sebastian.huber@…>, on 11/21/16 at 09:26:32

score: Group Per_CPU_Control members by alignment

Close #2820.

  • Property mode set to 100644
File size: 22.9 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 *  Copyright (c) 2012, 2016 embedded brains GmbH
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#ifndef _RTEMS_PERCPU_H
20#define _RTEMS_PERCPU_H
21
22#include <rtems/score/cpuimpl.h>
23
24#if defined( ASM )
25  #include <rtems/asm.h>
26#else
27  #include <rtems/score/assert.h>
28  #include <rtems/score/chain.h>
29  #include <rtems/score/isrlock.h>
30  #include <rtems/score/smp.h>
31  #include <rtems/score/smplock.h>
32  #include <rtems/score/timestamp.h>
33  #include <rtems/score/watchdog.h>
34#endif
35
36#ifdef __cplusplus
37extern "C" {
38#endif
39
40#if defined(RTEMS_SMP)
41  #if defined(RTEMS_PROFILING)
42    #define PER_CPU_CONTROL_SIZE_APPROX ( 512 + CPU_INTERRUPT_FRAME_SIZE )
43  #elif defined(RTEMS_DEBUG)
44    #define PER_CPU_CONTROL_SIZE_APPROX ( 256 + CPU_INTERRUPT_FRAME_SIZE )
45  #else
46    #define PER_CPU_CONTROL_SIZE_APPROX ( 128 + CPU_INTERRUPT_FRAME_SIZE )
47  #endif
48
49  /*
50   * This ensures that on SMP configurations the individual per-CPU controls
51   * are on different cache lines to prevent false sharing.  This define can be
52   * used in assembler code to easily get the per-CPU control for a particular
53   * processor.
54   */
55  #if PER_CPU_CONTROL_SIZE_APPROX > 1024
56    #define PER_CPU_CONTROL_SIZE_LOG2 11
57  #elif PER_CPU_CONTROL_SIZE_APPROX > 512
58    #define PER_CPU_CONTROL_SIZE_LOG2 10
59  #elif PER_CPU_CONTROL_SIZE_APPROX > 256
60    #define PER_CPU_CONTROL_SIZE_LOG2 9
61  #elif PER_CPU_CONTROL_SIZE_APPROX > 128
62    #define PER_CPU_CONTROL_SIZE_LOG2 8
63  #else
64    #define PER_CPU_CONTROL_SIZE_LOG2 7
65  #endif
66
67  #define PER_CPU_CONTROL_SIZE ( 1 << PER_CPU_CONTROL_SIZE_LOG2 )
68#endif
69
70#if !defined( ASM )
71
72struct _Thread_Control;
73
74struct Scheduler_Context;
75
76/**
77 *  @defgroup PerCPU RTEMS Per CPU Information
78 *
79 *  @ingroup Score
80 *
81 *  This defines the per CPU state information required by RTEMS
82 *  and the BSP.  In an SMP configuration, there will be multiple
83 *  instances of this data structure -- one per CPU -- and the
84 *  current CPU number will be used as the index.
85 */
86
87/**@{*/
88
89#if defined( RTEMS_SMP )
90
91/**
92 * @brief State of a processor.
93 *
94 * The processor state controls the life cycle of processors at the lowest
95 * level.  No multi-threading or other high-level concepts matter here.
96 *
97 * State changes must be initiated via _Per_CPU_State_change().  This function
98 * may not return in case someone requested a shutdown.  The
99 * _SMP_Send_message() function will be used to notify other processors about
100 * state changes if the other processor is in the up state.
101 *
102 * Due to the sequential nature of the basic system initialization one
103 * processor has a special role.  It is the processor executing the boot_card()
104 * function.  This processor is called the boot processor.  All other
105 * processors are called secondary.
106 *
107 * @dot
108 * digraph states {
109 *   i [label="PER_CPU_STATE_INITIAL"];
110 *   rdy [label="PER_CPU_STATE_READY_TO_START_MULTITASKING"];
111 *   reqsm [label="PER_CPU_STATE_REQUEST_START_MULTITASKING"];
112 *   u [label="PER_CPU_STATE_UP"];
113 *   s [label="PER_CPU_STATE_SHUTDOWN"];
114 *   i -> rdy [label="processor\ncompleted initialization"];
115 *   rdy -> reqsm [label="boot processor\ncompleted initialization"];
116 *   reqsm -> u [label="processor\nstarts multitasking"];
117 *   i -> s;
118 *   rdy -> s;
119 *   reqsm -> s;
120 *   u -> s;
121 * }
122 * @enddot
123 */
124typedef enum {
125  /**
126   * @brief The per CPU controls are initialized to zero.
127   *
128   * The boot processor executes the sequential boot code in this state.  The
129   * secondary processors should perform their basic initialization now and
130   * change into the PER_CPU_STATE_READY_TO_START_MULTITASKING state once this
131   * is complete.
132   */
133  PER_CPU_STATE_INITIAL,
134
135  /**
136   * @brief Processor is ready to start multitasking.
137   *
138   * The secondary processor performed its basic initialization and is ready to
139   * receive inter-processor interrupts.  Interrupt delivery must be disabled
140   * in this state, but requested inter-processor interrupts must be recorded
141   * and must be delivered once the secondary processor enables interrupts for
142   * the first time.  The boot processor will wait for all secondary processors
143   * to change into this state.  In case a secondary processor does not reach
144   * this state the system will not start.  The secondary processors wait now
145   * for a change into the PER_CPU_STATE_REQUEST_START_MULTITASKING state set
146   * by the boot processor once all secondary processors reached the
147   * PER_CPU_STATE_READY_TO_START_MULTITASKING state.
148   */
149  PER_CPU_STATE_READY_TO_START_MULTITASKING,
150
151  /**
152   * @brief Multitasking start of processor is requested.
153   *
154   * The boot processor completed system initialization and is about to perform
155   * a context switch to its heir thread.  Secondary processors should now
156   * issue a context switch to the heir thread.  This normally enables
157   * interrupts on the processor for the first time.
158   */
159  PER_CPU_STATE_REQUEST_START_MULTITASKING,
160
161  /**
162   * @brief Normal multitasking state.
163   */
164  PER_CPU_STATE_UP,
165
166  /**
167   * @brief This is the terminal state.
168   */
169  PER_CPU_STATE_SHUTDOWN
170} Per_CPU_State;
171
172#endif /* defined( RTEMS_SMP ) */
173
174/**
175 * @brief Per-CPU statistics.
176 */
177typedef struct {
178#if defined( RTEMS_PROFILING )
179  /**
180   * @brief The thread dispatch disabled begin instant in CPU counter ticks.
181   *
182   * This value is used to measure the time of disabled thread dispatching.
183   */
184  CPU_Counter_ticks thread_dispatch_disabled_instant;
185
186  /**
187   * @brief The maximum time of disabled thread dispatching in CPU counter
188   * ticks.
189   */
190  CPU_Counter_ticks max_thread_dispatch_disabled_time;
191
192  /**
193   * @brief The maximum time spent to process a single sequence of nested
194   * interrupts in CPU counter ticks.
195   *
196   * This is the time interval between the change of the interrupt nest level
197   * from zero to one and the change back from one to zero.
198   */
199  CPU_Counter_ticks max_interrupt_time;
200
201  /**
202   * @brief The maximum interrupt delay in CPU counter ticks if supported by
203   * the hardware.
204   */
205  CPU_Counter_ticks max_interrupt_delay;
206
207  /**
208   * @brief Count of times when the thread dispatch disable level changes from
209   * zero to one in thread context.
210   *
211   * This value may overflow.
212   */
213  uint64_t thread_dispatch_disabled_count;
214
215  /**
216   * @brief Total time of disabled thread dispatching in CPU counter ticks.
217   *
218   * The average time of disabled thread dispatching is the total time of
219   * disabled thread dispatching divided by the thread dispatch disabled
220   * count.
221   *
222   * This value may overflow.
223   */
224  uint64_t total_thread_dispatch_disabled_time;
225
226  /**
227   * @brief Count of times when the interrupt nest level changes from zero to
228   * one.
229   *
230   * This value may overflow.
231   */
232  uint64_t interrupt_count;
233
234  /**
235   * @brief Total time of interrupt processing in CPU counter ticks.
236   *
237   * The average time of interrupt processing is the total time of interrupt
238   * processing divided by the interrupt count.
239   *
240   * This value may overflow.
241   */
242  uint64_t total_interrupt_time;
243#endif /* defined( RTEMS_PROFILING ) */
244} Per_CPU_Stats;
245
246/**
247 * @brief Per-CPU watchdog header index.
248 */
249typedef enum {
250  /**
251   * @brief Index for relative per-CPU watchdog header.
252   *
253   * The reference time point for this header is current ticks value
254   * during insert.  Time is measured in clock ticks.
255   */
256  PER_CPU_WATCHDOG_RELATIVE,
257
258  /**
259   * @brief Index for absolute per-CPU watchdog header.
260   *
261   * The reference time point for this header is the POSIX Epoch.  Time is
262   * measured in nanoseconds since POSIX Epoch.
263   */
264  PER_CPU_WATCHDOG_ABSOLUTE,
265
266  /**
267   * @brief Count of per-CPU watchdog headers.
268   */
269  PER_CPU_WATCHDOG_COUNT
270} Per_CPU_Watchdog_index;
271
272/**
273 *  @brief Per CPU Core Structure
274 *
275 *  This structure is used to hold per core state information.
276 */
277typedef struct Per_CPU_Control {
278  #if CPU_PER_CPU_CONTROL_SIZE > 0
279    /**
280     * @brief CPU port specific control.
281     */
282    CPU_Per_CPU_control cpu_per_cpu;
283  #endif
284
285  #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \
286      (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
287    /**
288     * This contains a pointer to the lower range of the interrupt stack for
289     * this CPU.  This is the address allocated and freed.
290     */
291    void  *interrupt_stack_low;
292
293    /**
294     * This contains a pointer to the interrupt stack pointer for this CPU.
295     * It will be loaded at the beginning on an ISR.
296     */
297    void  *interrupt_stack_high;
298  #endif
299
300  /**
301   *  This contains the current interrupt nesting level on this
302   *  CPU.
303   */
304  uint32_t isr_nest_level;
305
306  /**
307   * @brief Indicetes if an ISR thread dispatch is disabled.
308   *
309   * This flag is context switched with each thread.  It indicates that this
310   * thread has an interrupt stack frame on its stack.  By using this flag, we
311   * can avoid nesting more interrupt dispatching attempts on a previously
312   * interrupted thread's stack.
313   */
314  uint32_t isr_dispatch_disable;
315
316  /**
317   * @brief The thread dispatch critical section nesting counter which is used
318   * to prevent context switches at inopportune moments.
319   */
320  volatile uint32_t thread_dispatch_disable_level;
321
322  /**
323   * @brief This is set to true when this processor needs to run the thread
324   * dispatcher.
325   *
326   * It is volatile since interrupts may alter this flag.
327   *
328   * This field is not protected by a lock and must be accessed only by this
329   * processor.  Code (e.g. scheduler and post-switch action requests) running
330   * on another processors must use an inter-processor interrupt to set the
331   * thread dispatch necessary indicator to true.
332   *
333   * @see _Thread_Get_heir_and_make_it_executing().
334   */
335  volatile bool dispatch_necessary;
336
337  /**
338   * @brief This is the thread executing on this processor.
339   *
340   * This field is not protected by a lock.  The only writer is this processor.
341   *
342   * On SMP configurations a thread may be registered as executing on more than
343   * one processor in case a thread migration is in progress.  On SMP
344   * configurations use _Thread_Is_executing_on_a_processor() to figure out if
345   * a thread context is executing on a processor.
346   */
347  struct _Thread_Control *executing;
348
349  /**
350   * @brief This is the heir thread for this processor.
351   *
352   * This field is not protected by a lock.  The only writer after multitasking
353   * start is the scheduler owning this processor.  It is assumed that stores
354   * to pointers are atomic on all supported SMP architectures.  The CPU port
355   * specific code (inter-processor interrupt handling and
356   * _CPU_SMP_Send_interrupt()) must guarantee that this processor observes the
357   * last value written.
358   *
359   * A thread can be a heir on at most one processor in the system.
360   *
361   * @see _Thread_Get_heir_and_make_it_executing().
362   */
363  struct _Thread_Control *heir;
364
365#if defined(RTEMS_SMP)
366  CPU_Interrupt_frame Interrupt_frame;
367#endif
368
369  /**
370   * @brief The CPU usage timestamp contains the time point of the last heir
371   * thread change or last CPU usage update of the executing thread of this
372   * processor.
373   *
374   * Protected by the scheduler lock.
375   *
376   * @see _Scheduler_Update_heir(), _Thread_Dispatch_update_heir() and
377   * _Thread_Get_CPU_time_used().
378   */
379  Timestamp_Control cpu_usage_timestamp;
380
381  /**
382   * @brief Watchdog state for this processor.
383   */
384  struct {
385    /**
386     * @brief Protects all watchdog operations on this processor.
387     */
388    ISR_LOCK_MEMBER( Lock )
389
390    /**
391     * @brief Watchdog ticks on this processor used for relative watchdogs.
392     */
393    uint64_t ticks;
394
395    /**
396     * @brief Header for watchdogs.
397     *
398     * @see Per_CPU_Watchdog_index.
399     */
400    Watchdog_Header Header[ PER_CPU_WATCHDOG_COUNT ];
401  } Watchdog;
402
403  #if defined( RTEMS_SMP )
404    /**
405     * @brief This lock protects some parts of the low-level thread dispatching.
406     *
407     * We must use a ticket lock here since we cannot transport a local context
408     * through the context switch.
409     *
410     * @see _Thread_Dispatch().
411     */
412    SMP_ticket_lock_Control Lock;
413
414    #if defined( RTEMS_PROFILING )
415      /**
416       * @brief Lock statistics for the per-CPU lock.
417       */
418      SMP_lock_Stats Lock_stats;
419
420      /**
421       * @brief Lock statistics context for the per-CPU lock.
422       */
423      SMP_lock_Stats_context Lock_stats_context;
424    #endif
425
426    /**
427     * @brief Chain of threads in need for help.
428     *
429     * This field is protected by the Per_CPU_Control::Lock lock.
430     */
431    Chain_Control Threads_in_need_for_help;
432
433    /**
434     * @brief Bit field for SMP messages.
435     *
436     * This bit field is not protected locks.  Atomic operations are used to
437     * set and get the message bits.
438     */
439    Atomic_Ulong message;
440
441    struct {
442      /**
443       * @brief The scheduler control of the scheduler owning this processor.
444       *
445       * This pointer is NULL in case this processor is currently not used by a
446       * scheduler instance.
447       */
448      const struct Scheduler_Control *control;
449
450      /**
451       * @brief The scheduler context of the scheduler owning this processor.
452       *
453       * This pointer is NULL in case this processor is currently not used by a
454       * scheduler instance.
455       */
456      const struct Scheduler_Context *context;
457
458      /**
459       * @brief The idle thread for this processor in case it is online and
460       * currently not used by a scheduler instance.
461       */
462      struct _Thread_Control *idle_if_online_and_unused;
463    } Scheduler;
464
465    /**
466     * @brief Indicates the current state of the CPU.
467     *
468     * This field is protected by the _Per_CPU_State_lock lock.
469     *
470     * @see _Per_CPU_State_change().
471     */
472    Per_CPU_State state;
473
474    /**
475     * @brief Action to be executed by this processor in the
476     * SYSTEM_STATE_BEFORE_MULTITASKING state on behalf of the boot processor.
477     *
478     * @see _SMP_Before_multitasking_action().
479     */
480    Atomic_Uintptr before_multitasking_action;
481
482    /**
483     * @brief Indicates if the processor has been successfully started via
484     * _CPU_SMP_Start_processor().
485     */
486    bool online;
487
488    /**
489     * @brief Indicates if the processor is the one that performed the initial
490     * system initialization.
491     */
492    bool boot;
493  #endif
494
495  Per_CPU_Stats Stats;
496} Per_CPU_Control;
497
498#if defined( RTEMS_SMP )
499typedef struct {
500  Per_CPU_Control per_cpu;
501  char unused_space_for_cache_line_alignment
502    [ PER_CPU_CONTROL_SIZE - sizeof( Per_CPU_Control ) ];
503} Per_CPU_Control_envelope;
504#else
505typedef struct {
506  Per_CPU_Control per_cpu;
507} Per_CPU_Control_envelope;
508#endif
509
510/**
511 *  @brief Set of Per CPU Core Information
512 *
513 *  This is an array of per CPU core information.
514 */
515extern Per_CPU_Control_envelope _Per_CPU_Information[] CPU_STRUCTURE_ALIGNMENT;
516
517#if defined( RTEMS_SMP )
518#define _Per_CPU_Acquire( cpu ) \
519  _SMP_ticket_lock_Acquire( \
520    &( cpu )->Lock, \
521    &( cpu )->Lock_stats, \
522    &( cpu )->Lock_stats_context \
523  )
524#else
525#define _Per_CPU_Acquire( cpu ) \
526  do { \
527    (void) ( cpu ); \
528  } while ( 0 )
529#endif
530
531#if defined( RTEMS_SMP )
532#define _Per_CPU_Release( cpu ) \
533  _SMP_ticket_lock_Release( \
534    &( cpu )->Lock, \
535    &( cpu )->Lock_stats_context \
536  )
537#else
538#define _Per_CPU_Release( cpu ) \
539  do { \
540    (void) ( cpu ); \
541  } while ( 0 )
542#endif
543
544#if defined( RTEMS_SMP )
545#define _Per_CPU_ISR_disable_and_acquire( cpu, isr_cookie ) \
546  do { \
547    _ISR_Local_disable( isr_cookie ); \
548    _Per_CPU_Acquire( cpu ); \
549  } while ( 0 )
550#else
551#define _Per_CPU_ISR_disable_and_acquire( cpu, isr_cookie ) \
552  do { \
553    _ISR_Local_disable( isr_cookie ); \
554    (void) ( cpu ); \
555  } while ( 0 )
556#endif
557
558#if defined( RTEMS_SMP )
559#define _Per_CPU_Release_and_ISR_enable( cpu, isr_cookie ) \
560  do { \
561    _Per_CPU_Release( cpu ); \
562    _ISR_Local_enable( isr_cookie ); \
563  } while ( 0 )
564#else
565#define _Per_CPU_Release_and_ISR_enable( cpu, isr_cookie ) \
566  do { \
567    (void) ( cpu ); \
568    _ISR_Local_enable( isr_cookie ); \
569  } while ( 0 )
570#endif
571
572#if defined( RTEMS_SMP )
573#define _Per_CPU_Acquire_all( isr_cookie ) \
574  do { \
575    uint32_t ncpus = _SMP_Get_processor_count(); \
576    uint32_t cpu; \
577    _ISR_Local_disable( isr_cookie ); \
578    for ( cpu = 0 ; cpu < ncpus ; ++cpu ) { \
579      _Per_CPU_Acquire( _Per_CPU_Get_by_index( cpu ) ); \
580    } \
581  } while ( 0 )
582#else
583#define _Per_CPU_Acquire_all( isr_cookie ) \
584  _ISR_Local_disable( isr_cookie )
585#endif
586
587#if defined( RTEMS_SMP )
588#define _Per_CPU_Release_all( isr_cookie ) \
589  do { \
590    uint32_t ncpus = _SMP_Get_processor_count(); \
591    uint32_t cpu; \
592    for ( cpu = 0 ; cpu < ncpus ; ++cpu ) { \
593      _Per_CPU_Release( _Per_CPU_Get_by_index( cpu ) ); \
594    } \
595    _ISR_Local_enable( isr_cookie ); \
596  } while ( 0 )
597#else
598#define _Per_CPU_Release_all( isr_cookie ) \
599  _ISR_Local_enable( isr_cookie )
600#endif
601
602/*
603 * If we get the current processor index in a context which allows thread
604 * dispatching, then we may already run on another processor right after the
605 * read instruction.  There are very few cases in which this makes sense (here
606 * we can use _Per_CPU_Get_snapshot()).  All other places must use
607 * _Per_CPU_Get() so that we can add checks for RTEMS_DEBUG.
608 */
609#if defined( _CPU_Get_current_per_CPU_control )
610  #define _Per_CPU_Get_snapshot() _CPU_Get_current_per_CPU_control()
611#else
612  #define _Per_CPU_Get_snapshot() \
613    ( &_Per_CPU_Information[ _SMP_Get_current_processor() ].per_cpu )
614#endif
615
616#if defined( RTEMS_SMP )
617static inline Per_CPU_Control *_Per_CPU_Get( void )
618{
619  Per_CPU_Control *cpu_self = _Per_CPU_Get_snapshot();
620
621  _Assert(
622    cpu_self->thread_dispatch_disable_level != 0 || _ISR_Get_level() != 0
623  );
624
625  return cpu_self;
626}
627#else
628#define _Per_CPU_Get() _Per_CPU_Get_snapshot()
629#endif
630
631static inline Per_CPU_Control *_Per_CPU_Get_by_index( uint32_t index )
632{
633  return &_Per_CPU_Information[ index ].per_cpu;
634}
635
636static inline uint32_t _Per_CPU_Get_index( const Per_CPU_Control *cpu )
637{
638  const Per_CPU_Control_envelope *per_cpu_envelope =
639    ( const Per_CPU_Control_envelope * ) cpu;
640
641  return ( uint32_t ) ( per_cpu_envelope - &_Per_CPU_Information[ 0 ] );
642}
643
644static inline struct _Thread_Control *_Per_CPU_Get_executing(
645  const Per_CPU_Control *cpu
646)
647{
648  return cpu->executing;
649}
650
651static inline bool _Per_CPU_Is_processor_online(
652  const Per_CPU_Control *cpu
653)
654{
655#if defined( RTEMS_SMP )
656  return cpu->online;
657#else
658  (void) cpu;
659
660  return true;
661#endif
662}
663
664static inline bool _Per_CPU_Is_boot_processor(
665  const Per_CPU_Control *cpu
666)
667{
668#if defined( RTEMS_SMP )
669  return cpu->boot;
670#else
671  (void) cpu;
672
673  return true;
674#endif
675}
676
677#if defined( RTEMS_SMP )
678
679/**
680 *  @brief Allocate and Initialize Per CPU Structures
681 *
682 *  This method allocates and initialize the per CPU structure.
683 */
684void _Per_CPU_Initialize(void);
685
686void _Per_CPU_State_change(
687  Per_CPU_Control *cpu,
688  Per_CPU_State new_state
689);
690
691/**
692 * @brief Waits for a processor to change into a non-initial state.
693 *
694 * This function should be called only in _CPU_SMP_Start_processor() if
695 * required by the CPU port or BSP.
696 *
697 * @code
698 * bool _CPU_SMP_Start_processor(uint32_t cpu_index)
699 * {
700 *   uint32_t timeout = 123456;
701 *
702 *   start_the_processor(cpu_index);
703 *
704 *   return _Per_CPU_State_wait_for_non_initial_state(cpu_index, timeout);
705 * }
706 * @endcode
707 *
708 * @param[in] cpu_index The processor index.
709 * @param[in] timeout_in_ns The timeout in nanoseconds.  Use a value of zero to
710 * wait forever if necessary.
711 *
712 * @retval true The processor is in a non-initial state.
713 * @retval false The timeout expired before the processor reached a non-initial
714 * state.
715 */
716bool _Per_CPU_State_wait_for_non_initial_state(
717  uint32_t cpu_index,
718  uint32_t timeout_in_ns
719);
720
721#endif /* defined( RTEMS_SMP ) */
722
723/*
724 * On a non SMP system, the _SMP_Get_current_processor() is defined to 0.
725 * Thus when built for non-SMP, there should be no performance penalty.
726 */
727#define _Thread_Dispatch_disable_level \
728  _Per_CPU_Get()->thread_dispatch_disable_level
729#define _Thread_Heir \
730  _Per_CPU_Get()->heir
731
732#if defined(_CPU_Get_thread_executing)
733#define _Thread_Executing \
734  _CPU_Get_thread_executing()
735#else
736#define _Thread_Executing \
737  _Per_CPU_Get_executing( _Per_CPU_Get() )
738#endif
739
740#define _ISR_Nest_level \
741  _Per_CPU_Get()->isr_nest_level
742#define _CPU_Interrupt_stack_low \
743  _Per_CPU_Get()->interrupt_stack_low
744#define _CPU_Interrupt_stack_high \
745  _Per_CPU_Get()->interrupt_stack_high
746#define _Thread_Dispatch_necessary \
747  _Per_CPU_Get()->dispatch_necessary
748
749/**
750 * @brief Returns the thread control block of the executing thread.
751 *
752 * This function can be called in any thread context.  On SMP configurations,
753 * interrupts are disabled to ensure that the processor index is used
754 * consistently if no CPU port specific method is available to get the
755 * executing thread.
756 *
757 * @return The thread control block of the executing thread.
758 */
759RTEMS_INLINE_ROUTINE struct _Thread_Control *_Thread_Get_executing( void )
760{
761  struct _Thread_Control *executing;
762
763  #if defined(RTEMS_SMP) && !defined(_CPU_Get_thread_executing)
764    ISR_Level level;
765
766    _ISR_Local_disable( level );
767  #endif
768
769  executing = _Thread_Executing;
770
771  #if defined(RTEMS_SMP) && !defined(_CPU_Get_thread_executing)
772    _ISR_Local_enable( level );
773  #endif
774
775  return executing;
776}
777
778/**@}*/
779
780#endif /* !defined( ASM ) */
781
782#if defined( ASM ) || defined( _RTEMS_PERCPU_DEFINE_OFFSETS )
783
784#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \
785    (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
786  /*
787   *  If this CPU target lets RTEMS allocates the interrupt stack, then
788   *  we need to have places in the per CPU table to hold them.
789   */
790  #define PER_CPU_INTERRUPT_STACK_LOW \
791    CPU_PER_CPU_CONTROL_SIZE
792  #define PER_CPU_INTERRUPT_STACK_HIGH \
793    PER_CPU_INTERRUPT_STACK_LOW + CPU_SIZEOF_POINTER
794  #define PER_CPU_END_STACK             \
795    PER_CPU_INTERRUPT_STACK_HIGH + CPU_SIZEOF_POINTER
796
797  #define INTERRUPT_STACK_LOW \
798    (SYM(_Per_CPU_Information) + PER_CPU_INTERRUPT_STACK_LOW)
799  #define INTERRUPT_STACK_HIGH \
800    (SYM(_Per_CPU_Information) + PER_CPU_INTERRUPT_STACK_HIGH)
801#else
802  #define PER_CPU_END_STACK \
803    CPU_PER_CPU_CONTROL_SIZE
804#endif
805
806/*
807 *  These are the offsets of the required elements in the per CPU table.
808 */
809#define PER_CPU_ISR_NEST_LEVEL \
810  PER_CPU_END_STACK
811#define PER_CPU_ISR_DISPATCH_DISABLE \
812  PER_CPU_ISR_NEST_LEVEL + 4
813#define PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL \
814  PER_CPU_ISR_DISPATCH_DISABLE + 4
815#define PER_CPU_DISPATCH_NEEDED \
816  PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL + 4
817#define PER_CPU_OFFSET_EXECUTING \
818  PER_CPU_DISPATCH_NEEDED + 4
819#define PER_CPU_OFFSET_HEIR \
820  PER_CPU_OFFSET_EXECUTING + CPU_SIZEOF_POINTER
821#if defined(RTEMS_SMP)
822#define PER_CPU_INTERRUPT_FRAME_AREA \
823  PER_CPU_OFFSET_HEIR + CPU_SIZEOF_POINTER
824#endif
825
826#define THREAD_DISPATCH_DISABLE_LEVEL \
827  (SYM(_Per_CPU_Information) + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)
828#define ISR_NEST_LEVEL \
829  (SYM(_Per_CPU_Information) + PER_CPU_ISR_NEST_LEVEL)
830#define DISPATCH_NEEDED \
831  (SYM(_Per_CPU_Information) + PER_CPU_DISPATCH_NEEDED)
832
833#endif /* defined( ASM ) || defined( _RTEMS_PERCPU_DEFINE_OFFSETS ) */
834
835#ifdef __cplusplus
836}
837#endif
838
839#endif
840/* end of include file */
Note: See TracBrowser for help on using the repository browser.