tools/testing/selftests/timers/adjtick.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/timers/adjtick.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/timers/adjtick.c
Extension
.c
Size
4581 bytes
Lines
208
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (diff == 0 || newdiff < diff) {
			diff = newdiff;
			*raw = mid;
			tmp = (ts_to_nsec(start) + ts_to_nsec(end))/2;
			*mon = nsec_to_ts(tmp);
		}
	}
}

long long get_ppm_drift(void)
{
	struct timespec mon_start, raw_start, mon_end, raw_end;
	long long delta1, delta2, eppm;

	get_monotonic_and_raw(&mon_start, &raw_start);

	sleep(15);

	get_monotonic_and_raw(&mon_end, &raw_end);

	delta1 = diff_timespec(mon_start, mon_end);
	delta2 = diff_timespec(raw_start, raw_end);

	eppm = (delta1*MILLION)/delta2 - MILLION;

	return eppm;
}

int check_tick_adj(long tickval)
{
	long long eppm, ppm;
	struct timex tx1;

	tx1.modes	 = ADJ_TICK;
	tx1.modes	|= ADJ_OFFSET;
	tx1.modes	|= ADJ_FREQUENCY;
	tx1.modes	|= ADJ_STATUS;

	tx1.status	= STA_PLL;
	tx1.offset	= 0;
	tx1.freq	= 0;
	tx1.tick	= tickval;

	adjtimex(&tx1);

	sleep(1);

	ppm = ((long long)tickval * MILLION)/systick - MILLION;
	printf("Estimating tick (act: %ld usec, %lld ppm): ", tickval, ppm);

	eppm = get_ppm_drift();
	printf("%lld usec, %lld ppm", systick + (systick * eppm / MILLION), eppm);
	fflush(stdout);

	tx1.modes = 0;
	adjtimex(&tx1);

	if (tx1.offset || tx1.freq || tx1.tick != tickval) {
		printf("	[ERROR]\n");
		printf("\tUnexpected adjtimex return values, make sure ntpd is not running.\n");
		return -1;
	}

	/*
	 * Here we use 100ppm difference as an error bound.
	 * We likely should see better, but some coarse clocksources
	 * cannot match the HZ tick size accurately, so we have a
	 * internal correction factor that doesn't scale exactly
	 * with the adjustment, resulting in > 10ppm error during
	 * a 10% adjustment. 100ppm also gives us more breathing
	 * room for interruptions during the measurement.
	 */
	if (llabs(eppm - ppm) > 100) {
		printf("	[FAILED]\n");
		return -1;
	}
	printf("	[OK]\n");

	return  0;
}

int main(int argc, char **argv)
{
	struct timespec raw;
	long tick, max, interval, err;
	struct timex tx1;

	err = 0;
	setbuf(stdout, NULL);

Annotation

Implementation Notes