| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- #define _GNU_SOURCE
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sched.h>
- #include <err.h>
- #include <sys/time.h>
- #include <signal.h>
- #include <sys/syscall.h>
- #include <sys/timerfd.h>
- #include <linux/unistd.h>
- #include <linux/kernel.h>
- #include <linux/types.h>
- #include <sys/syscall.h>
- #include <stdbool.h>
- #define gettid() syscall(__NR_gettid)
- static int do_print;
- static int do_quit;
- static size_t loops;
- #ifndef __NR_sched_setattr
- #ifdef __x86_64__
- #define __NR_sched_setattr 314L
- #define __NR_sched_getattr 315L
- #endif
- #endif
- struct sched_attr {
- __u32 size;
- __u32 sched_policy;
- __u64 sched_flags;
- __s32 sched_nice;
- __s32 sched_priority;
- __u64 sched_runtime;
- __u64 sched_deadline;
- __u64 sched_period;
- };
- long sched_setattr(pid_t pid, const struct sched_attr *attr,
- unsigned int flags)
- {
- return syscall(__NR_sched_setattr, pid, attr, flags);
- }
- long sched_getattr(pid_t pid, struct sched_attr *attr,
- unsigned int size, unsigned int flags)
- {
- return syscall(__NR_sched_getattr, pid, attr, size, flags);
- }
- static void sig_handler(int signum)
- {
- switch (signum)
- {
- case SIGQUIT:
- case SIGTERM:
- case SIGINT:
- signal(SIGINT, SIG_DFL);
- do_quit = 1;
- __attribute__((fallthrough));
- case SIGUSR1:
- do_print = 1;
- break;
- case SIGHUP:
- loops = 0;
- default:
- break;
- }
- }
- static int deadline(size_t period_ms)
- {
- int rc = 0;
- #ifndef EDF
- int tfd = -1;
- struct itimerspec itval;
- tfd = timerfd_create(CLOCK_MONOTONIC, 0);
- if (tfd == -1)
- err(-1, "timerfd");
- itval.it_interval.tv_sec = 0;
- itval.it_interval.tv_nsec = period_ms * 1000 * 1000;
- itval.it_value.tv_sec = 0;
- itval.it_value.tv_nsec = itval.it_interval.tv_nsec;
- rc = timerfd_settime(tfd, 0, &itval, NULL);
- if (rc)
- err(-1, "timerfd_settime");
- do {
- static unsigned long long overrun;
- rc = read(tfd, &overrun, sizeof overrun);
- if (rc == -1) {
- err(-1, "Timer read");
- }
- ++loops;
- if (do_print) {
- do_print = 0;
- fprintf(stdout, "Loops: %zu.\n", loops);
- }
- } while(!do_quit);
- #else
- struct sched_attr attr;
- unsigned int flags = 0;
- attr.size = sizeof attr;
- attr.sched_flags = 0;
- attr.sched_nice = 0;
- attr.sched_priority = 0;
- attr.sched_policy = SCHED_DEADLINE;
- attr.sched_runtime = (period_ms - 1) * 1000 * 1000;
- attr.sched_period = attr.sched_deadline = period_ms * 1000 * 1000;
- rc = sched_setattr(0, &attr, flags);
- if (rc)
- err(EXIT_FAILURE, "sched_setattr");
- do {
- ++loops;
- if (do_print) {
- do_print = 0;
- fprintf(stdout, "Loops: %zu.\n", loops);
- }
- sched_yield();
- } while(!do_quit);
- #endif
- printf("last counter => %zu.\n", loops);
- }
- #define SEC_NSEC 1000000000U
- static __attribute__((const)) u_int64_t timespec_sub_to_ns(struct timespec t1,
- struct timespec t2)
- {
- u_int64_t diff;
- if (t1.tv_nsec < t2.tv_nsec) {
- diff = SEC_NSEC * (u_int64_t)(t1.tv_sec - t2.tv_sec -1);
- diff += (u_int64_t)(t1.tv_nsec - t2.tv_nsec);
- diff += SEC_NSEC;
- } else {
- diff = SEC_NSEC * (u_int64_t)(t1.tv_sec - t2.tv_sec);
- diff += (u_int64_t)(t1.tv_nsec - t2.tv_nsec);
- }
- return diff;
- }
- int main(int argc, char *argv[])
- {
- int rc;
- struct sigaction sa = {0};
- struct timespec t0, t1;
- /* Set up the structure to specify the new action. */
- sigemptyset (&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGINT);
- sa.sa_handler = &sig_handler;
- sa.sa_flags = 0;
- sigaddset(&sa.sa_mask, SIGTERM);
- sigaddset(&sa.sa_mask, SIGINT);
- sigaddset(&sa.sa_mask, SIGHUP);
- sigaddset(&sa.sa_mask, SIGUSR1);
- sigaddset(&sa.sa_mask, SIGQUIT);
- if (sigaction (SIGINT, &sa, NULL) == -1) {
- perror("sigaction");
- exit(EXIT_FAILURE);
- }
- sigaction (SIGTERM, &sa, NULL);
- sigaction (SIGQUIT, &sa, NULL);
- sigaction (SIGUSR1, &sa, NULL);
- sigaction (SIGHUP, &sa, NULL);
- printf("[%d] Starting deadline thread.\n", getpid());
- clock_gettime(CLOCK_MONOTONIC, &t0);
- rc = deadline(5);
- clock_gettime(CLOCK_MONOTONIC, &t1);
- size_t to = timespec_sub_to_ns(t1, t0) / 1000000;
- printf("Time: %lums. average : %lums.\n", to, to / loops);
- return rc ? EXIT_FAILURE : EXIT_SUCCESS;
- }
|