Why a “barrier()” is enough for disabling or enabling the preemption?
Hi all, Below is the preemption disable/enable code: #ifdef CONFIG_PREEMPT_COUNT #define preempt_disable() \ do { \ inc_preempt_count(); \ barrier(); \ } while (0) ...... #define preempt_enable() \ do { \ preempt_enable_no_resched(); \ barrier(); \ preempt_check_resched(); \ } while (0) #else /* !CONFIG_PREEMPT_COUNT */ /* * Even if we don't have any preemption, we need preempt disable/enable * to be barriers, so that we don't have things like get_user/put_user * that can cause faults and scheduling migrate into our preempt-protected * region. */ #define preempt_disable() barrier() ...... #define preempt_enable() barrier() ...... #endif /* CONFIG_PREEMPT_COUNT */ And I have a question about it:If the CONFIG_PREEMPT_COUNT is OFF, while CONFIG_PREEMPT is ON, why only a barrier()can disable/enable preemption? What is the magic behind it? Or On SMP, the CONFIG_PREEMPT_COUNT should always be ON? BTW, I also post this issue on SO(http://stackoverflow.com/questions/33864903/why-a-barrier-is-enough-for-disa...), but can't receive clear answers. Thanks in advance! Best Regards Nan Xiao
#define preempt_disable() barrier() ...... #define preempt_enable() barrier()
Let me try answering this with a limited knowledge I have about barriers. barrier() essentially was added so that compiler reordering does not happen. In the code above, since the compiler does not know/understand the specialty of preempt_[enable/disable], the compiler might decide to change the ordering. In this case, where the code is disabling/enabling preemption, barrier() tells the compiler that it can't move stuff around. I hope this helps. - Doug
participants (2)
-
Doug Wilson -
Nan Xiao