Add support for ADJ_SETOFFSET mode

This adjtimex mode allows precise stepping of the system clock.
This commit is contained in:
Miroslav Lichvar
2011-06-09 12:55:28 +02:00
parent b088b70f82
commit 6ab3d1daa3
4 changed files with 87 additions and 15 deletions

View File

@@ -229,5 +229,53 @@ TMX_GetPLLOffsetLeft(long *offset)
return result;
}
int
TMX_TestStepOffset(void)
{
struct timex txc;
/* Zero maxerror and check it's reset to a maximum after ADJ_SETOFFSET.
This seems to be the only way how to verify that the kernel really
supports the ADJ_SETOFFSET mode as it doesn't return an error on unknown
mode. */
txc.modes = ADJ_MAXERROR;
txc.maxerror = 0;
if (adjtimex(&txc) < 0 || txc.maxerror != 0)
return -1;
txc.modes = ADJ_SETOFFSET;
txc.time.tv_sec = 0;
txc.time.tv_usec = 0;
if (adjtimex(&txc) < 0 || txc.maxerror < 100000)
return -1;
return 0;
}
int
TMX_ApplyStepOffset(double offset)
{
struct timex txc;
txc.modes = ADJ_SETOFFSET;
if (offset >= 0) {
txc.time.tv_sec = offset;
} else {
txc.time.tv_sec = offset - 1;
}
/* ADJ_NANO changes the status even with ADJ_SETOFFSET, use it only when
STA_NANO is already enabled */
if (status & STA_PLL) {
txc.modes |= ADJ_NANO;
txc.time.tv_usec = 1e9 * (offset - txc.time.tv_sec);
} else {
txc.time.tv_usec = 1e6 * (offset - txc.time.tv_sec);
}
return adjtimex(&txc);
}
#endif