进程调度API之preempt_count_dec_and_test
2017-12-11 09:24
423 查看
preempt_count_dec_and_test()用于判断当前thread的preempt_count是否零从而决定当前thread是否可以被抢占 其使用的例子如下: #define preempt_enable() \ do { \ barrier(); \ if (unlikely(preempt_count_dec_and_test())) \ __preempt_schedule(); \ } while (0) 可以看到如果preempt_count_dec_and_test 如果返回true的话,则说明当前thread 可以被抢占 其源码分析如下: #if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER) #define preempt_count_dec_and_test() \ ({ preempt_count_sub(1); should_resched(0); }) #else #define preempt_count_dec_and_test() __preempt_count_dec_and_test() #endif 假定我们这里没有定义CONFIG_DEBUG_PREEMPT 或者 CONFIG_PREEMPT_TRACER。这两个是用于preempt debug的 一般情况下也不开. static __always_inline bool __preempt_count_dec_and_test(void) { /* * Because of load-store architectures cannot do per-cpu atomic * operations; we cannot use PREEMPT_NEED_RESCHED because it might get * lost. */ return !--*preempt_count_ptr() && tif_need_resched(); } 这里解释了为啥不能用PREEMPT_NEED_RESCHED来判断当前thread可以被抢占,原因是load-store 表示原子 操作,因此PREEMPT_NEED_RESCHED 可能被丢失掉. 在__preempt_count_dec_and_test 中首先通过preempt_count_ptr 减一来判断preempt是否为零 static __always_inline volatile int *preempt_count_ptr(void) { return ¤t_thread_info()->preempt_count; } 也就是读取当前thread的preempt_count 后减一,看是否为零 其次调用tif_need_resched 看当前thread是否置位TIF_NEED_RESCHED #define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED) 这里又是通过宏test_thread_flag 来判断是否置位TIF_NEED_RESCHED #define test_thread_flag(flag) \ test_ti_thread_flag(current_thread_info(), flag) 这里在test_ti_thread_flag 首先通过current_thread_info 拿到当前thraed的thread_info,然后 判断thread_info 中是否置位TIF_NEED_RESCHED static inline int test_ti_thread_flag(struct thread_info *ti, int flag) { return test_bit(flag, (unsigned long *)&ti->flags); } 所以总结一下:preempt_count_dec_and_test 用于判断当前thread是否可以被抢占,要被抢占的话 必须满足两个调价,一个是preempt为零,第二个是必须置位TIF_NEED_RESCHED
相关文章推荐
- 进程调度API之preempt_count_add/preempt_count_sub
- 进程调度API之preempt_count_add(val)/preempt_count_sub(val)
- 进程调度API之preempt_schedule
- 进程调度API之preempt_notifier_register/preempt_notifier_unregister
- 进程调度API之sleep_on_spinunlock
- 进程调度API之task_cpu
- Linux 设备驱动--- 并发 与 竞态 --- atomic_t --- atomic_dec_and_test --- 原子操作
- 进程调度API之__wake_up_sync
- 进程调度API之should_resched
- 进程调度API之set_user_nice
- linux内核的preempt抢占调度,preempt_count抢占保护“锁”
- 进程调度API之prepare_to_wait/prepare_to_wait_exclusive
- 进程调度API之wait_for_completion_x
- 进程调度API之__wake_up
- 进程调度API之add_wait_queue/remove_wait_queue
- 进程调度API之add_wait_queue_exclusive
- 进程调度API之complete
- 进程调度API之finish_wait
- 进程调度API之yield
- Linux 设备驱动--- 并发 与 竞态 --- atomic_t --- atomic_dec_and_test --- 原子操作