Have actor_poll take an indication from the outer event loop of how many
ticks of ACTOR_RESOLUTION have passed, and return how many ticks into
the future it would like to be called again.

Then in event_loop, try and keep the poll timeouts as long as possible
without delaying actors or screwing up their timeouts too badly.

First draft sent to me by Adam Jackson, but I've reworked everything
except the actor_check changes considerably so blame me.

Bugzilla: https://bugzilla.redhat.com/458213
Cc: Adam Jackson <a...@redhat.com>
Signed-off-by: Chris Leech <cle...@redhat.com>
---
 usr/Makefile     |  4 ++--
 usr/actor.c      | 23 ++++++++++++++++-------
 usr/actor.h      |  2 +-
 usr/event_poll.c | 42 ++++++++++++++++++++++++++++++++++++++----
 4 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/usr/Makefile b/usr/Makefile
index 3d8ee22..550fdff 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -55,14 +55,14 @@ all: $(PROGRAMS)
 
 iscsid: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(DISCOVERY_SRCS) \
        iscsid.o session_mgmt.o discoveryd.o
-       $(CC) $(CFLAGS) $^ -o $@  -L../utils/open-isns -lisns
+       $(CC) $(CFLAGS) $^ -o $@  -L../utils/open-isns -lisns -lrt
 
 iscsiadm: $(ISCSI_LIB_SRCS) $(DISCOVERY_SRCS) iscsiadm.o session_mgmt.o
        $(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns
 
 iscsistart: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(FW_BOOT_SRCS) \
                iscsistart.o statics.o
-       $(CC) $(CFLAGS) -static $^ -o $@
+       $(CC) $(CFLAGS) -static $^ -o $@ -lrt
 clean:
        rm -f *.o $(PROGRAMS) .depend $(LIBSYS)
 
diff --git a/usr/actor.c b/usr/actor.c
index 7f93e76..3685a41 100644
--- a/usr/actor.c
+++ b/usr/actor.c
@@ -193,17 +193,18 @@ actor_timer_mod(actor_t *thread, uint32_t timeout, void 
*data)
        return 0;
 }
 
-static void
+static uint64_t
 actor_check(uint64_t current_time)
 {
        struct actor *thread, *tmp;
+       uint64_t ret;
 
        list_for_each_entry_safe(thread, tmp, &pend_list, list) {
-               if (actor_diff_time(thread, current_time)) {
+               if ((ret = actor_diff_time(thread, current_time))) {
                        log_debug(7, "thread %08lx wait some more",
                                (long)thread);
                        /* wait some more */
-                       break;
+                       return ret;
                }
 
                /* it is time to schedule this entry */
@@ -220,12 +221,17 @@ actor_check(uint64_t current_time)
                log_debug(7, "thread %08lx now in actor_list",
                        (long)thread);
        }
+
+       return -1LL;
 }
 
-void
-actor_poll(void)
+uint64_t
+actor_poll(uint64_t ticks_expired)
 {
        struct actor *thread;
+       uint64_t ticks_to_wait;
+
+       actor_jiffies += ticks_expired;
 
        /* check that there are no any concurrency */
        if (poll_in_progress) {
@@ -233,7 +239,7 @@ actor_poll(void)
        }
 
        /* check the wait list */
-       actor_check(actor_jiffies);
+       ticks_to_wait = actor_check(actor_jiffies);
 
        /* the following code to check in the main data path */
        poll_in_progress = 1;
@@ -252,6 +258,9 @@ actor_poll(void)
        }
        poll_in_progress = 0;
 
+       if (!list_empty(&poll_list))
+               ticks_to_wait = 1;
+
        while (!list_empty(&poll_list)) {
                thread = list_entry(poll_list.next, struct actor, list);
                list_del_init(&thread->list);
@@ -266,5 +275,5 @@ actor_poll(void)
                        (long)thread);
        }
 
-       actor_jiffies++;
+       return ticks_to_wait;
 }
diff --git a/usr/actor.h b/usr/actor.h
index 4c1ae60..eb624ed 100644
--- a/usr/actor.h
+++ b/usr/actor.h
@@ -48,7 +48,7 @@ extern void actor_schedule(actor_t *thread);
 extern void actor_timer(actor_t *thread, uint32_t timeout,
                        void (*callback)(void *), void *data);
 extern int actor_timer_mod(actor_t *thread, uint32_t new_timeout, void *data);
-extern void actor_poll(void);
+extern uint64_t actor_poll(uint64_t ticks_expired);
 extern void actor_init(void);
 
 #endif /* ACTOR_H */
diff --git a/usr/event_poll.c b/usr/event_poll.c
index f36fec1..dcbb79a 100644
--- a/usr/event_poll.c
+++ b/usr/event_poll.c
@@ -121,17 +121,37 @@ static int shutdown_wait_pids(void)
 static int event_loop_stop;
 static queue_task_t *shutdown_qtask; 
 
-
 void event_loop_exit(queue_task_t *qtask)
 {
        shutdown_qtask = qtask;
        event_loop_stop = 1;
 }
 
+#include <time.h>
+
+uint64_t elapsed_ticks(struct timespec *start, struct timespec *end)
+{
+       struct timespec elapsed;
+
+       if ((end->tv_nsec - start->tv_nsec) < 0) {
+               elapsed.tv_sec = end->tv_sec - start->tv_sec - 1;
+               elapsed.tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec;
+       } else{
+               elapsed.tv_sec = end->tv_sec - start->tv_sec;
+               elapsed.tv_nsec = end->tv_nsec - start->tv_nsec;
+       }
+       return (elapsed.tv_sec * (1000 / ACTOR_RESOLUTION)) +
+              (elapsed.tv_nsec / (1000000 * ACTOR_RESOLUTION));
+}
+
 void event_loop(struct iscsi_ipc *ipc, int control_fd, int mgmt_ipc_fd)
 {
        struct pollfd poll_array[POLL_MAX];
        int res, has_shutdown_children = 0;
+       int poll_timeout;
+       struct timespec last_actor_poll;
+       struct timespec now;
+       uint64_t elapsed = 0;
 
        poll_array[POLL_CTRL].fd = control_fd;
        poll_array[POLL_CTRL].events = POLLIN;
@@ -149,7 +169,13 @@ void event_loop(struct iscsi_ipc *ipc, int control_fd, int 
mgmt_ipc_fd)
                                break;
                }
 
-               res = poll(poll_array, POLL_MAX, ACTOR_RESOLUTION);
+               poll_timeout = actor_poll(elapsed) * ACTOR_RESOLUTION;
+               if (poll_timeout > 0)
+                       /* we only need this if an actor is waiting */
+                       clock_gettime(CLOCK_MONOTONIC, &last_actor_poll);
+
+               res = poll(poll_array, POLL_MAX, poll_timeout);
+
                if (res > 0) {
                        log_debug(6, "poll result %d", res);
                        if (poll_array[POLL_CTRL].revents)
@@ -165,14 +191,22 @@ void event_loop(struct iscsi_ipc *ipc, int control_fd, 
int mgmt_ipc_fd)
                                          "exiting", res, errno);
                                break;
                        }
-               } else
-                       actor_poll();
+               }
                reap_proc();
                /*
                 * flush sysfs cache since kernel objs may
                 * have changed as a result of handling op
                 */
                sysfs_cleanup();
+
+               if (poll_timeout > 0) {
+                       clock_gettime(CLOCK_MONOTONIC, &now);
+                       elapsed = elapsed_ticks(&last_actor_poll, &now);
+               } else {
+                       /* negative timeout means there are no actors waiting
+                        * so indicated elapsed ticks doesn't matter */
+                       elapsed = 1;
+               }
        }
        if (shutdown_qtask)
                mgmt_ipc_write_rsp(shutdown_qtask, ISCSI_SUCCESS);
-- 
1.8.1.4

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to open-iscsi+unsubscr...@googlegroups.com.
To post to this group, send email to open-iscsi@googlegroups.com.
Visit this group at http://groups.google.com/group/open-iscsi?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to