|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH v4] xen: credit2: provide custom option to create runqueue
Hi,
Can you please provide comments on the shared patch.
Thanks in advance.
Regards,
~Praveen.
On Wed, 2017-04-19 at 23:15 +0530, Praveen Kumar wrote:
> The patch introduces a new, very flexible way of arranging runqueues
> in Credit2.
> It allows to specify, explicitly and precisely, what pCPUs should
> belong to
> which runqueue.
>
> Signed-off-by: Praveen Kumar <kpraveen.lkml@xxxxxxxxx>
> ---
> docs/misc/xen-command-line.markdown | 10 ++-
> xen/common/sched_credit2.c | 167
> +++++++++++++++++++++++++++++++++++-
> 2 files changed, 174 insertions(+), 3 deletions(-)
>
> diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-
> command-line.markdown
> index 33e54aef63..f2ee4ad972 100644
> --- a/docs/misc/xen-command-line.markdown
> +++ b/docs/misc/xen-command-line.markdown
> @@ -525,7 +525,7 @@ also slow in responding to load changes.
> The default value of `1 sec` is rather long.
>
> ### credit2\_runqueue
> -> `= cpu | core | socket | node | all`
> +> `= cpu | core | socket | node | all | <custom>`
>
> > Default: `socket`
>
> @@ -543,6 +543,14 @@ Available alternatives, with their meaning, are:
> * `node`: one runqueue per each NUMA node of the host;
> * `all`: just one runqueue shared by all the logical pCPUs of
> the host
> +* `<custom>`: one runqueue per mentioned subset. The subset can be
> defined as
> + as shown in below example:
> + credit2_runqueue=[[0,1,][2,6][3,5][4,7]] , or
> 0,1\;2,6\;3,5\;4,7
> + which means :
> + - pCPUs 0 and 1 belong to runqueue 0
> + - pCPUs 2 and 6 belong to runqueue 1
> + - pCPUs 3 and 5 belong to runqueue 2
> + - pCPUs 4 and 7 belong to runqueue 3
>
> ### dbgp
> > `= ehci[ <integer> | @pci<bus>:<slot>.<func> ]`
> diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c
> index b9b928347f..ebec33f450 100644
> --- a/xen/common/sched_credit2.c
> +++ b/xen/common/sched_credit2.c
> @@ -321,6 +321,16 @@ integer_param("credit2_balance_over",
> opt_overload_balance_tolerance);
> * (logical) processors of the host belong. This will
> happen if
> * the opt_runqueue parameter is set to 'all'.
> *
> + * - custom: meaning that there will be one runqueue per subset
> being passed as
> + * parameter to credit2_runqueue as shown in below
> example.
> + * Example:
> + * credit2_runqueue=[[cpu0,cpu1][cpu3][cpu4,cpu5]] or
> + * credit2_runqueue=0,1\;3\;4,5
> + * The example mentioned states :
> + * cpu0 and cpu1 belongs to runqueue 0
> + * cpu3 belongs to runqueue 1
> + * cpu4 and cpu5 belongs to runqueue 2
> + *
> * Depending on the value of opt_runqueue, therefore, cpus that are
> part of
> * either the same physical core, the same physical socket, the same
> NUMA
> * node, or just all of them, will be put together to form
> runqueues.
> @@ -330,15 +340,138 @@ integer_param("credit2_balance_over",
> opt_overload_balance_tolerance);
> #define OPT_RUNQUEUE_SOCKET 2
> #define OPT_RUNQUEUE_NODE 3
> #define OPT_RUNQUEUE_ALL 4
> +#define OPT_RUNQUEUE_CUSTOM 5
> static const char *const opt_runqueue_str[] = {
> [OPT_RUNQUEUE_CPU] = "cpu",
> [OPT_RUNQUEUE_CORE] = "core",
> [OPT_RUNQUEUE_SOCKET] = "socket",
> [OPT_RUNQUEUE_NODE] = "node",
> - [OPT_RUNQUEUE_ALL] = "all"
> + [OPT_RUNQUEUE_ALL] = "all",
> + [OPT_RUNQUEUE_CUSTOM] = "custom"
> };
> static int __read_mostly opt_runqueue = OPT_RUNQUEUE_SOCKET;
>
> +static unsigned long __read_mostly custom_cpu_runqueue[NR_CPUS];
> +
> +static inline int getlen(const char *start, const char *end)
> +{
> + if ( ( start ) && ( end ) && ( end > start ) )
> + return end-start;
> + else
> + return -1;
> +}
> +
> +static int parse_custom_runqueue_option(const char *s)
> +{
> + const char *parse = NULL, *s_end = NULL;
> + const char *start = NULL, *end = NULL;
> + char delimiter[2] = {0};
> + int cpu_added_to_runqueue = 0;
> + int runqueue = 0;
> +
> + /* Format supported :
> + * [[0,1,4,5][2,3,6,7][8,9,12,13][10,11,14,15]]
> + * or
> + * 0,1,4,5\;2,3,6,7\;8,9,12,13\;10,11,14,15
> + */
> + parse = s;
> + s_end = s + strlen(s);
> + /* The start and should always be in format of '[..]' */
> + if ( ( '[' == *parse ) && ( ']' == *(s_end-1)) )
> + {
> + delimiter[0] = '[';
> + delimiter[1] = '\0';
> + parse++;
> + }
> + else
> + {
> + delimiter[0] = ';';
> + delimiter[1] = '\0';
> + }
> +
> + while ( ( parse != NULL ) && ( parse < s_end ) )
> + {
> + const char *token_sub_str = NULL;
> +
> + while ( *parse == '[' )
> + parse++;
> +
> + start = parse;
> + end = strstr(parse, delimiter);
> +
> + /* Check if we don't have the delimiter */
> + if ( !end )
> + {
> + /* If we don't have delimiter, then break, if start is
> greater than
> + * or equal to s_end, as we have reached the end.
> + */
> + if ( start >= s_end )
> + break;
> +
> + /* We need to parse till s_end, as we have the last set
> */
> + end = s_end;
> + }
> +
> + /* Just move to next, as we have empty set like [] or ;; */
> + if ( getlen ( start, end ) < 1 )
> + goto next;
> +
> + /*
> + * find token within the subset
> + */
> + do
> + {
> + unsigned long token = 0;
> +
> + /* Get cpu ids separated by ',' within each set */
> + token_sub_str = strpbrk(start, ",");
> +
> + /* Basic checks to validate the last entry in subset */
> + if ( ( !token_sub_str && start < end ) ||
> + ( token_sub_str > end && token_sub_str > start ) )
> + {
> + if ( ( delimiter[0] == '[' ) && ( start == s_end - 1
> ) )
> + goto next;
> +
> + token_sub_str = end;
> + }
> +
> + /* Just move to next, as we have empty set like [] or ;;
> */
> + if ( getlen(start, token_sub_str) < 1 )
> + goto next;
> +
> + token = simple_strtoul(start ,&token_sub_str, 0);
> +
> + if ( token >= nr_cpu_ids)
> + return -1;
> +
> + /* If not set already */
> + if ( custom_cpu_runqueue[token] == -1 )
> + {
> + custom_cpu_runqueue[token] = runqueue;
> + cpu_added_to_runqueue = 1;
> + }
> + else
> + return -1;
> +
> + if ( !token_sub_str || token_sub_str > end )
> + goto next;
> +
> + start = ++token_sub_str;
> + } while ( start < end );
> +next:
> + if ( cpu_added_to_runqueue )
> + {
> + runqueue++;
> + cpu_added_to_runqueue = 0;
> + }
> +
> + parse = ++end;
> + }
> + opt_runqueue = OPT_RUNQUEUE_CUSTOM;
> + return 0;
> +}
> +
> static void parse_credit2_runqueue(const char *s)
> {
> unsigned int i;
> @@ -351,8 +484,29 @@ static void parse_credit2_runqueue(const char
> *s)
> return;
> }
> }
> + /*
> + * At this stage we are either unknown value of credit2_runqueue
> or we can
> + * consider it to be custom cpu. Lets try parsing the same.
> + * Resetting the custom_cpu_runqueue for future use. Only the
> non-negative
> + * entries will be valid. The index 'i' in custom_cpu_runqueue
> will store
> + * the specific runqueue it belongs to.
> + * Example:
> + * If custom_cpu_runqueue[3] == 2
> + * Then, it means that cpu 3 belong to runqueue 2.
> + * If custom_cpu_runqueue[4] == -1
> + * Then, it means that cpu 4 doesn't belong to any runqueue.
> + */
> + for ( i = 0; i < nr_cpu_ids; i++ )
> + custom_cpu_runqueue[i] = -1;
>
> - printk("WARNING, unrecognized value of credit2_runqueue
> option!\n");
> + if ( parse_custom_runqueue_option(s) != 0 )
> + {
> + /* Resetting in case of failure, so that we don't mess-up
> during any failure
> + * due to wrong or spurious pattern passed by user.
> + */
> + opt_runqueue = OPT_RUNQUEUE_SOCKET;
> + printk("WARNING, unrecognized value of credit2_runqueue
> option!\n");
> + }
> }
> custom_param("credit2_runqueue", parse_credit2_runqueue);
>
> @@ -662,6 +816,15 @@ cpu_to_runqueue(struct csched2_private *prv,
> unsigned int cpu)
> struct csched2_runqueue_data *rqd;
> unsigned int rqi;
>
> + if ( opt_runqueue == OPT_RUNQUEUE_CUSTOM )
> + {
> + if ( custom_cpu_runqueue[cpu] != -1 )
> + {
> + BUG_ON(custom_cpu_runqueue[cpu] >= nr_cpu_ids);
> + return custom_cpu_runqueue[cpu];
> + }
> + }
> +
> for ( rqi = 0; rqi < nr_cpu_ids; rqi++ )
> {
> unsigned int peer_cpu;
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |