VPP-425: Scheduler policy & priority configuration
[vpp.git] / vlib / vlib / threads.c
index 72f340e..67c57a6 100644 (file)
@@ -13,7 +13,6 @@
  * limitations under the License.
  */
 #define _GNU_SOURCE
-#include <sched.h>
 
 #include <signal.h>
 #include <math.h>
@@ -77,6 +76,18 @@ os_get_cpu_number (void)
   return n;
 }
 
+uword
+os_get_ncpus (void)
+{
+  u32 len;
+
+  len = vec_len (vlib_thread_stacks);
+  if (len == 0)
+    return 1;
+  else
+    return len;
+}
+
 void
 vlib_set_thread_name (char *name)
 {
@@ -88,7 +99,7 @@ vlib_set_thread_name (char *name)
     {
       rv = pthread_setname_np (thread, name);
       if (rv)
-        clib_warning ("pthread_setname_np returned %d", rv);
+       clib_warning ("pthread_setname_np returned %d", rv);
     }
 }
 
@@ -120,7 +131,7 @@ vlib_sysfs_list_to_bitmap (char *filename)
          unformat_init_string (&in, (char *) buffer,
                                strlen ((char *) buffer));
          if (unformat (&in, "%U", unformat_bitmap_list, &r) != 1)
-            clib_warning ("unformat_bitmap_list failed");
+           clib_warning ("unformat_bitmap_list failed");
          unformat_free (&in);
        }
       vec_free (buffer);
@@ -204,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;
 
@@ -983,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)
 {
@@ -995,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;
 
@@ -1049,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)
@@ -1065,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)
@@ -1325,6 +1386,8 @@ vlib_worker_thread_internal (vlib_main_t * vm)
   vlib_node_main_t *nm = &vm->node_main;
   u64 cpu_time_now = clib_cpu_time_now ();
 
+  vec_alloc (nm->pending_interrupt_node_runtime_indices, 32);
+
   while (1)
     {
       vlib_worker_thread_barrier_check ();
@@ -1339,6 +1402,28 @@ vlib_worker_thread_internal (vlib_main_t * vm)
                                      cpu_time_now);
       }
 
+      /* Next handle interrupts. */
+      {
+       uword l = _vec_len (nm->pending_interrupt_node_runtime_indices);
+       uword i;
+       if (l > 0)
+         {
+           _vec_len (nm->pending_interrupt_node_runtime_indices) = 0;
+           for (i = 0; i < l; i++)
+             {
+               n = vec_elt_at_index (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT],
+                                     nm->
+                                     pending_interrupt_node_runtime_indices
+                                     [i]);
+               cpu_time_now =
+                 dispatch_node (vm, n, VLIB_NODE_TYPE_INPUT,
+                                VLIB_NODE_STATE_INTERRUPT,
+                                /* frame */ 0,
+                                cpu_time_now);
+             }
+         }
+      }
+
       if (_vec_len (nm->pending_frames))
        {
          int i;