ADJ_SETOFFSET mode was added in 2.6.39:
$ git tag --contains 094aa1881fdc1b8889b442eb3511b31f3ec2b762 | head -n 1
v2.6.39
ADJ_MICRO and ADJ_NANO modes were added in 2.6.26:
$ git tag --contains eea83d896e318bda54be2d2770d2c5d6668d11db | head -n 1
v2.6.26
Signed-off-by: Nikola Forró <nforro@redhat.com>
Probably, it's not wise to suggest adjtime(3) as the more
portable API. Rather, ntp_adjtime(3) should be used.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Starting with Linux 3.4, the time_state change is now asynchronous
and the call returns the time_state before it has been altered,
rather than after it was altered as the previous code did.
======================================================
Notes from Petr Gajdos
attached program behaves differently on 2.6 and 3.0 kernels:
*******************************************************
2.6.32.59-0.7-default
Insert LS
adjtimex() return code 1: insert leap second (TIME_INS)
Kernel leap second flag: STA_INS
Delete LS
adjtimex() return code 2: delete leap second (TIME_DEL)
Kernel leap second flag: STA_DEL
Insert LS again
adjtimex() return code 1: insert leap second (TIME_INS)
Kernel leap second flag: STA_INS
Delete LS again
adjtimex() return code 2: delete leap second (TIME_DEL)
Kernel leap second flag: STA_DEL
*******************************************************
3.0.101-0.35-default
sbsvt101:~/tmp # ./adjt
Insert LS
adjtimex() return code 0: clock synchronized (TIME_OK)
Kernel leap second flag: STA_INS
Delete LS
adjtimex() return code 1: insert leap second (TIME_INS)
Kernel leap second flag: STA_DEL
Insert LS again
adjtimex() return code 2: delete leap second (TIME_DEL)
Kernel leap second flag: STA_INS
Delete LS again
adjtimex() return code 1: insert leap second (TIME_INS)
Kernel leap second flag: STA_DEL
*******************************************************
The explanation provided by William Preston (in CC):
"""
in both cases you get the actual value of the global kernel variable
time_state.
The code changed between the two kernels in the way it handled this.
In 2.6.32.59 the adjtimex call starts a timer immediately with the
function ntp_start_leap_timer(), which sets the value of time_state
before returning to the user.
This means you will get the value TIME_INS / TIME_DEL back
immediately.
In 3.0.101, the timer has been removed and the value of time_state is
set when the microsecond field overflows. The function
second_overflow() handles this. This means the value of time_state
will not have been set when the syscall adjtimex returns, and so you
will almost certainly get the old state.
Incidentally if you remove the sleep() calls in the code for 3.0.101
you may instead see the state of TIME_OK when switching between
STA_INS / STA_DEL.
All this is completely normal and expected behaviour, since both
return the current state, however I agree it is not intuitive.
I would recommend calling adjtimex without a mode to get the actual
state of the system after waiting a second.
At the same time, William suggests the patch in the attachement.
Petr
=============== adjt.c ================
void adjtm(int);
int main()
{
printf("Insert LS\n");
adjtm(STA_INS);
sleep(2);
printf("\nDelete LS\n");
adjtm(STA_DEL);
sleep(2);
printf("\nInsert LS again\n");
adjtm(STA_INS);
sleep(2);
printf("\nDelete LS again\n");
adjtm(STA_DEL);
printf("\nRestoring initial state\n");
adjtm(0);
}
/*************************************/
/* Modify LS flag and print status */
/*************************************/
void adjtm(int ls)
{
struct timex tx;
int rc;
tx.modes = ADJ_STATUS;
tx.status = ls;
if ((rc = adjtimex(&tx)) == -1) {
perror("adjtimex()");
exit(1);
}
sleep(2);
tx.modes = 0;
rc = adjtimex(&tx);
printf("adjtimex() return code %d: ", rc);
switch (rc) {
case TIME_OK:
printf("clock synchronized (TIME_OK)\n");
break;
case TIME_INS:
printf("insert leap second (TIME_INS)\n");
break;
case TIME_DEL:
printf("delete leap second (TIME_DEL)\n");
break;
case TIME_OOP:
printf("leap second in progress (TIME_OOP)\n");
break;
case TIME_WAIT:
printf("leap second has occurred (TIME_WAIT)\n");
break;
case TIME_BAD:
printf("clock not synchronized (TIME_BAD)\n");
break;
default:
printf("Unknown return code: %i\n", rc);
break;
}
printf("Kernel leap second flag: ");
if (tx.status & STA_INS)
printf("STA_INS\n");
else if (tx.status & STA_DEL)
printf("STA_DEL\n");
else
printf("not set\n");
}
=======================================
Reported-by: Petr Gajdos <pgajdos@suse.cz>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
It seems that adjtimex() never needed _BSD_SOURCE (and my
earlier commit 5918743bc8 was simply a blunder.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Hi again,
this is the second patch of the new series of patchs for adjtimex.2.
This is a trivia patch correcting "PPM" (parts per million) to the more usual "ppm".
Credits to Jeff Epler <jepler@unpythonic.net>.
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This patch makes explicit and clarifies the unit used for
the fields "freq", "ppsfreq" and "stabil" in struct timex.
Reviewed-by: Richard Cochran <richardcochran@gmail.com>
Reviewed-by: Jeff Epler <jepler@unpythonic.net>
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>