I used strace
on ntpdate
command which calls adjtimex to adjust time.
I got this:
adjtimex({modes=ADJ_OFFSET|0x8000, offset=-479139, freq=0, maxerror=16000000, esterror=16000000, status=STA_UNSYNC, constant=2, precision=1, tolerance=32768000, time={1352220968, 428418}, tick=10000, ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, errcnt=0, stbcnt=0}) = 5 (TIME_ERROR)
Then I looked into implementation of adjtimex API in do_adjtimex main funcition.
But from the code I can not see how ntpdate
adjusts the time.
modes=ADJ_OFFSET|0x8000=ADJ_OFFSET|ADJ_ADJTIME
int do_adjtimex(struct timex *txc)
{
struct timespec ts;
int result;
/* Validate the data before disabling interrupts */
if (txc->modes & ADJ_ADJTIME) { **<----this is true. modes as ADJ_OFFSET|ADJ_ADJTIME**
/* singleshot must not be used with any other mode bits */
if (!(txc->modes & ADJ_OFFSET_SINGLESHOT))
return -EINVAL;
if (!(txc->modes & ADJ_OFFSET_READONLY) &&
!capable(CAP_SYS_TIME))
return -EPERM;
} else {
.....
}
if (txc->modes & ADJ_SETOFFSET) { **《===this is false**
.....
}
getnstimeofday(&ts);**《------------just get the walk time**
spin_lock_irq(&ntp_lock);
if (txc->modes & ADJ_ADJTIME) {<----this is true.
long save_adjust = time_adjust; **<----this is global valu eoffset=-479139**
if (!(txc->modes & ADJ_OFFSET_READONLY)) {
/* adjtime() is independent from ntp_adjtime() */
time_adjust = txc->offset;
ntp_update_frequency();
}
txc->offset = save_adjust;
} else {
.......
}
result = time_state; /* mostly `TIME_OK' */ this is
/* check for errors */
if (is_error_status(time_status)) **<----this is STA_UNSYNC**
result = TIME_ERROR;
txc->freq = shift_right((time_freq >> PPM_SCALE_INV_SHIFT) *
PPM_SCALE_INV, NTP_SCALE_SHIFT);
txc->maxerror = time_maxerror;
txc->esterror = time_esterror;
txc->status = time_status;
txc->constant = time_constant;
txc->precision = 1;
txc->tolerance = MAXFREQ_SCALED / PPM_SCALE;
txc->tick = tick_usec;
txc->tai = time_tai;
/* fill PPS status fields */
pps_fill_timex(txc);
spin_unlock_irq(&ntp_lock);
txc->time.tv_sec = ts.tv_sec;
txc->time.tv_usec = ts.tv_nsec;
if (!(time_status & STA_NANO))
txc->time.tv_usec /= NSEC_PER_USEC;
notify_cmos_timer(); <---- call sync_cmos_clock.
return result;
}
sync_cmos_clock checks whether ntp is synced. time_status is STA_UNSYNC. Just do nothing and return.
if (!ntp_synced()) { /*
* Not synced, exit, do not restart a timer (if one is
* running, let it run out). */
return; }
Am I missing something?