Ver código fonte

Sched deadline

patron 8 meses atrás
pai
commit
45f0c716aa
1 arquivos alterados com 94 adições e 7 exclusões
  1. 94 7
      timerfd/main.c

+ 94 - 7
timerfd/main.c

@@ -1,19 +1,56 @@
+#define _GNU_SOURCE
+#include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.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;
 
-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)
 	{
 		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
 	int tfd = -1;
 	struct itimerspec itval;
-	int rc = 0;
 
 	tfd = timerfd_create(CLOCK_MONOTONIC, 0);
 	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);
 #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);
@@ -93,7 +175,12 @@ int main(int argc, char *argv[])
 	sigaction (SIGHUP, &sa, NULL);
 
 	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;
 }