]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - include/linux/preempt.h
Merge remote-tracking branch 'tegra/for-next'
[karo-tx-linux.git] / include / linux / preempt.h
index f5d4723cdb3d3e6ab30d5af02d1eaadbdc7d0ee3..a3d9dc8c2c006a02cd7677a6e4a6ac10dac69910 100644 (file)
  * preempt_count (used for kernel preemption, interrupt count, etc.)
  */
 
-#include <linux/thread_info.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 
-#if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER)
-  extern void add_preempt_count(int val);
-  extern void sub_preempt_count(int val);
-#else
-# define add_preempt_count(val)        do { preempt_count() += (val); } while (0)
-# define sub_preempt_count(val)        do { preempt_count() -= (val); } while (0)
-#endif
-
-#define inc_preempt_count() add_preempt_count(1)
-#define dec_preempt_count() sub_preempt_count(1)
-
-#define preempt_count()        (current_thread_info()->preempt_count)
-
-#ifdef CONFIG_PREEMPT
-
-asmlinkage void preempt_schedule(void);
-
-#define preempt_check_resched() \
-do { \
-       if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
-               preempt_schedule(); \
-} while (0)
-
-#ifdef CONFIG_CONTEXT_TRACKING
+/*
+ * We use the MSB mostly because its available; see <linux/preempt_mask.h> for
+ * the other bits -- can't include that header due to inclusion hell.
+ */
+#define PREEMPT_NEED_RESCHED   0x80000000
 
-void preempt_schedule_context(void);
+#include <asm/preempt.h>
 
-#define preempt_check_resched_context() \
-do { \
-       if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
-               preempt_schedule_context(); \
-} while (0)
+#if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER)
+extern void preempt_count_add(int val);
+extern void preempt_count_sub(int val);
+#define preempt_count_dec_and_test() ({ preempt_count_sub(1); should_resched(); })
 #else
+#define preempt_count_add(val) __preempt_count_add(val)
+#define preempt_count_sub(val) __preempt_count_sub(val)
+#define preempt_count_dec_and_test() __preempt_count_dec_and_test()
+#endif
 
-#define preempt_check_resched_context() preempt_check_resched()
-
-#endif /* CONFIG_CONTEXT_TRACKING */
-
-#else /* !CONFIG_PREEMPT */
-
-#define preempt_check_resched()                do { } while (0)
-#define preempt_check_resched_context()        do { } while (0)
-
-#endif /* CONFIG_PREEMPT */
+#define __preempt_count_inc() __preempt_count_add(1)
+#define __preempt_count_dec() __preempt_count_sub(1)
 
+#define preempt_count_inc() preempt_count_add(1)
+#define preempt_count_dec() preempt_count_sub(1)
 
 #ifdef CONFIG_PREEMPT_COUNT
 
 #define preempt_disable() \
 do { \
-       inc_preempt_count(); \
+       preempt_count_inc(); \
        barrier(); \
 } while (0)
 
 #define sched_preempt_enable_no_resched() \
 do { \
        barrier(); \
-       dec_preempt_count(); \
+       preempt_count_dec(); \
 } while (0)
 
-#define preempt_enable_no_resched()    sched_preempt_enable_no_resched()
+#define preempt_enable_no_resched() sched_preempt_enable_no_resched()
 
+#ifdef CONFIG_PREEMPT
 #define preempt_enable() \
 do { \
-       preempt_enable_no_resched(); \
        barrier(); \
-       preempt_check_resched(); \
+       if (unlikely(preempt_count_dec_and_test())) \
+               __preempt_schedule(); \
+} while (0)
+
+#define preempt_check_resched() \
+do { \
+       if (should_resched()) \
+               __preempt_schedule(); \
 } while (0)
 
-/* For debugging and tracer internals only! */
-#define add_preempt_count_notrace(val)                 \
-       do { preempt_count() += (val); } while (0)
-#define sub_preempt_count_notrace(val)                 \
-       do { preempt_count() -= (val); } while (0)
-#define inc_preempt_count_notrace() add_preempt_count_notrace(1)
-#define dec_preempt_count_notrace() sub_preempt_count_notrace(1)
+#else
+#define preempt_enable() preempt_enable_no_resched()
+#define preempt_check_resched() do { } while (0)
+#endif
 
 #define preempt_disable_notrace() \
 do { \
-       inc_preempt_count_notrace(); \
+       __preempt_count_inc(); \
        barrier(); \
 } while (0)
 
 #define preempt_enable_no_resched_notrace() \
 do { \
        barrier(); \
-       dec_preempt_count_notrace(); \
+       __preempt_count_dec(); \
 } while (0)
 
-/* preempt_check_resched is OK to trace */
+#ifdef CONFIG_PREEMPT
+
+#ifndef CONFIG_CONTEXT_TRACKING
+#define __preempt_schedule_context() __preempt_schedule()
+#endif
+
 #define preempt_enable_notrace() \
 do { \
-       preempt_enable_no_resched_notrace(); \
        barrier(); \
-       preempt_check_resched_context(); \
+       if (unlikely(__preempt_count_dec_and_test())) \
+               __preempt_schedule_context(); \
 } while (0)
+#else
+#define preempt_enable_notrace() preempt_enable_no_resched_notrace()
+#endif
 
 #else /* !CONFIG_PREEMPT_COUNT */
 
@@ -115,10 +104,11 @@ do { \
  * that can cause faults and scheduling migrate into our preempt-protected
  * region.
  */
-#define preempt_disable()              barrier()
+#define preempt_disable()                      barrier()
 #define sched_preempt_enable_no_resched()      barrier()
-#define preempt_enable_no_resched()    barrier()
-#define preempt_enable()               barrier()
+#define preempt_enable_no_resched()            barrier()
+#define preempt_enable()                       barrier()
+#define preempt_check_resched()                        do { } while (0)
 
 #define preempt_disable_notrace()              barrier()
 #define preempt_enable_no_resched_notrace()    barrier()