tools/testing/selftests/timers/leap-a-day.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/timers/leap-a-day.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/timers/leap-a-day.c
Extension
.c
Size
9162 bytes
Lines
379
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

switch (opt) {
		case 'w':
			printf("Only setting leap-flag, not changing time. It could take up to a day for leap to trigger.\n");
			settime = 0;
			break;
		case 'i':
			iterations = atoi(optarg);
			break;
		case 't':
			tai_time = 1;
			break;
		default:
			printf("Usage: %s [-w] [-i <iterations>]\n", argv[0]);
			printf("	-w: Set flag and wait for leap second each iteration");
			printf("	    (default sets time to right before leapsecond)\n");
			printf("	-i: Number of iterations (-1 = infinite, default is 10)\n");
			printf("	-t: Print TAI time\n");
			exit(-1);
		}
	}

	/* Make sure TAI support is present if -t was used */
	if (tai_time) {
		struct timespec ts;

		if (clock_gettime(CLOCK_TAI, &ts)) {
			printf("System doesn't support CLOCK_TAI\n");
			ksft_exit_fail();
		}
	}

	signal(SIGINT, handler);
	signal(SIGKILL, handler);

	/* Set up timer signal handler: */
	sigfillset(&act.sa_mask);
	act.sa_flags = 0;
	act.sa_handler = sigalarm;
	sigaction(signum, &act, NULL);

	if (iterations < 0)
		printf("This runs continuously. Press ctrl-c to stop\n");
	else
		printf("Running for %i iterations. Press ctrl-c to stop\n", iterations);

	printf("\n");
	while (1) {
		int ret;
		struct timespec ts;
		struct timex tx;
		time_t now;

		/* Get the current time */
		clock_gettime(CLOCK_REALTIME, &ts);

		/* Calculate the next possible leap second 23:59:60 GMT */
		next_leap = ts.tv_sec;
		next_leap += 86400 - (next_leap % 86400);

		if (settime) {
			struct timeval tv;

			tv.tv_sec = next_leap - 10;
			tv.tv_usec = 0;
			settimeofday(&tv, NULL);
			printf("Setting time to %s", ctime(&tv.tv_sec));
		}

		/* Reset NTP time state */
		clear_time_state();

		/* Set the leap second insert flag */
		tx.modes = ADJ_STATUS;
		if (insert)
			tx.status = STA_INS;
		else
			tx.status = STA_DEL;
		ret = adjtimex(&tx);
		if (ret < 0) {
			printf("Error: Problem setting STA_INS/STA_DEL!: %s\n",
							time_state_str(ret));
			ksft_exit_fail();
		}

		/* Validate STA_INS was set */
		tx.modes = 0;
		ret = adjtimex(&tx);
		if (tx.status != STA_INS && tx.status != STA_DEL) {
			printf("Error: STA_INS/STA_DEL not set!: %s\n",
							time_state_str(ret));

Annotation

Implementation Notes