[stgt] [PATCH] add timerfd work scheduler support
FUJITA Tomonori
fujita.tomonori at lab.ntt.co.jp
Thu Jan 20 11:39:04 CET 2011
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 at lab.ntt.co.jp>
Date: Thu, 20 Jan 2011 19:20:01 +0900
Subject: [PATCH] add timerfd work scheduler support
Signed-off-by: FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp>
---
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 at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the stgt
mailing list