David Marec 10 bulan lalu
melakukan
be046ec713
2 mengubah file dengan 166 tambahan dan 0 penghapusan
  1. 17 0
      kqueue/Makefile
  2. 149 0
      kqueue/kq_timer.c

+ 17 - 0
kqueue/Makefile

@@ -0,0 +1,17 @@
+CFLAGS+=-O3 -Wall
+LDFLAGS+=-Wl,-O3,--sort-common,--as-needed,-z,relro,-z,now,--strip-all
+
+KQT=kq_timer
+KQT_OBJS=kq_timer.o
+
+all: $(KQT)
+
+kq_timer: $(KQT_OBJS)
+	$(CC) -o ${.TARGET} ${.ALLSRC} $(LDFLAGS)
+
+%o: 
+	$(CC) -o ${.TARGET} -c ${.IMPSRC}
+
+clean:
+	rm -f *.o $(KQT)
+

+ 149 - 0
kqueue/kq_timer.c

@@ -0,0 +1,149 @@
+#include <sys/event.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <sched.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h> 
+#include <unistd.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdbool.h>
+
+static int verbose;
+
+static int usage(void)
+{
+	fputs("kq_timer [--verbose] [--period ms]\n", stderr);
+	exit (EXIT_SUCCESS);
+}
+
+static double diff_ms(const struct timespec *time1, const struct timespec *time0)
+{
+	return (time1->tv_sec - time0->tv_sec) * 1000 
+		+ (time1->tv_nsec - time0->tv_nsec) / 1000000.0;
+}
+
+static void sig_handler(int sig)
+{
+	signal(SIGINT, SIG_DFL);
+}
+
+int main(int argc, char *argv[])
+{
+	struct kevent change; /* event we want to monitor */
+	struct kevent event;  /* event that was triggered */
+	int kq, nev; /* handlers */
+	int ch; /* opt long */
+
+	int period = 1000; /* Default to 1 sec. */
+	size_t counter = 0;
+	size_t total = 0;
+	FILE *fd = NULL;
+	char template[64];
+	int rc = EXIT_FAILURE;
+	struct	timespec t0 = { 0, 0};
+	const struct sched_param param = {.sched_priority = 49};
+	static struct option longopts[] = {
+		{ "period",   required_argument,      NULL, 'p' },
+		{ "verbose",  no_argument      ,  &verbose,  1  },
+		{ NULL,	0, NULL, 0 }
+	};
+
+	while ((ch = getopt_long(argc, argv, "hvp:", longopts, NULL)) != -1) {
+		switch (ch) {
+			case 'v':
+				verbose = 1;
+				break;
+			case 'p':
+				period = atoi(optarg);
+				break;
+			case 0:
+				/* long option */
+				break;
+			default:
+				usage();
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (*argv)
+		usage();
+
+	/* create a new kernel event queue */
+	if ((kq = kqueue()) == -1)
+		err(EXIT_FAILURE, "kqueue() failure");
+
+	/* initalise kevent structure */
+	EV_SET(&change, 1, EVFILT_TIMER, EV_ADD | EV_ENABLE, NOTE_MSECONDS, 1, 0);
+
+	/* Dummy file to store measurements */
+	strncpy(template, "/tmp/timer.XXXXXX", sizeof template);
+	if (mkstemp(template) == -1) {
+		warn("mkstemp() failure");
+		goto exit_kqueue;
+	}
+
+	fd = fopen(template, "w");
+	if (fd == NULL) {
+		warn("fopen() failure");
+		goto exit_kqueue;
+	}
+
+	printf("Log file: %s\n", template);
+
+	/* process priority */
+	sched_setscheduler(0, SCHED_FIFO, &param);
+
+	signal(SIGINT, sig_handler);
+
+	while (true) {
+		nev = kevent(kq, &change, 1, &event, 1, NULL);
+
+		if (nev < 0) {
+			/* interrupted */
+			break;
+		}
+
+		if (nev > 0) {
+
+			/* measurements */
+			struct	timespec t1;
+			clock_gettime(CLOCK_MONOTONIC, &t1);
+
+			if (!(t0.tv_sec == 0 && t0.tv_nsec == 0))
+				fprintf(fd, "%06.3f\n", diff_ms(&t1, &t0));
+
+			t0 = t1;
+
+			if (event.flags & EV_ERROR) {
+				fprintf(stderr, "EV_ERROR: %s\n", strerror(event.data));
+				rc = EXIT_FAILURE;
+				break;
+			}
+
+			/* verbose mode */
+			++counter;
+			if (counter == period) {
+				if (verbose) {
+					fputs(".", stdout);
+					fflush(stdout);
+				}
+
+				counter = 0;
+				++total;
+			}
+		}
+	}
+
+	rc = 0;
+
+	fclose(fd);
+	fprintf(stdout, "\n%zu entries stored.\n", total);
+exit_kqueue:
+	close(kq);
+	return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+