VPP-425: Scheduler policy & priority configuration 02/3102/4
authorPavel Kotucek <pkotucek@cisco.com>
Fri, 23 Sep 2016 06:54:14 +0000 (08:54 +0200)
committerDamjan Marion <dmarion.lists@gmail.com>
Tue, 27 Sep 2016 09:04:22 +0000 (09:04 +0000)
Add ability to hadle scheduling policy and priority via config file.
CPU section contains new items to specify scheduling policy and
priority:

cpu {
scheduler-priority <num>
scheduler-policy [other | batch | idle | fifo | rr ]
}

Change-Id: Ie20765280e458e1d7deb4a8c66daaa69793f795e
Signed-off-by: Pavel Kotucek <pkotucek@cisco.com>
vlib/vlib/threads.c
vlib/vlib/threads.h
vlib/vlib/threads_cli.c

index dc9b1bb..67c57a6 100644 (file)
@@ -13,7 +13,6 @@
  * limitations under the License.
  */
 #define _GNU_SOURCE
-#include <sched.h>
 
 #include <signal.h>
 #include <math.h>
@@ -216,6 +215,17 @@ vlib_thread_init (vlib_main_t * vm)
   w->lwp = syscall (SYS_gettid);
   tm->n_vlib_mains = 1;
 
+  if (tm->sched_policy != ~0)
+    {
+      struct sched_param sched_param;
+      if (!sched_getparam (w->lwp, &sched_param))
+       {
+         if (tm->sched_priority != ~0)
+           sched_param.sched_priority = tm->sched_priority;
+         sched_setscheduler (w->lwp, tm->sched_policy, &sched_param);
+       }
+    }
+
   /* assign threads to cores and set n_vlib_mains */
   tr = tm->next;
 
@@ -995,6 +1005,20 @@ vlib_worker_thread_node_runtime_update (void)
     }
 }
 
+u32
+unformat_sched_policy (unformat_input_t * input, va_list * args)
+{
+  u32 *r = va_arg (*args, u32 *);
+
+  if (0);
+#define _(v,f,s) else if (unformat (input, s)) *r = SCHED_POLICY_##f;
+  foreach_sched_policy
+#undef _
+    else
+    return 0;
+  return 1;
+}
+
 static clib_error_t *
 cpu_config (vlib_main_t * vm, unformat_input_t * input)
 {
@@ -1007,7 +1031,10 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input)
   u32 count;
 
   tm->thread_registrations_by_name = hash_create_string (0, sizeof (uword));
+
   tm->n_thread_stacks = 1;     /* account for main thread */
+  tm->sched_policy = ~0;
+  tm->sched_priority = ~0;
 
   tr = tm->next;
 
@@ -1061,11 +1088,18 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input)
          tr->coremask = bitmap;
          tr->count = clib_bitmap_count_set_bits (tr->coremask);
        }
+      else
+       if (unformat
+           (input, "scheduler-policy %U", unformat_sched_policy,
+            &tm->sched_policy))
+       ;
+      else if (unformat (input, "scheduler-prio %u", &tm->sched_priority))
+       ;
       else if (unformat (input, "%s %u", &name, &count))
        {
          p = hash_get_mem (tm->thread_registrations_by_name, name);
          if (p == 0)
-           return clib_error_return (0, "no such thread type '%s'", name);
+           return clib_error_return (0, "no such thread type '%s'", name);
 
          tr = (vlib_thread_registration_t *) p[0];
          if (tr->fixed_count)
@@ -1077,6 +1111,21 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input)
        break;
     }
 
+  if (tm->sched_policy != ~0)
+    {
+      if (tm->sched_priority != ~0
+         && (tm->sched_policy == SCHED_FIFO || tm->sched_policy == SCHED_RR))
+       {
+         u32 prio_max = sched_get_priority_max (tm->sched_policy);
+         u32 prio_min = sched_get_priority_min (tm->sched_policy);
+         if (tm->sched_priority > prio_max)
+           tm->sched_priority = prio_max;
+         if (tm->sched_priority < prio_min)
+           tm->sched_priority = prio_min;
+       }
+      else
+       tm->sched_priority = 0;
+    }
   tr = tm->next;
 
   if (!tm->thread_prefix)
index 4283b70..589d1f3 100644 (file)
@@ -16,6 +16,7 @@
 #define included_vlib_threads_h
 
 #include <vlib/main.h>
+#include <linux/sched.h>
 
 vlib_main_t **vlib_mains;
 
@@ -257,6 +258,21 @@ typedef struct vlib_efd_t
   u8 pad;
 } vlib_efd_t;
 
+#define foreach_sched_policy \
+  _(SCHED_OTHER, OTHER, "other") \
+  _(SCHED_BATCH, BATCH, "batch") \
+  _(SCHED_IDLE, IDLE, "idle")   \
+  _(SCHED_FIFO, FIFO, "fifo")   \
+  _(SCHED_RR, RR, "rr")
+
+typedef enum
+{
+#define _(v,f,s) SCHED_POLICY_##f = v,
+  foreach_sched_policy
+#undef _
+    SCHED_POLICY_N,
+} sched_policy_t;
+
 typedef struct
 {
   /* Link list of registrations, built by constructors */
@@ -314,6 +330,12 @@ typedef struct
   /* worker thread initialization barrier */
   volatile u32 worker_thread_release;
 
+  /* scheduling policy */
+  u32 sched_policy;
+
+  /* scheduling policy priority */
+  u32 sched_priority;
+
 } vlib_thread_main_t;
 
 vlib_thread_main_t vlib_thread_main;
index 9ab4edc..179906b 100644 (file)
 #include <vlib/vlib.h>
 
 #include <vlib/threads.h>
+#include <linux/sched.h>
+
+u8 *
+format_sched_policy (u8 * s, va_list * args)
+{
+  u32 i = va_arg (*args, u32);
+  u8 *t = 0;
+
+  switch (i)
+    {
+#define _(v,f,str) case SCHED_POLICY_##f: t = (u8 *) str; break;
+      foreach_sched_policy
+#undef _
+    }
+  s = format (s, "%-6s ", t);
+  return s;
+}
 
 static clib_error_t *
 show_threads_fn (vlib_main_t * vm,
@@ -25,8 +42,8 @@ show_threads_fn (vlib_main_t * vm,
   vlib_worker_thread_t *w;
   int i;
 
-  vlib_cli_output (vm, "%-7s%-20s%-12s%-8s%-7s%-7s%-7s%-10s",
-                  "ID", "Name", "Type", "LWP",
+  vlib_cli_output (vm, "%-7s%-20s%-12s%-8s%-7s%-9s%-7s%-7s%-7s%-10s",
+                  "ID", "Name", "Type", "LWP", "Policy", "Priority",
                   "lcore", "Core", "Socket", "State");
 
 #if !defined(__powerpc64__)
@@ -40,6 +57,14 @@ show_threads_fn (vlib_main_t * vm,
                     w->name ? w->name : (u8 *) "",
                     w->registration ? w->registration->name : "", w->lwp);
 
+      line =
+       format (line, "%U", format_sched_policy, sched_getscheduler (w->lwp));
+
+      struct sched_param sched_param;
+      line = format (line, "%8d ",
+                    (!sched_getparam (w->lwp, &sched_param)) ?
+                    sched_param.sched_priority : -1);
+
 #if DPDK==1
       int lcore = w->dpdk_lcore_id;
       if (lcore > -1)