LCOV - code coverage report
Current view: top level - include/linux - hardirq.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4 4 100.0 %
Date: 2017-01-25 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef LINUX_HARDIRQ_H
       2             : #define LINUX_HARDIRQ_H
       3             : 
       4             : #include <linux/preempt.h>
       5             : #ifdef CONFIG_PREEMPT
       6             : #include <linux/smp_lock.h>
       7             : #endif
       8             : #include <linux/lockdep.h>
       9             : #include <linux/ftrace_irq.h>
      10             : #include <asm/hardirq.h>
      11             : #include <asm/system.h>
      12             : 
      13             : /*
      14             :  * We put the hardirq and softirq counter into the preemption
      15             :  * counter. The bitmask has the following meaning:
      16             :  *
      17             :  * - bits 0-7 are the preemption count (max preemption depth: 256)
      18             :  * - bits 8-15 are the softirq count (max # of softirqs: 256)
      19             :  *
      20             :  * The hardirq count can in theory reach the same as NR_IRQS.
      21             :  * In reality, the number of nested IRQS is limited to the stack
      22             :  * size as well. For archs with over 1000 IRQS it is not practical
      23             :  * to expect that they will all nest. We give a max of 10 bits for
      24             :  * hardirq nesting. An arch may choose to give less than 10 bits.
      25             :  * m68k expects it to be 8.
      26             :  *
      27             :  * - bits 16-25 are the hardirq count (max # of nested hardirqs: 1024)
      28             :  * - bit 26 is the NMI_MASK
      29             :  * - bit 28 is the PREEMPT_ACTIVE flag
      30             :  *
      31             :  * PREEMPT_MASK: 0x000000ff
      32             :  * SOFTIRQ_MASK: 0x0000ff00
      33             :  * HARDIRQ_MASK: 0x03ff0000
      34             :  *     NMI_MASK: 0x04000000
      35             :  */
      36             : #define PREEMPT_BITS    8
      37             : #define SOFTIRQ_BITS    8
      38             : #define NMI_BITS        1
      39             : 
      40             : #define MAX_HARDIRQ_BITS 10
      41             : 
      42             : #ifndef HARDIRQ_BITS
      43             : # define HARDIRQ_BITS   MAX_HARDIRQ_BITS
      44             : #endif
      45             : 
      46             : #if HARDIRQ_BITS > MAX_HARDIRQ_BITS
      47             : #error HARDIRQ_BITS too high!
      48             : #endif
      49             : 
      50             : #define PREEMPT_SHIFT   0
      51             : #define SOFTIRQ_SHIFT   (PREEMPT_SHIFT + PREEMPT_BITS)
      52             : #define HARDIRQ_SHIFT   (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
      53             : #define NMI_SHIFT       (HARDIRQ_SHIFT + HARDIRQ_BITS)
      54             : 
      55             : #define __IRQ_MASK(x)   ((1UL << (x))-1)
      56             : 
      57             : #define PREEMPT_MASK    (__IRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
      58             : #define SOFTIRQ_MASK    (__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
      59             : #define HARDIRQ_MASK    (__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
      60             : #define NMI_MASK        (__IRQ_MASK(NMI_BITS)     << NMI_SHIFT)
      61             : 
      62             : #define PREEMPT_OFFSET  (1UL << PREEMPT_SHIFT)
      63             : #define SOFTIRQ_OFFSET  (1UL << SOFTIRQ_SHIFT)
      64             : #define HARDIRQ_OFFSET  (1UL << HARDIRQ_SHIFT)
      65             : #define NMI_OFFSET      (1UL << NMI_SHIFT)
      66             : 
      67             : #ifndef PREEMPT_ACTIVE
      68             : #define PREEMPT_ACTIVE_BITS     1
      69             : #define PREEMPT_ACTIVE_SHIFT    (NMI_SHIFT + NMI_BITS)
      70             : #define PREEMPT_ACTIVE  (__IRQ_MASK(PREEMPT_ACTIVE_BITS) << PREEMPT_ACTIVE_SHIFT)
      71             : #endif
      72             : 
      73             : #if PREEMPT_ACTIVE < (1 << (NMI_SHIFT + NMI_BITS))
      74             : #error PREEMPT_ACTIVE is too low!
      75             : #endif
      76             : 
      77             : #define hardirq_count() (preempt_count() & HARDIRQ_MASK)
      78             : #define softirq_count() (preempt_count() & SOFTIRQ_MASK)
      79             : #define irq_count()     (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK \
      80             :                                  | NMI_MASK))
      81             : 
      82             : /*
      83             :  * Are we doing bottom half or hardware interrupt processing?
      84             :  * Are we in a softirq context? Interrupt context?
      85             :  */
      86             : #define in_irq()                (hardirq_count())
      87             : #define in_softirq()            (softirq_count())
      88             : #define in_interrupt()          (irq_count())
      89             : 
      90             : /*
      91             :  * Are we in NMI context?
      92             :  */
      93             : #define in_nmi()        (preempt_count() & NMI_MASK)
      94             : 
      95             : #if defined(CONFIG_PREEMPT)
      96             : # define PREEMPT_INATOMIC_BASE kernel_locked()
      97             : # define PREEMPT_CHECK_OFFSET 1
      98             : #else
      99             : # define PREEMPT_INATOMIC_BASE 0
     100             : # define PREEMPT_CHECK_OFFSET 0
     101             : #endif
     102             : 
     103             : /*
     104             :  * Are we running in atomic context?  WARNING: this macro cannot
     105             :  * always detect atomic context; in particular, it cannot know about
     106             :  * held spinlocks in non-preemptible kernels.  Thus it should not be
     107             :  * used in the general case to determine whether sleeping is possible.
     108             :  * Do not use in_atomic() in driver code.
     109             :  */
     110             : #define in_atomic()     ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_INATOMIC_BASE)
     111             : 
     112             : /*
     113             :  * Check whether we were atomic before we did preempt_disable():
     114             :  * (used by the scheduler, *after* releasing the kernel lock)
     115             :  */
     116             : #define in_atomic_preempt_off() \
     117             :                 ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET)
     118             : 
     119             : #ifdef CONFIG_PREEMPT
     120             : # define preemptible()  (preempt_count() == 0 && !irqs_disabled())
     121             : # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
     122             : #else
     123             : # define preemptible()  0
     124             : # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
     125             : #endif
     126             : 
     127             : #if defined(CONFIG_SMP) || defined(CONFIG_GENERIC_HARDIRQS)
     128             : extern void synchronize_irq(unsigned int irq);
     129             : #else
     130             : # define synchronize_irq(irq)   barrier()
     131             : #endif
     132             : 
     133             : struct task_struct;
     134             : 
     135             : #ifndef CONFIG_VIRT_CPU_ACCOUNTING
     136             : static inline void account_system_vtime(struct task_struct *tsk)
     137             : {
     138             : }
     139             : #endif
     140             : 
     141             : #if defined(CONFIG_NO_HZ)
     142             : #if defined(CONFIG_TINY_RCU)
     143             : extern void rcu_enter_nohz(void);
     144             : extern void rcu_exit_nohz(void);
     145             : 
     146             : static inline void rcu_irq_enter(void)
     147             : {
     148             :         rcu_exit_nohz();
     149             : }
     150             : 
     151             : static inline void rcu_irq_exit(void)
     152             : {
     153             :         rcu_enter_nohz();
     154             : }
     155             : 
     156             : static inline void rcu_nmi_enter(void)
     157             : {
     158             : }
     159             : 
     160             : static inline void rcu_nmi_exit(void)
     161             : {
     162             : }
     163             : 
     164             : #else
     165             : extern void rcu_irq_enter(void);
     166             : extern void rcu_irq_exit(void);
     167             : extern void rcu_nmi_enter(void);
     168             : extern void rcu_nmi_exit(void);
     169             : #endif
     170             : #else
     171             : # define rcu_irq_enter() do { } while (0)
     172             : # define rcu_irq_exit() do { } while (0)
     173             : # define rcu_nmi_enter() do { } while (0)
     174             : # define rcu_nmi_exit() do { } while (0)
     175             : #endif /* #if defined(CONFIG_NO_HZ) */
     176             : 
     177             : /*
     178             :  * It is safe to do non-atomic ops on ->hardirq_context,
     179             :  * because NMI handlers may not preempt and the ops are
     180             :  * always balanced, so the interrupted value of ->hardirq_context
     181             :  * will always be restored.
     182             :  */
     183             : #define __irq_enter()                                   \
     184             :         do {                                            \
     185             :                 account_system_vtime(current);          \
     186             :                 add_preempt_count(HARDIRQ_OFFSET);      \
     187             :                 trace_hardirq_enter();                  \
     188             :         } while (0)
     189             : 
     190             : /*
     191             :  * Enter irq context (on NO_HZ, update jiffies):
     192             :  */
     193             : extern void irq_enter(void);
     194             : 
     195             : /*
     196             :  * Exit irq context without processing softirqs:
     197             :  */
     198             : #define __irq_exit()                                    \
     199             :         do {                                            \
     200             :                 trace_hardirq_exit();                   \
     201             :                 account_system_vtime(current);          \
     202             :                 sub_preempt_count(HARDIRQ_OFFSET);      \
     203             :         } while (0)
     204             : 
     205             : /*
     206             :  * Exit irq context and process softirqs if needed:
     207             :  */
     208             : extern void irq_exit(void);
     209           1 : 
     210           1 : #define nmi_enter()                                             \
     211             :         do {                                                    \
     212             :                 ftrace_nmi_enter();                             \
     213             :                 BUG_ON(in_nmi());                               \
     214             :                 add_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \
     215             :                 lockdep_off();                                  \
     216             :                 rcu_nmi_enter();                                \
     217             :                 trace_hardirq_enter();                          \
     218             :         } while (0)
     219           1 : 
     220             : #define nmi_exit()                                              \
     221             :         do {                                                    \
     222             :                 trace_hardirq_exit();                           \
     223             :                 rcu_nmi_exit();                                 \
     224           1 :                 lockdep_on();                                   \
     225             :                 BUG_ON(!in_nmi());                              \
     226             :                 sub_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \
     227             :                 ftrace_nmi_exit();                              \
     228             :         } while (0)
     229             : 
     230             : #endif /* LINUX_HARDIRQ_H */

Generated by: LCOV version 1.10