msleep 不能用在atomic context,但是mdelay 可以

在atomic context环境中不能调用msleep等函数,atomic context基本就是中断或者被spin_lock/spin_unlock等包起来的部分,我们先看看msleep 为啥在atomic context中使用
void msleep(unsigned int msecs)
{
    unsigned long timeout = msecs_to_jiffies(msecs) + 1;

    while (timeout)
        timeout = schedule_timeout_uninterruptible(timeout);
}
原来是调用schedule_timeout_uninterruptible
signed long __sched schedule_timeout_uninterruptible(signed long timeout)
{
    __set_current_state(TASK_UNINTERRUPTIBLE);
    return schedule_timeout(timeout);
}
在schedule_timeout_uninterruptible->__schedule->schedule_debug 最终会出现 BUG: scheduling while atomic经典bug 这样经典的bug
但是如果真的要在atomic context delay该怎么办呢?答案是可以调用mdelay函数
#ifndef mdelay
#define mdelay(n) (\
    (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
    ({unsigned long __ms=(n); while (__ms--) udelay(1000);}))
这里都是调用udelay
#define udelay(n)                            \
    ({                                \
        if (__builtin_constant_p(n)) {                \
            if ((n) / 20000 >= 1)                \
                 __bad_udelay();            \
            else                        \
                __const_udelay((n) * 0x10c7ul);        \
        } else {                        \
            __udelay(n);                    \
        }                            \
    })
加入走else的case
void __udelay(unsigned long usecs)
{
    __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
}
可见最终也是调用__const_udelay
static inline void cpu_relax(void)
{
    asm volatile("yield" ::: "memory");
}

void __delay(unsigned long cycles)
{
    cycles_t start = get_cycles();

    while ((get_cycles() - start) < cycles)
        cpu_relax();
}
EXPORT_SYMBOL(__delay);

inline void __const_udelay(unsigned long xloops)
{
    unsigned long loops;

    loops = xloops * loops_per_jiffy * HZ;
    __delay(loops >> 32);
}

原来最终是调用cpu_relax 啊,所以说mdelay可以用在atomic context环境中


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值