hongmingjian / epos

《操作系统原理》实验操作系统
61 stars 20 forks source link

BUG in kernel/timer.c 乘法溢出 #4

Closed hyuuko1 closed 4 years ago

hyuuko1 commented 4 years ago

做实验二的时候发现以下代码出了问题: https://github.com/hongmingjian/epos/blob/a55c8dfc8fb0b09996f20327e869c475f2d7c197/kernel/timer.c#L128-L134

其中的loops_per_tick * num溢出。

修改为:

/* Busy-wait for approximately NUM/DENOM seconds. */
static void _delay (unsigned num, unsigned denom)
{
  /* Scale the numerator and denominator down by 1000 to avoid
     the possibility of overflow. */
  busy_wait (loops_per_tick / (denom / 1000) * num / 1000 * HZ);
}

可解决问题

hongmingjian commented 4 years ago

谢谢!怎么调用的时候发现溢出了?

hyuuko1 commented 4 years ago

_delay函数改成:

/* Busy-wait for approximately NUM/DENOM seconds. */
static void _delay(unsigned num, unsigned denom)
{
  /* Scale the numerator and denominator down by 1000 to avoid
     the possibility of overflow. */

  int overflow = loops_per_tick * num / 1000 * HZ / (denom / 1000);
  int not_overflow = loops_per_tick / (denom / 1000) * num / 1000 * HZ;

  printk("\n overflow: %d", overflow);
  printk("\n not overflow: %d\n", not_overflow);

  //busy_wait (loops_per_tick / (denom / 1000) * num / 1000 * HZ);
}

main函数中调用nanosleep

void main(void* pv) {
    printf("task #%d: I'm the first user task(pv=0x%08x)!\r\n", task_getid(), pv);

    // TODO: Your code goes here
    struct timespec ts = { 0, 5000000 }; // 5 毫秒
    nanosleep(&ts, NULL);

    while (1)
        ;
    task_exit(0);
}

输出: image

hongmingjian commented 4 years ago

加个括号,这样还会溢出吗?loops_per_tick (num / 1000) HZ / (denom / 1000);

hyuuko1 commented 4 years ago

会,我的机器上loops_per_tick大概等于7*10^7,num为5*10^6loops_per_tick * (num / 1000)的结果就是3.5*10^11,超出了unsigned int的最大值4,294,967,296‬

hyuuko1 commented 4 years ago

linux-1.2.0是这样处理a*b*c的:

extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
{
    __asm__("mull %1 ; divl %2"
        :"=a" (a)
        :"d" (b),
         "r" (c),
         "0" (a)
        :"dx");
    return a;
}
hongmingjian commented 4 years ago

哦。那我在你的基础上,改为loops_per_tick / (denom / 1000) (num / 1000) HZ;应该也可以吧?

hyuuko1 commented 4 years ago

应该可以

hongmingjian commented 4 years ago

OK,那我修改一下提交了。

我看你对OS也有兴趣,加我QQ私聊。

hyuuko1 commented 4 years ago

好的!