]> git.puffer.fish Git - matthieu/frr.git/commitdiff
2005-11-14 Paul Jakma <paul.jakma@sun.com>
authorpaul <paul>
Mon, 14 Nov 2005 12:07:47 +0000 (12:07 +0000)
committerpaul <paul>
Mon, 14 Nov 2005 12:07:47 +0000 (12:07 +0000)
* (general) Add state to detect queue floods.  There's no sense
  trying to be sparing of CPU resources, if the queue is
  flooding and using ever more memory resources. we should just
  get on with clearing the queue.
  The sense of delay and hold were wrong way around, fix.
* workqueue.h: (struct work_queue) Add status bitfield.  Add
  'flood' integer to workqueue spec.  Add runs_since_clear
  counter to workqueue.
* workqueue.c: (work_queue_new) set defaults for delay, hold
  and flood.
  (work_queue_add) initial schedule should use delay, not hold.
  (show_work_queues) Print flood field, conserve whitespace.
  (work_queue_unplug) use delay, not hold.
  (work_queue_run) consecutive runs should be seperated by hold
  time, not delay.
  Keep track of number of consecutive runs, go into 'overdrive'
  if queue is being flooded, we can't avoid making heavy use of
  resources, better to use CPU than ever more RAM.

lib/ChangeLog
lib/workqueue.c
lib/workqueue.h

index 106de4772ccdc110fb82628cb6d538a8aa0a6718..b6407c4a68701a819b862db25a38232ebf42fe09 100644 (file)
@@ -1,4 +1,25 @@
-2005-11-12 Paul Jakma <paul.jakma@sun.com>
+2005-11-14 Paul Jakma <paul.jakma@sun.com>
+
+       * (general) Add state to detect queue floods.  There's no sense
+         trying to be sparing of CPU resources, if the queue is
+         flooding and using ever more memory resources. we should just
+         get on with clearing the queue.
+         The sense of delay and hold were wrong way around, fix.
+       * workqueue.h: (struct work_queue) Add status bitfield.  Add
+         'flood' integer to workqueue spec.  Add runs_since_clear
+         counter to workqueue.
+       * workqueue.c: (work_queue_new) set defaults for delay, hold
+         and flood.
+         (work_queue_add) initial schedule should use delay, not hold.
+         (show_work_queues) Print flood field, conserve whitespace.
+         (work_queue_unplug) use delay, not hold.
+         (work_queue_run) consecutive runs should be seperated by hold
+         time, not delay.
+         Keep track of number of consecutive runs, go into 'overdrive'
+         if queue is being flooded, we can't avoid making heavy use of 
+         resources, better to use CPU than ever more RAM.
+
+2005-11-05 Paul Jakma <paul.jakma@sun.com>
 
        * routemap.c: (vty_show_route_map_entry) call action is
          seperate from exit action, latter should still be printed
index bac413028f2247e0480eb6a8422db46aa0668c8c..c2ff10db1bcb7bd4ae319cbc9ad0d5b9956780ce 100644 (file)
@@ -80,7 +80,12 @@ work_queue_new (struct thread_master *m, const char *queue_name)
   listnode_add (&work_queues, new);
   
   new->cycles.granularity = WORK_QUEUE_MIN_GRANULARITY;
-  
+
+  /* Default values, can be overriden by caller */
+  new->spec.delay = WORK_QUEUE_DEFAULT_DELAY;
+  new->spec.hold = WORK_QUEUE_DEFAULT_HOLD;
+  new->spec.flood = WORK_QUEUE_DEFAULT_FLOOD;
+    
   return new;
 }
 
@@ -128,7 +133,7 @@ work_queue_add (struct work_queue *wq, void *data)
   item->data = data;
   listnode_add (wq->items, item);
   
-  work_queue_schedule (wq, wq->spec.hold);
+  work_queue_schedule (wq, wq->spec.delay);
   
   return;
 }
@@ -167,12 +172,12 @@ DEFUN(show_work_queues,
   struct work_queue *wq;
   
   vty_out (vty, 
-           "%c %8s  %11s  %8s %21s%s",
-           ' ', "List","(ms)   ","Q. Runs","Cycle Counts   ",
+           "%c%c %8s %11s %8s %21s%s",
+           ' ', ' ', "List","(ms)   ","Q. Runs","Cycle Counts   ",
            VTY_NEWLINE);
   vty_out (vty,
-           "%c %8s  %5s %5s  %8s  %7s %6s %6s %s%s",
-           ' ',
+           "%c%c %8s %5s %5s %8s %7s %6s %6s %s%s",
+           'P', 'F',
            "Items",
            "Delay","Hold",
            "Total",
@@ -182,8 +187,9 @@ DEFUN(show_work_queues,
  
   for (ALL_LIST_ELEMENTS_RO ((&work_queues), node, wq))
     {
-      vty_out (vty,"%c %8d  %5d %5d  %8ld  %7d %6d %6u %s%s",
+      vty_out (vty,"%c%c %8d %5d %5d %8ld %7d %6d %6u %s%s",
                (wq->flags == WQ_PLUGGED ? 'P' : ' '),
+               (wq->runs_since_clear >= wq->spec.flood ? 'F' : ' '),
                listcount (wq->items),
                wq->spec.delay, wq->spec.hold,
                wq->runs,
@@ -220,7 +226,7 @@ work_queue_unplug (struct work_queue *wq)
   wq->flags = WQ_UNPLUGGED;
 
   /* if thread isnt already waiting, add one */
-  work_queue_schedule (wq, wq->spec.hold);
+  work_queue_schedule (wq, wq->spec.delay);
 }
 
 /* timer thread to process a work queue
@@ -364,9 +370,19 @@ stats:
   
   /* Is the queue done yet? If it is, call the completion callback. */
   if (listcount (wq->items) > 0)
-    work_queue_schedule (wq, wq->spec.delay);
-  else if (wq->spec.completion_func)
-    wq->spec.completion_func (wq);
+    {
+      if (++(wq->runs_since_clear) < wq->spec.flood)
+        work_queue_schedule (wq, wq->spec.hold);
+      else
+        work_queue_schedule (wq, 0); /* queue flooded, go into overdrive */
+    }
+  else
+    {
+      wq->runs_since_clear = 0;
+      
+      if (wq->spec.completion_func)
+        wq->spec.completion_func (wq);
+    }
   
   return 0;
 }
index 626d8e6cb935edcb06a9cf779bb823ff360ebf38..15c72f62f325abd4d4e1108f9ba209c82bcdbfc9 100644 (file)
@@ -25,8 +25,9 @@
 #define _QUAGGA_WORK_QUEUE_H
 
 /* Work queue default hold and cycle times - millisec */
-#define WORK_QUEUE_DEFAULT_HOLD  50  /* hold time for initial run of a queue */
-#define WORK_QUEUE_DEFAULT_DELAY 10  /* minimum delay between queue runs */
+#define WORK_QUEUE_DEFAULT_HOLD  50  /* hold-time between runs of a queue */
+#define WORK_QUEUE_DEFAULT_DELAY 10  /* minimum delay for queue runs */
+#define WORK_QUEUE_DEFAULT_FLOOD 40   /* flood factor, ~2s with prev values */
 
 /* action value, for use by item processor and item error handlers */
 typedef enum
@@ -56,12 +57,17 @@ enum work_queue_flags
 
 struct work_queue
 {
+  /* Everything but the specification struct is private */
   struct thread_master *master;       /* thread master */
   struct thread *thread;              /* thread, if one is active */
   char *name;                         /* work queue name */
+  char status;                        /* status */
+#define WQ_STATE_FLOODED       (1 << 0)
   enum work_queue_flags flags;         /* flags */
   
-  /* specification for this work queue */
+  /* Specification for this work queue.
+   * Public, must be set before use by caller. May be modified at will.
+   */
   struct {
     /* work function to process items with */
     wq_item_status (*workfunc) (void *);
@@ -80,11 +86,24 @@ struct work_queue
 
     unsigned int hold; /* hold time for first run, in ms */
     unsigned int delay; /* min delay between queue runs, in ms */
+    
+    unsigned int flood; /* number of queue runs after which we consider
+                         * queue to be flooded, where the runs are
+                         * consecutive and each has used its full slot,
+                         * and the queue has still not been cleared. If
+                         * the queue is flooded, then we try harder to
+                         * clear it by ignoring the hold and delay
+                         * times. No point sparing CPU resources just
+                         * to use ever more memory resources.
+                         */
   } spec;
   
   /* remaining fields should be opaque to users */
   struct list *items;                 /* queue item list */
   unsigned long runs;                 /* runs count */
+  unsigned int runs_since_clear;      /* number of runs since queue was
+                                       * last cleared
+                                       */
   
   struct {
     unsigned int best;