|
@@ -1,19 +1,56 @@
|
|
|
|
|
+#define _GNU_SOURCE
|
|
|
|
|
+#include <unistd.h>
|
|
|
#include <stdio.h>
|
|
#include <stdio.h>
|
|
|
#include <stdlib.h>
|
|
#include <stdlib.h>
|
|
|
-#include <unistd.h>
|
|
|
|
|
|
|
+#include <sched.h>
|
|
|
#include <err.h>
|
|
#include <err.h>
|
|
|
#include <sys/time.h>
|
|
#include <sys/time.h>
|
|
|
#include <signal.h>
|
|
#include <signal.h>
|
|
|
#include <sys/syscall.h>
|
|
#include <sys/syscall.h>
|
|
|
#include <sys/timerfd.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_print;
|
|
|
static int do_quit;
|
|
static int do_quit;
|
|
|
static size_t loops;
|
|
static size_t loops;
|
|
|
|
|
|
|
|
-void sig_handler(int signum)
|
|
|
|
|
|
|
+#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)
|
|
|
{
|
|
{
|
|
|
- printf("ok");
|
|
|
|
|
switch (signum)
|
|
switch (signum)
|
|
|
{
|
|
{
|
|
|
case SIGQUIT:
|
|
case SIGQUIT:
|
|
@@ -32,12 +69,12 @@ void sig_handler(int signum)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-int deadline(size_t period_ms)
|
|
|
|
|
|
|
+static int deadline(size_t period_ms)
|
|
|
{
|
|
{
|
|
|
|
|
+ int rc = 0;
|
|
|
#ifndef EDF
|
|
#ifndef EDF
|
|
|
int tfd = -1;
|
|
int tfd = -1;
|
|
|
struct itimerspec itval;
|
|
struct itimerspec itval;
|
|
|
- int rc = 0;
|
|
|
|
|
|
|
|
|
|
tfd = timerfd_create(CLOCK_MONOTONIC, 0);
|
|
tfd = timerfd_create(CLOCK_MONOTONIC, 0);
|
|
|
if (tfd == -1)
|
|
if (tfd == -1)
|
|
@@ -63,14 +100,59 @@ int deadline(size_t period_ms)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ } 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);
|
|
} while(!do_quit);
|
|
|
#endif
|
|
#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 main(int argc, char *argv[])
|
|
|
{
|
|
{
|
|
|
int rc;
|
|
int rc;
|
|
|
struct sigaction sa = {0};
|
|
struct sigaction sa = {0};
|
|
|
|
|
+ struct timespec t0, t1;
|
|
|
|
|
|
|
|
/* Set up the structure to specify the new action. */
|
|
/* Set up the structure to specify the new action. */
|
|
|
sigemptyset (&sa.sa_mask);
|
|
sigemptyset (&sa.sa_mask);
|
|
@@ -93,7 +175,12 @@ int main(int argc, char *argv[])
|
|
|
sigaction (SIGHUP, &sa, NULL);
|
|
sigaction (SIGHUP, &sa, NULL);
|
|
|
|
|
|
|
|
printf("[%d] Starting deadline thread.\n", getpid());
|
|
printf("[%d] Starting deadline thread.\n", getpid());
|
|
|
- rc = deadline(500);
|
|
|
|
|
- exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
|
|
|
|
|
|
|
+ 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;
|
|
|
}
|
|
}
|