static void check_time(int wiggle) { struct tm start, date[4], end; struct tm *datep; time_t ts; /* * This check assumes a few things. First, we cannot guarantee that we get * a consistent reading from the wall clock because we may hit an edge of * the clock while reading. To work around this, we read four clock readings * such that at least two of them should match. We need to assume that one * reading is corrupt so we need four readings to ensure that we have at * least two consecutive identical readings * * It's also possible that we'll cross an edge reading the host clock so * simply check to make sure that the clock reading is within the period of * when we expect it to be. */ ts = time(NULL); gmtime_r(&ts, &start); cmos_get_date_time(&date[0]); cmos_get_date_time(&date[1]); cmos_get_date_time(&date[2]); cmos_get_date_time(&date[3]); ts = time(NULL); gmtime_r(&ts, &end); if (tm_cmp(&date[0], &date[1]) == 0) { datep = &date[0]; } else if (tm_cmp(&date[1], &date[2]) == 0) { datep = &date[1]; } else if (tm_cmp(&date[2], &date[3]) == 0) { datep = &date[2]; } else { g_assert_not_reached(); } if (!(tm_cmp(&start, datep) <= 0 && tm_cmp(datep, &end) <= 0)) { long t, s; start.tm_isdst = datep->tm_isdst; t = (long)mktime(datep); s = (long)mktime(&start); if (t < s) { g_test_message("RTC is %ld second(s) behind wall-clock\n", (s - t)); } else { g_test_message("RTC is %ld second(s) ahead of wall-clock\n", (t - s)); } g_assert_cmpint(ABS(t - s), <=, wiggle); }
static int timegm_internal (struct tm *tmp, time_t *tp) { struct tm tm0; struct tm tm1; time_t t0, t1, t, dt; static time_t delta; static int delta_ok = 0; int diff; /* Construct t0 and t1 to bracket the answer. First, guess a value close * to the correct answer. Consider: * tm_utc = gmtime(t) * tm_loc = localtime(t) * delta = tm_loc - tm_utc * Then we expect * t = mktime (tm_loc) = timegm(tm_utc) * = mktime (tm_utc + delta) * = mktime (tm_utc) + delta * ==> timegm(tm) = mktime(tm) + delta * ==> tm = gmtime(mktime(tm+delta)) * = gmtime(mktime(tm)) + delta * delta = tm - gmtime(mktime(tm)) */ if (delta_ok == 0) { /* localtime Jan 15, 2000 00:00:00 */ memset ((char *)&tm1, 0, sizeof(tm0)); tm1.tm_mday = 15; tm1.tm_year = 100; /* want mktime(tm1), but mktime will modify tm1, so use tm0 as a tmp */ tm0 = tm1; t1 = mktime (&tm0); if (-1 == call_gmtime (t1, &tm0)) return -1; /* Compute delta = tm1 - tm0 */ tm1.tm_hour += 24*(tm1.tm_mday - tm0.tm_mday); delta = (tm1.tm_hour - tm0.tm_hour)*3600 + (tm1.tm_min - tm0.tm_min)*60 + (tm1.tm_sec - tm0.tm_sec); delta_ok = 1; } tm0 = *tmp; /* do not allow mktime to mess with *tmp */ t = mktime (&tm0) + delta; /* Find a lower bound */ dt = 0; while (1) { int wrapped = 0; t0 = t - dt; while (t0 > t)/* handle wrapping */ { wrapped = 1; t0++; } if (-1 == call_gmtime (t0, &tm0)) return -1; diff = tm_cmp (&tm0, tmp); if (diff == 0) { *tp = t0; return 0; } if (diff < 0) break; if (wrapped) { SLang_verror (SL_Internal_Error, "timegm: Unable to find a lower limit"); return -1; } dt = dt*2 + 1; } /* upper bound */ dt = 1; while (1) { int wrapped = 0; t1 = t + dt; while (t1 < t)/* handle wrapping */ { wrapped = 1; t1--; } if (-1 == call_gmtime (t1, &tm1)) return -1; diff = tm_cmp (&tm1, tmp); if (diff == 0) { *tp = t1; return 0; } if (diff>0) break; if (wrapped) { SLang_verror (SL_Internal_Error, "timegm: Unable to find an upper limit"); return -1; } dt = dt * 2; } do { struct tm tmx; t = t0 + (t1-t0)/2; if (-1 == call_gmtime (t, &tmx)) return -1; diff = tm_cmp (&tmx, tmp); if (diff == 0) { *tp = t; return 0; } if (diff < 0) { if (t0 == t) break; t0 = t; tm0 = tmx; } else { t1 = t; tm1 = tmx; } } while (t0 + 1 < t1); *tp = t1; return 0; }
// Compares a skiplist node and a constant // Returns -1 when the skiplist node is less than the given constant, // 0 when they are equal and 1 when the skiplist node is greater than the given constant int slnode_const_cmp(slnode *arg, void *const_node) { ASSERT(arg); ASSERT(const_node); return (tm_cmp(arg->key, const_node)); }