关于时钟(2)以及定时器精度问题

在应用层,使用timeout是做不到延迟微秒级别,甚至在很多架构上,连ms都做不多,为什么这样说,线索如下:


            timeout = ROUND_UP(usec, 1000000/HZ);
            timeout += sec * (unsigned long) HZ;


#define ROUND_UP(x,y) (((x)+(y)-1)/(y)),这里假设sec为0。


在x86,hz为100,当usec<10000,也就是小于10ms的时候,在kernel里面,会认为,是一个10ms的timeout,也就是一个hz(一个时钟中断),所以精度只能到达10ms。

通过函数schedule_timeout,把进程主动调度出去,schedule()。


在kernel里面使用的udelay是完全不一样,

udelay 通过下面的来实现:

udelay函数通过BogoMIPS实现。Bogo的意思是Bogus,MIPS的意思是每秒百万条指令(million of instructions per second)
BogoMIPS纪录处理器在给定时间内忙循环执行的次数(该值存放在loops_per_jiffy),所以udelay函数仅仅需要根据指定时间在1秒所占的比例,就可以知道执行多少次循环能达到要求的推迟时间。


inline void __const_udelay( unsigned long xloops)
{
    int d0;

    xloops * = 4;

    /* 这段汇编取出每CPU的loops_per_jiffy的值,*/

    /* 乘上HZ表示每秒执行的指令条数,最后与xloops相乘 */

    /* 乘法会溢出,将高32bit放入寄存器edx,将低32bit的值放入寄存器eax */

    /* xloops保留了高32bit的值 */
    __asm__ ( "mull %0"
        : "=d" ( xloops) , "=&a" ( d0)
        : "1" ( xloops) , "0"
        ( cpu_data[ raw_smp_processor_id( ) ] . loops_per_jiffy * ( HZ/ 4) ) ) ;

    /* 调用__delay函数,这里之所以要再++,我估计是弥补低32bit的精度损失 */
    __delay( + + xloops) ;
}

void __udelay( unsigned long usecs)
{

    /* 微妙换算成秒,数值太小,乘上2**32,即左移32bit */
    __const_udelay( usecs * 0x000010c7) ; /* 2**32 / 1000000 (rounded up) */
}

 

static void delay_loop( unsigned long loops)
{
    int d0;

    __asm__ __volatile__(
        "/tjmp 1f/n"
        ".align 16/n"
        "1:/tjmp 2f/n"
        ".align 16/n"
        "2:/tdecl %0/n/tjns 2b"
        : "=&a" ( d0)
        : "0" ( loops) ) ;
}

static void ( * delay_fn) ( unsigned long ) = delay_loop;

void __delay( unsigned long loops)
{
    delay_fn( loops) ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值