#define _raw_spin_lock(lock) __LOCK(lock)
/*
* In the UP-nondebug case there‘s no real locking going on, so the
* only thing we have to do is to keep the preempt counts and irq
* flags straight, to suppress compiler warnings of unused lock
* variables, and to add the proper checker annotations:
*/
#define __LOCK(lock) \
do { preempt_disable(); __acquire(lock); (void)(lock); } while (0)
#define preempt_disable() \
do { \
preempt_count_inc(); \
barrier(); \
} while (0)
由以上代码可知,UP下spin_lock仅仅是禁用了内核抢占,而此时IRQ是可以正常触发的。那就先考虑tick中断——即,UP下,持有spin_lock的进程会被调度器切走么?
1)UP下,spin_lock() 是不会失败的, 但spin_lock() 保护的临界代码还是需要一定时间执行的,这期间内核抢占被禁止,那当前进程有可能被切走么?
先假设CFS(先假设调度器用的是CFS)在禁止内核抢占的情况下不会将当前进程切走,那么,仅仅禁用内核抢占可以保证临界区代码不会被进程上下文重入;如果,CFS并不理会抢占计数,会强制剥夺当前进程的CPU使用权,那么就存在spin_lock()保护的临界区代码被进程上下文重入的问题。
2)再考虑,spin_lock() 临界区被中断上下文重入的问题。
以上两点,都不会造成死锁或者CPU Halt, 因为UP下spin_lock()没有进行锁等待,所以存在的就只是代码重入问题,也即,即便用spin_lock()进行保护,这段代码还是有被重入的可能。
那问题已经提出来了,就看看代码如何实现?先看CFS的周期调度代码,如下代码确认当前进程是否需要重新调度:
static void check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
{
....
ideal_runtime = sched_slice(cfs_rq, curr);
/*
* 计算该进程的预期运行时间:
*
*当cfs_rq中的运行进程不大于sched_nr_latency(8)时,各个进程的ideal_runtime是一个常量
*之所以是常量,是因为period是常量(sysctl_sched_latency=6000000)。
*当cfs_rq中的运行进程大于sched_nr_latency时,period = nr_running * sysctl_sched_min_granularity;
*其中,sysctl_sched_min_granularity是750000.
*ideal_runtime *= period * weight/load;
*/
if (delta_exec > ideal_runtime)
{
//delta_exec 实际运行的时间已经超过其预计运行时间,
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-77053-9.html
希望能有所帮助
这样的“优质资源”当然他自己享受了
这是教育体制落后的具体体现