[PATCH] add timerfd work scheduler support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This needs to be applied on the top of:

http://lists.wpkg.org/pipermail/stgt/2011-January/004380.html

This leads to less cpu usage rather than the signal base scheduler.

=
From: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>
Date: Thu, 20 Jan 2011 19:20:01 +0900
Subject: [PATCH] add timerfd work scheduler support

Signed-off-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>
---
 usr/work.c |  150 +++++++++++++++++++++++++++++++++++++++---------------------
 usr/work.h |    2 +-
 2 files changed, 99 insertions(+), 53 deletions(-)

diff --git a/usr/work.c b/usr/work.c
index c3e1f34..cce3943 100644
--- a/usr/work.c
+++ b/usr/work.c
@@ -24,6 +24,7 @@
 #include <stdint.h>
 #include <signal.h>
 #include <sys/epoll.h>
+#include <sys/timerfd.h>
 
 #include "list.h"
 #include "util.h"
@@ -40,9 +41,9 @@ static struct itimerval work_timer = {
 	{WORK_TIMER_INT_SEC, WORK_TIMER_INT_USEC}
 };
 
-static int elapsed_msecs;
+static unsigned int elapsed_msecs;
 static int timer_pending;
-static int timer_fd[2];
+static int timer_fd[2] = {-1, -1};
 
 static LIST_HEAD(active_work_list);
 static LIST_HEAD(inactive_work_list);
@@ -76,29 +77,70 @@ static void work_timer_sig_handler(int data)
 
 static void work_timer_evt_handler(int fd, int events, void *data)
 {
-	unsigned int n;
 	int err;
+	static int first = 1;
 
-	err = read(timer_fd[0], &n, sizeof(n));
-	if (err < 0) {
-		eprintf("Failed to read from pipe, %m\n");
-		return;
-	}
+	if (timer_fd[1] == -1) {
+		unsigned long long s;
+		struct timeval cur_time;
+
+		err = read(timer_fd[0], &s, sizeof(s));
+		if (err < 0) {
+			if (err != -EAGAIN)
+				eprintf("failed to read from timerfd, %m\n");
+			return;
+		}
+
+		if (first) {
+			first = 0;
+			err = gettimeofday(&cur_time, NULL);
+			if (err) {
+				eprintf("gettimeofday failed, %m\n");
+				exit(1);
+			}
+			elapsed_msecs = timeval_to_msecs(cur_time);
+			return;
+		}
+
+		elapsed_msecs += (unsigned int)s * WORK_TIMER_INT_MSEC;
+	} else {
+		unsigned int n;
+		struct timeval cur_time;
+
+		err = read(timer_fd[0], &n, sizeof(n));
+		if (err < 0) {
+			eprintf("Failed to read from pipe, %m\n");
+			return;
+		}
 
-	timer_pending = 0;
+		timer_pending = 0;
+
+		err = gettimeofday(&cur_time, NULL);
+		if (err) {
+			eprintf("gettimeofday failed, %m\n");
+			exit(1);
+		}
+
+		elapsed_msecs = timeval_to_msecs(cur_time);
+	}
 
 	execute_work();
 }
 
 int work_timer_start(void)
 {
-	struct sigaction s;
 	struct timeval t;
 	int err;
 
 	if (elapsed_msecs)
 		return 0;
 
+	timer_fd[0] = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);
+	if (timer_fd[0] < 0)
+		eprintf("use the signal based schedular\n");
+	else
+		eprintf("use the timer_fd based schedular\n");
+
 	err = gettimeofday(&t, NULL);
 	if (err) {
 		eprintf("gettimeofday failed, %m\n");
@@ -106,30 +148,45 @@ int work_timer_start(void)
 	}
 	elapsed_msecs = timeval_to_msecs(t);
 
-	sigemptyset(&s.sa_mask);
-	sigaddset(&s.sa_mask, SIGALRM);
-	s.sa_flags = 0;
-	s.sa_handler = work_timer_sig_handler;
-	err = sigaction(SIGALRM, &s, NULL);
-	if (err) {
-		eprintf("Failed to setup timer handler\n");
-		goto timer_err;
-	}
+	if (timer_fd[0] < 0) {
+		struct sigaction s;
 
-	err = setitimer(ITIMER_REAL, &work_timer, 0);
-	if (err) {
-		eprintf("Failed to set timer\n");
-		goto timer_err;
-	}
+		sigemptyset(&s.sa_mask);
+		sigaddset(&s.sa_mask, SIGALRM);
+		s.sa_flags = 0;
+		s.sa_handler = work_timer_sig_handler;
+		err = sigaction(SIGALRM, &s, NULL);
+		if (err) {
+			eprintf("Failed to setup timer handler\n");
+			goto timer_err;
+		}
 
-	err = pipe(timer_fd);
-	if (err) {
-		eprintf("Failed to open timer pipe\n");
-		goto timer_err;
+		err = setitimer(ITIMER_REAL, &work_timer, 0);
+		if (err) {
+			eprintf("Failed to set timer\n");
+			goto timer_err;
+		}
+
+		err = pipe(timer_fd);
+		if (err) {
+			eprintf("Failed to open timer pipe\n");
+			goto timer_err;
+		}
+	} else {
+		struct itimerspec new, old;
+
+		new.it_value.tv_sec = 0;
+		new.it_value.tv_nsec = 1;
+
+		new.it_interval.tv_sec = 0;
+		new.it_interval.tv_nsec = WORK_TIMER_INT_USEC * 1000;
+
+		err = timerfd_settime(timer_fd[0], TFD_TIMER_ABSTIME, &new, &old);
+		if (err < 0)
+			goto timer_err;
 	}
 
-	err = tgt_event_add(timer_fd[0], EPOLLIN,
-			    work_timer_evt_handler, NULL);
+	err = tgt_event_add(timer_fd[0], EPOLLIN, work_timer_evt_handler, NULL);
 	if (err) {
 		eprintf("failed to add timer event, fd:%d\n", timer_fd[0]);
 		goto timer_err;
@@ -144,12 +201,10 @@ timer_err:
 	return err;
 }
 
-int work_timer_stop(void)
+void work_timer_stop(void)
 {
-	int err;
-
 	if (!elapsed_msecs)
-		return 0;
+		return;
 
 	elapsed_msecs = 0;
 
@@ -157,16 +212,17 @@ int work_timer_stop(void)
 
 	if (timer_fd[0] > 0)
 		close(timer_fd[0]);
-	if (timer_fd[1] > 0)
-		close(timer_fd[1]);
 
-	err = setitimer(ITIMER_REAL, 0, 0);
-	if (err)
-		eprintf("Failed to stop timer\n");
-	else
-		dprintf("Timer stopped\n");
+	if (timer_fd[1] > 0) {
+		int ret;
+		close(timer_fd[1]);
 
-	return err;
+		ret = setitimer(ITIMER_REAL, 0, 0);
+		if (ret)
+			eprintf("Failed to stop timer\n");
+		else
+			dprintf("Timer stopped\n");
+	}
 }
 
 void add_work(struct tgt_work *work, unsigned int second)
@@ -202,17 +258,7 @@ void del_work(struct tgt_work *work)
 
 static void execute_work()
 {
-	struct timeval cur_time;
 	struct tgt_work *work, *n;
-	int err;
-
-	err = gettimeofday(&cur_time, NULL);
-	if (err) {
-		eprintf("gettimeofday failed, %m\n");
-		exit(1);
-	}
-
-	elapsed_msecs = timeval_to_msecs(cur_time);
 
 	list_for_each_entry_safe(work, n, &inactive_work_list, entry) {
 		if (before(elapsed_msecs, work->when))
diff --git a/usr/work.h b/usr/work.h
index 98a28d5..e845560 100644
--- a/usr/work.h
+++ b/usr/work.h
@@ -11,7 +11,7 @@ struct tgt_work {
 };
 
 extern int work_timer_start(void);
-extern int work_timer_stop(void);
+extern void work_timer_stop(void);
 
 extern void add_work(struct tgt_work *work, unsigned int second);
 extern void del_work(struct tgt_work *work);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Linux RAID]     [Linux Clusters]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]

  Powered by Linux