diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 02:58:10 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 02:58:10 +0200 |
commit | 50596be0d5ff65c79060bcd858cda33a974a0dc1 (patch) | |
tree | 4c5532f9924f9afc47af95d3cdfa7141e4e901c9 /lib/workqueue.c | |
parent | Add replace-as option to remove-private-as (diff) | |
download | frr-50596be0d5ff65c79060bcd858cda33a974a0dc1.tar.xz frr-50596be0d5ff65c79060bcd858cda33a974a0dc1.zip |
Some small enhancements to thread and workqueue libraries in zebra:
- Allow work queues to specify the yield duration for corresponding background thread
- Support using specified yield duration in thread yielding
- During work queue processing, if using a single list element with a meta-queue
(like done in Zebra), do not exit after each element is processed, instead
update the next-node upon a WQ_REQUEUE so that the WQ processing continues
and is terminated by the yield logic.
- Enhance work queue debug output
Diffstat (limited to 'lib/workqueue.c')
-rw-r--r-- | lib/workqueue.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/lib/workqueue.c b/lib/workqueue.c index 61643bf81..a7f4b7071 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -84,6 +84,7 @@ work_queue_new (struct thread_master *m, const char *queue_name) /* Default values, can be overriden by caller */ new->spec.hold = WORK_QUEUE_DEFAULT_HOLD; + new->spec.yield = THREAD_YIELD_TIME_SLOT; return new; } @@ -113,6 +114,9 @@ work_queue_schedule (struct work_queue *wq, unsigned int delay) { wq->thread = thread_add_background (wq->master, work_queue_run, wq, delay); + /* set thread yield time, if needed */ + if (wq->thread && wq->spec.yield != THREAD_YIELD_TIME_SLOT) + thread_set_yield_time (wq->thread, wq->spec.yield); return 1; } else @@ -174,27 +178,27 @@ DEFUN(show_work_queues, struct work_queue *wq; vty_out (vty, - "%c %8s %5s %8s %21s%s", - ' ', "List","(ms) ","Q. Runs","Cycle Counts ", + "%c %8s %5s %8s %8s %21s%s", + ' ', "List","(ms) ","Q. Runs","Yields","Cycle Counts ", VTY_NEWLINE); vty_out (vty, - "%c %8s %5s %8s %7s %6s %6s %s%s", + "%c %8s %5s %8s %8s %7s %6s %8s %6s %s%s", 'P', "Items", "Hold", - "Total", - "Best","Gran.","Avg.", + "Total","Total", + "Best","Gran.","Total","Avg.", "Name", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO ((&work_queues), node, wq)) { - vty_out (vty,"%c %8d %5d %8ld %7d %6d %6u %s%s", + vty_out (vty,"%c %8d %5d %8ld %8ld %7d %6d %8ld %6u %s%s", (CHECK_FLAG (wq->flags, WQ_UNPLUGGED) ? ' ' : 'P'), listcount (wq->items), wq->spec.hold, - wq->runs, - wq->cycles.best, wq->cycles.granularity, + wq->runs, wq->yields, + wq->cycles.best, wq->cycles.granularity, wq->cycles.total, (wq->runs) ? (unsigned int) (wq->cycles.total / wq->runs) : 0, wq->name, @@ -250,7 +254,8 @@ work_queue_run (struct thread *thread) assert (wq && wq->items); /* calculate cycle granularity: - * list iteration == 1 cycle + * list iteration == 1 run + * listnode processing == 1 cycle * granularity == # cycles between checks whether we should yield. * * granularity should be > 0, and can increase slowly after each run to @@ -309,6 +314,14 @@ work_queue_run (struct thread *thread) { item->ran--; work_queue_item_requeue (wq, node); + /* If a single node is being used with a meta-queue (e.g., zebra), + * update the next node as we don't want to exit the thread and + * reschedule it after every node. By definition, WQ_REQUEUE is + * meant to continue the processing; the yield logic will kick in + * to terminate the thread when time has exceeded. + */ + if (nnode == NULL) + nnode = node; break; } case WQ_RETRY_NOW: @@ -346,7 +359,7 @@ stats: /* we yielded, check whether granularity should be reduced */ if (yielded && (cycles < wq->cycles.granularity)) { - wq->cycles.granularity = ((cycles > 0) ? cycles + wq->cycles.granularity = ((cycles > 0) ? cycles : WORK_QUEUE_MIN_GRANULARITY); } /* otherwise, should granularity increase? */ @@ -354,7 +367,7 @@ stats: { if (cycles > wq->cycles.best) wq->cycles.best = cycles; - + /* along with yielded check, provides hysteresis for granularity */ if (cycles > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR * WQ_HYSTERESIS_FACTOR)) @@ -366,6 +379,8 @@ stats: wq->runs++; wq->cycles.total += cycles; + if (yielded) + wq->yields++; #if 0 printf ("%s: cycles %d, new: best %d, worst %d\n", |