[sheepdog] [PATCH v10 5/7] lib: add a mechanism for prioritizing events

Hitoshi Mitake mitake.hitoshi at lab.ntt.co.jp
Mon Apr 8 03:47:05 CEST 2013


I posted the patch which implements a prioritizing mechanism in
event_loop() of libsheepdog [1]. This patch implements a similar
but simpler one.

The previous patch changed type of event handlers for detecting
requirements of refresh, etc by their return values. The new one
doesn't require changing the types. If event handlers want event loop
to refresh, they only need to call a new API: event_force_refresh().

In addition, event_loop() doesn't cause sort of events based on their
priority. If programs which employ libsheepdog.a want to use the event
prioritize mechanism, they have to call event_loop_prio() instead of
event_loop() in their main event loops.

Because of these features, overhead of implementation and runtime
performance is minimized.

[1] http://lists.wpkg.org/pipermail/sheepdog/2012-December/007426.html

Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
 include/event.h |   14 +++++++++++-
 lib/event.c     |   61 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 68 insertions(+), 7 deletions(-)

diff --git a/include/event.h b/include/event.h
index b0e7552..65277fa 100644
--- a/include/event.h
+++ b/include/event.h
@@ -2,16 +2,19 @@
 #define __EVENT_H__
 
 #include "list.h"
+#include <limits.h>
 
 struct event_info;
 
 typedef void (*event_handler_t)(int fd, int events, void *data);
 
 int init_event(int nr);
-int register_event(int fd, event_handler_t h, void *data);
+int register_event_prio(int fd, event_handler_t h, void *data, int prio);
 void unregister_event(int fd);
 int modify_event(int fd, unsigned int events);
 void event_loop(int timeout);
+void event_loop_prio(int timeout);
+void event_force_refresh(void);
 
 struct timer {
 	void (*callback)(void *);
@@ -20,4 +23,13 @@ struct timer {
 
 void add_timer(struct timer *t, unsigned int mseconds);
 
+#define EVENT_PRIO_MAX     INT_MAX
+#define EVENT_PRIO_DEFAULT 0
+#define EVENT_PRIO_MIN     INT_MIN
+
+static inline int register_event(int fd, event_handler_t h, void *data)
+{
+return register_event_prio(fd, h, data, EVENT_PRIO_DEFAULT);
+}
+
 #endif
diff --git a/lib/event.c b/lib/event.c
index 536b285..5b15925 100644
--- a/lib/event.c
+++ b/lib/event.c
@@ -69,10 +69,17 @@ struct event_info {
 	int fd;
 	void *data;
 	struct list_head ei_list;
+	int prio;
 };
 
+static struct epoll_event *events;
+static int nr_events;
+
 int init_event(int nr)
 {
+	nr_events = nr;
+	events = xcalloc(nr_events, sizeof(struct epoll_event));
+
 	efd = epoll_create(nr);
 	if (efd < 0) {
 		sd_eprintf("failed to create epoll fd");
@@ -92,7 +99,7 @@ static struct event_info *lookup_event(int fd)
 	return NULL;
 }
 
-int register_event(int fd, event_handler_t h, void *data)
+int register_event_prio(int fd, event_handler_t h, void *data, int prio)
 {
 	int ret;
 	struct epoll_event ev;
@@ -102,6 +109,7 @@ int register_event(int fd, event_handler_t h, void *data)
 	ei->fd = fd;
 	ei->handler = h;
 	ei->data = data;
+	ei->prio = prio;
 
 	memset(&ev, 0, sizeof(ev));
 	ev.events = EPOLLIN;
@@ -134,7 +142,7 @@ void unregister_event(int fd)
 	free(ei);
 }
 
-int modify_event(int fd, unsigned int events)
+int modify_event(int fd, unsigned int new_events)
 {
 	int ret;
 	struct epoll_event ev;
@@ -147,7 +155,7 @@ int modify_event(int fd, unsigned int events)
 	}
 
 	memset(&ev, 0, sizeof(ev));
-	ev.events = events;
+	ev.events = new_events;
 	ev.data.ptr = ei;
 
 	ret = epoll_ctl(efd, EPOLL_CTL_MOD, fd, &ev);
@@ -158,12 +166,38 @@ int modify_event(int fd, unsigned int events)
 	return 0;
 }
 
-void event_loop(int timeout)
+static bool event_loop_refresh;
+
+void event_force_refresh(void)
+{
+	event_loop_refresh = true;
+}
+
+static int epoll_event_cmp(const void *_a, const void *_b)
+{
+	struct event_info *a, *b;
+
+	a = (struct event_info *)((struct epoll_event *)_a)->data.ptr;
+	b = (struct event_info *)((struct epoll_event *)_b)->data.ptr;
+
+	/* we need sort event_info array in reverse order */
+	if (a->prio < b->prio)
+		return 1;
+	else if (b->prio < a->prio)
+		return -1;
+
+	return 0;
+}
+
+static void do_event_loop(int timeout, bool sort_with_prio)
 {
 	int i, nr;
-	struct epoll_event events[128];
 
-	nr = epoll_wait(efd, events, ARRAY_SIZE(events), TICK * 1000);
+refresh:
+	nr = epoll_wait(efd, events, nr_events, TICK * 1000);
+	if (sort_with_prio)
+		qsort(events, nr, sizeof(struct epoll_event), epoll_event_cmp);
+
 	if (nr < 0) {
 		if (errno == EINTR)
 			return;
@@ -175,6 +209,21 @@ void event_loop(int timeout)
 
 			ei = (struct event_info *)events[i].data.ptr;
 			ei->handler(ei->fd, events[i].events, ei->data);
+
+			if (event_loop_refresh) {
+				event_loop_refresh = false;
+				goto refresh;
+			}
 		}
 	}
 }
+
+void event_loop(int timeout)
+{
+	do_event_loop(timeout, false);
+}
+
+void event_loop_prio(int timeout)
+{
+	do_event_loop(timeout, true);
+}
-- 
1.7.2.5




More information about the sheepdog mailing list