critical section Linux内核同步 - spin_lock(9)

电脑杂谈  发布时间:2018-02-14 08:19:43  来源:网络整理

#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

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 綦毋诚
      綦毋诚

      这是教育体制落后的具体体现

    • 赵孟坚
      赵孟坚

      希望能有所帮助

    • 郑轨
      郑轨

      这样的“优质资源”当然他自己享受了

    热点图片
    拼命载入中...