Empty queues are kept in scheduler priority queues for
performance reasons. The scheduler moved to the next priority
queue after seeing an empty queue, which resulted sometimes
scheduler to return zero events, although there were events
available deeper in the priority queue.

This patch keeps scheduler scheduling a priority queue until an
event is found or the queue is empty (over empty or destroyed
queues).

This fixes bug https://bugs.linaro.org/show_bug.cgi?id=2457

Signed-off-by: Petri Savolainen <petri.savolai...@nokia.com>
---
 platform/linux-generic/odp_schedule.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/platform/linux-generic/odp_schedule.c 
b/platform/linux-generic/odp_schedule.c
index 8405423..e08de54 100644
--- a/platform/linux-generic/odp_schedule.c
+++ b/platform/linux-generic/odp_schedule.c
@@ -552,7 +552,7 @@ static int do_schedule(odp_queue_t *out_queue, odp_event_t 
out_ev[],
 
                id = (sched_local.thr + offset) & (QUEUES_PER_PRIO - 1);
 
-               for (j = 0; j < QUEUES_PER_PRIO; j++, id++) {
+               for (j = 0; j < QUEUES_PER_PRIO;) {
                        odp_queue_t  pri_q;
                        int num;
                        int grp;
@@ -562,14 +562,23 @@ static int do_schedule(odp_queue_t *out_queue, 
odp_event_t out_ev[],
                        if (id >= QUEUES_PER_PRIO)
                                id = 0;
 
-                       if (odp_unlikely((sched->pri_mask[i] & (1 << id)) == 0))
+                       /* No queues created for this priority queue */
+                       if (odp_unlikely((sched->pri_mask[i] & (1 << id))
+                           == 0)) {
+                               j++;
+                               id++;
                                continue;
+                       }
 
                        pri_q = sched->pri_queue[i][id];
                        ev    = odp_queue_deq(pri_q);
 
-                       if (ev == ODP_EVENT_INVALID)
+                       /* Priority queue empty */
+                       if (ev == ODP_EVENT_INVALID) {
+                               j++;
+                               id++;
                                continue;
+                       }
 
                        buf       = odp_buffer_from_event(ev);
                        sched_cmd = odp_buffer_addr(buf);
@@ -584,6 +593,9 @@ static int do_schedule(odp_queue_t *out_queue, odp_event_t 
out_ev[],
                                 */
                                if (odp_queue_enq(pri_q, ev))
                                        ODP_ABORT("schedule failed\n");
+
+                               j++;
+                               id++;
                                continue;
                        }
 
@@ -600,13 +612,15 @@ static int do_schedule(odp_queue_t *out_queue, 
odp_event_t out_ev[],
                                                       max_deq);
 
                        if (num < 0) {
-                               /* Destroyed queue */
+                               /* Destroyed queue. Continue scheduling the same
+                                * priority queue. */
                                sched_cb_queue_destroy_finalize(qi);
                                continue;
                        }
 
                        if (num == 0) {
-                               /* Remove empty queue from scheduling */
+                               /* Remove empty queue from scheduling. Continue
+                                * scheduling the same priority queue. */
                                continue;
                        }
 
-- 
2.8.1

Reply via email to