rtc: Fix Unix epoch conversion from RTC time.
authorYuzhuo Jing <yzjing@jhu.edu>
Sat, 29 May 2021 18:58:01 +0000 (11:58 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 29 May 2021 18:58:27 +0000 (11:58 -0700)
We can see the effect by adding two printf shown in the rtcprint.patch
attachment. Running `pintos --bochs -- -q`, I get the following output:

Time is 70-01-01 00:00:09
Unix epoch is 2678409

The expected epoch should be 9 according to the first line. The epoch we
see is 1 month behind the correct value.

Reason for this is the months to seconds calculation:

  for (i = 1; i <= mon; i++)
    time += days_per_month[i - 1] * 24 * 60 * 60;
  …
  time += (mday - 1) * 24 * 60 * 60;

The days in that month is calculated in the last line in the snippet.
Therefore, only the days before that month in that year needs to be
counted in the for loop. We can change ‘<=‘ to ‘<‘ in the loop
condition.

After fixing this, running `pintos -- -q; date; date +%s` gives:

Time is 21-05-24 09:32:40
Unix epoch is 1621762360

Mon May 24 09:32:40 UTC 2021
1621848760

There is a time difference of 1 leap day. Year 1970 was not a leap year,
but 1968 and 1972 were.

src/devices/rtc.c

index d99eb4679f1c9da0eed03412062f84209666cfd3..745d779eebf7010f8ef31b7fb5c1fe7fc405e765 100644 (file)
@@ -1,4 +1,5 @@
 #include "devices/rtc.h"
+#include <round.h>
 #include <stdio.h>
 #include "threads/io.h"
 
@@ -82,10 +83,10 @@ rtc_get_time (void)
   year -= 70;
 
   /* Break down all components into seconds. */
-  time = (year * 365 + (year - 1) / 4) * 24 * 60 * 60;
-  for (i = 1; i <= mon; i++)
+  time = (year * 365 + DIV_ROUND_UP (year - 2, 4)) * 24 * 60 * 60;
+  for (i = 1; i < mon; i++)
     time += days_per_month[i - 1] * 24 * 60 * 60;
-  if (mon > 2 && year % 4 == 0)
+  if (mon > 2 && year % 4 == 2)
     time += 24 * 60 * 60;
   time += (mday - 1) * 24 * 60 * 60;
   time += hour * 60 * 60;