From 1e7658340ac4cba20defba056c2e13ec0e1a0a69 Mon Sep 17 00:00:00 2001 From: Pavel Kotucek Date: Fri, 23 Sep 2016 08:54:14 +0200 Subject: [PATCH] VPP-425: Scheduler policy & priority configuration 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 scheduler-policy [other | batch | idle | fifo | rr ] } Change-Id: Ie20765280e458e1d7deb4a8c66daaa69793f795e Signed-off-by: Pavel Kotucek --- vlib/vlib/threads.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++-- vlib/vlib/threads.h | 22 ++++++++++++++++++++ vlib/vlib/threads_cli.c | 29 +++++++++++++++++++++++++-- 3 files changed, 100 insertions(+), 4 deletions(-) diff --git a/vlib/vlib/threads.c b/vlib/vlib/threads.c index dc9b1bbecd7..67c57a60f41 100644 --- a/vlib/vlib/threads.c +++ b/vlib/vlib/threads.c @@ -13,7 +13,6 @@ * limitations under the License. */ #define _GNU_SOURCE -#include #include #include @@ -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 3 '%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) diff --git a/vlib/vlib/threads.h b/vlib/vlib/threads.h index 4283b70a61d..589d1f3a1ec 100644 --- a/vlib/vlib/threads.h +++ b/vlib/vlib/threads.h @@ -16,6 +16,7 @@ #define included_vlib_threads_h #include +#include 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; diff --git a/vlib/vlib/threads_cli.c b/vlib/vlib/threads_cli.c index 9ab4edcd357..179906ba51b 100644 --- a/vlib/vlib/threads_cli.c +++ b/vlib/vlib/threads_cli.c @@ -17,6 +17,23 @@ #include #include +#include + +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) -- 2.16.6