summaryrefslogtreecommitdiffstats
path: root/lib/workqueue.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2016-03-30 13:44:03 +0300
committerTimo Teräs <timo.teras@iki.fi>2016-03-30 14:29:40 +0300
commit8cb40c91cdfb00ddf04e88d3ecd40403890d90f7 (patch)
tree6d6a3de27525820abb740f1fa8347b6f03986bad /lib/workqueue.c
parent86c5d2ee68f7b9c00ae4aeb5c8b3c5d82c5ebffc (diff)
downloadquagga-8cb40c91cdfb00ddf04e88d3ecd40403890d90f7.tar.bz2
quagga-8cb40c91cdfb00ddf04e88d3ecd40403890d90f7.tar.xz
cumulus take-3cumulus-take-3
Diffstat (limited to 'lib/workqueue.c')
-rw-r--r--lib/workqueue.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/lib/workqueue.c b/lib/workqueue.c
index b1a5d5bf..d2d002f2 100644
--- a/lib/workqueue.c
+++ b/lib/workqueue.c
@@ -88,6 +88,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;
}
@@ -123,6 +124,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
@@ -184,27 +188,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,
@@ -260,7 +264,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
@@ -319,6 +324,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:
@@ -356,7 +369,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? */
@@ -364,7 +377,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))
@@ -376,6 +389,8 @@ stats:
wq->runs++;
wq->cycles.total += cycles;
+ if (yielded)
+ wq->yields++;
#if 0
printf ("%s: cycles %d, new: best %d, worst %d\n",