|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 06/10] xen: credit2: group the runq manipulating functions.
On Thu, Feb 9, 2017 at 1:59 PM, Dario Faggioli
<dario.faggioli@xxxxxxxxxx> wrote:
> So that they're all close among each other, and
> also near to the comment describind the runqueue
> organization (which is also moved).
>
> No functional change intended.
>
> Signed-off-by: Dario Faggioli <dario.faggioli@xxxxxxxxxx>
> ---
> Cc: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
> Cc: Anshul Makkar <anshul.makkar@xxxxxxxxxx>
> ---
> xen/common/sched_credit2.c | 572
> ++++++++++++++++++++++----------------------
> 1 file changed, 286 insertions(+), 286 deletions(-)
>
> diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c
> index 4b4f4f8..addee7b 100644
> --- a/xen/common/sched_credit2.c
> +++ b/xen/common/sched_credit2.c
> @@ -295,63 +295,6 @@ static int __read_mostly opt_overload_balance_tolerance
> = -3;
> integer_param("credit2_balance_over", opt_overload_balance_tolerance);
>
> /*
> - * Runqueue organization.
> - *
> - * The various cpus are to be assigned each one to a runqueue, and we
> - * want that to happen basing on topology. At the moment, it is possible
> - * to choose to arrange runqueues to be:
> - *
> - * - per-core: meaning that there will be one runqueue per each physical
> - * core of the host. This will happen if the opt_runqueue
> - * parameter is set to 'core';
> - *
> - * - per-socket: meaning that there will be one runqueue per each physical
> - * socket (AKA package, which often, but not always, also
> - * matches a NUMA node) of the host; This will happen if
> - * the opt_runqueue parameter is set to 'socket';
> - *
> - * - per-node: meaning that there will be one runqueue per each physical
> - * NUMA node of the host. This will happen if the opt_runqueue
> - * parameter is set to 'node';
> - *
> - * - global: meaning that there will be only one runqueue to which all the
> - * (logical) processors of the host belong. This will happen if
> - * the opt_runqueue parameter is set to 'all'.
> - *
> - * 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.
> - */
> -#define OPT_RUNQUEUE_CORE 0
> -#define OPT_RUNQUEUE_SOCKET 1
> -#define OPT_RUNQUEUE_NODE 2
> -#define OPT_RUNQUEUE_ALL 3
> -static const char *const opt_runqueue_str[] = {
> - [OPT_RUNQUEUE_CORE] = "core",
> - [OPT_RUNQUEUE_SOCKET] = "socket",
> - [OPT_RUNQUEUE_NODE] = "node",
> - [OPT_RUNQUEUE_ALL] = "all"
> -};
> -static int __read_mostly opt_runqueue = OPT_RUNQUEUE_SOCKET;
> -
> -static void parse_credit2_runqueue(const char *s)
> -{
> - unsigned int i;
> -
> - for ( i = 0; i < ARRAY_SIZE(opt_runqueue_str); i++ )
> - {
> - if ( !strcmp(s, opt_runqueue_str[i]) )
> - {
> - opt_runqueue = i;
> - return;
> - }
> - }
> -
> - printk("WARNING, unrecognized value of credit2_runqueue option!\n");
> -}
> -custom_param("credit2_runqueue", parse_credit2_runqueue);
Most of the motion makes sense, but moving the option parser along too
seems a bit strange. Wouldn't it make more sense to leave it with the
other option parsers? (Perhaps with a "pointer" comment if you want
to move the main bulk of the comment?)
Everything else looks good.
-George
> -
> -/*
> * Per-runqueue data
> */
> struct csched2_runqueue_data {
> @@ -563,45 +506,304 @@ static int get_fallback_cpu(struct csched2_vcpu *svc)
> return cpumask_first(cpumask_scratch_cpu(cpu));
> }
>
> - ASSERT(!cpumask_empty(cpumask_scratch_cpu(cpu)));
> -
> - return cpumask_first(cpumask_scratch_cpu(cpu));
> + ASSERT(!cpumask_empty(cpumask_scratch_cpu(cpu)));
> +
> + return cpumask_first(cpumask_scratch_cpu(cpu));
> +}
> +
> +/*
> + * Time-to-credit, credit-to-time.
> + *
> + * We keep track of the "residual" time to make sure that frequent short
> + * schedules still get accounted for in the end.
> + *
> + * FIXME: Do pre-calculated division?
> + */
> +static void t2c_update(struct csched2_runqueue_data *rqd, s_time_t time,
> + struct csched2_vcpu *svc)
> +{
> + uint64_t val = time * rqd->max_weight + svc->residual;
> +
> + svc->residual = do_div(val, svc->weight);
> + svc->credit -= val;
> +}
> +
> +static s_time_t c2t(struct csched2_runqueue_data *rqd, s_time_t credit,
> struct csched2_vcpu *svc)
> +{
> + return credit * svc->weight / rqd->max_weight;
> +}
> +
> +/*
> + * Runqueue related code.
> + */
> +
> +/*
> + * Runqueue organization.
> + *
> + * The various cpus are to be assigned each one to a runqueue, and we
> + * want that to happen basing on topology. At the moment, it is possible
> + * to choose to arrange runqueues to be:
> + *
> + * - per-core: meaning that there will be one runqueue per each physical
> + * core of the host. This will happen if the opt_runqueue
> + * parameter is set to 'core';
> + *
> + * - per-socket: meaning that there will be one runqueue per each physical
> + * socket (AKA package, which often, but not always, also
> + * matches a NUMA node) of the host; This will happen if
> + * the opt_runqueue parameter is set to 'socket';
> + *
> + * - per-node: meaning that there will be one runqueue per each physical
> + * NUMA node of the host. This will happen if the opt_runqueue
> + * parameter is set to 'node';
> + *
> + * - global: meaning that there will be only one runqueue to which all the
> + * (logical) processors of the host belong. This will happen if
> + * the opt_runqueue parameter is set to 'all'.
> + *
> + * 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.
> + */
> +#define OPT_RUNQUEUE_CORE 0
> +#define OPT_RUNQUEUE_SOCKET 1
> +#define OPT_RUNQUEUE_NODE 2
> +#define OPT_RUNQUEUE_ALL 3
> +static const char *const opt_runqueue_str[] = {
> + [OPT_RUNQUEUE_CORE] = "core",
> + [OPT_RUNQUEUE_SOCKET] = "socket",
> + [OPT_RUNQUEUE_NODE] = "node",
> + [OPT_RUNQUEUE_ALL] = "all"
> +};
> +static int __read_mostly opt_runqueue = OPT_RUNQUEUE_SOCKET;
> +
> +static void parse_credit2_runqueue(const char *s)
> +{
> + unsigned int i;
> +
> + for ( i = 0; i < ARRAY_SIZE(opt_runqueue_str); i++ )
> + {
> + if ( !strcmp(s, opt_runqueue_str[i]) )
> + {
> + opt_runqueue = i;
> + return;
> + }
> + }
> +
> + printk("WARNING, unrecognized value of credit2_runqueue option!\n");
> +}
> +custom_param("credit2_runqueue", parse_credit2_runqueue);
> +
> +static inline int vcpu_on_runq(struct csched2_vcpu *svc)
> +{
> + return !list_empty(&svc->runq_elem);
> +}
> +
> +static struct csched2_vcpu * runq_elem(struct list_head *elem)
> +{
> + return list_entry(elem, struct csched2_vcpu, runq_elem);
> +}
> +
> +static void activate_runqueue(struct csched2_private *prv, int rqi)
> +{
> + struct csched2_runqueue_data *rqd;
> +
> + rqd = prv->rqd + rqi;
> +
> + BUG_ON(!cpumask_empty(&rqd->active));
> +
> + rqd->max_weight = 1;
> + rqd->id = rqi;
> + INIT_LIST_HEAD(&rqd->svc);
> + INIT_LIST_HEAD(&rqd->runq);
> + spin_lock_init(&rqd->lock);
> +
> + __cpumask_set_cpu(rqi, &prv->active_queues);
> +}
> +
> +static void deactivate_runqueue(struct csched2_private *prv, int rqi)
> +{
> + struct csched2_runqueue_data *rqd;
> +
> + rqd = prv->rqd + rqi;
> +
> + BUG_ON(!cpumask_empty(&rqd->active));
> +
> + rqd->id = -1;
> +
> + __cpumask_clear_cpu(rqi, &prv->active_queues);
> +}
> +
> +static inline bool_t same_node(unsigned int cpua, unsigned int cpub)
> +{
> + return cpu_to_node(cpua) == cpu_to_node(cpub);
> +}
> +
> +static inline bool_t same_socket(unsigned int cpua, unsigned int cpub)
> +{
> + return cpu_to_socket(cpua) == cpu_to_socket(cpub);
> +}
> +
> +static inline bool_t same_core(unsigned int cpua, unsigned int cpub)
> +{
> + return same_socket(cpua, cpub) &&
> + cpu_to_core(cpua) == cpu_to_core(cpub);
> +}
> +
> +static unsigned int
> +cpu_to_runqueue(struct csched2_private *prv, unsigned int cpu)
> +{
> + struct csched2_runqueue_data *rqd;
> + unsigned int rqi;
> +
> + for ( rqi = 0; rqi < nr_cpu_ids; rqi++ )
> + {
> + unsigned int peer_cpu;
> +
> + /*
> + * As soon as we come across an uninitialized runqueue, use it.
> + * In fact, either:
> + * - we are initializing the first cpu, and we assign it to
> + * runqueue 0. This is handy, especially if we are dealing
> + * with the boot cpu (if credit2 is the default scheduler),
> + * as we would not be able to use cpu_to_socket() and similar
> + * helpers anyway (they're result of which is not reliable yet);
> + * - we have gone through all the active runqueues, and have not
> + * found anyone whose cpus' topology matches the one we are
> + * dealing with, so activating a new runqueue is what we want.
> + */
> + if ( prv->rqd[rqi].id == -1 )
> + break;
> +
> + rqd = prv->rqd + rqi;
> + BUG_ON(cpumask_empty(&rqd->active));
> +
> + peer_cpu = cpumask_first(&rqd->active);
> + BUG_ON(cpu_to_socket(cpu) == XEN_INVALID_SOCKET_ID ||
> + cpu_to_socket(peer_cpu) == XEN_INVALID_SOCKET_ID);
> +
> + if ( opt_runqueue == OPT_RUNQUEUE_ALL ||
> + (opt_runqueue == OPT_RUNQUEUE_CORE && same_core(peer_cpu, cpu))
> ||
> + (opt_runqueue == OPT_RUNQUEUE_SOCKET && same_socket(peer_cpu,
> cpu)) ||
> + (opt_runqueue == OPT_RUNQUEUE_NODE && same_node(peer_cpu, cpu))
> )
> + break;
> + }
> +
> + /* We really expect to be able to assign each cpu to a runqueue. */
> + BUG_ON(rqi >= nr_cpu_ids);
> +
> + return rqi;
> +}
> +
> +/* Find the domain with the highest weight. */
> +static void update_max_weight(struct csched2_runqueue_data *rqd, int
> new_weight,
> + int old_weight)
> +{
> + /* Try to avoid brute-force search:
> + * - If new_weight is larger, max_weigth <- new_weight
> + * - If old_weight != max_weight, someone else is still max_weight
> + * (No action required)
> + * - If old_weight == max_weight, brute-force search for max weight
> + */
> + if ( new_weight > rqd->max_weight )
> + {
> + rqd->max_weight = new_weight;
> + SCHED_STAT_CRANK(upd_max_weight_quick);
> + }
> + else if ( old_weight == rqd->max_weight )
> + {
> + struct list_head *iter;
> + int max_weight = 1;
> +
> + list_for_each( iter, &rqd->svc )
> + {
> + struct csched2_vcpu * svc = list_entry(iter, struct
> csched2_vcpu, rqd_elem);
> +
> + if ( svc->weight > max_weight )
> + max_weight = svc->weight;
> + }
> +
> + rqd->max_weight = max_weight;
> + SCHED_STAT_CRANK(upd_max_weight_full);
> + }
> +
> + if ( unlikely(tb_init_done) )
> + {
> + struct {
> + unsigned rqi:16, max_weight:16;
> + } d;
> + d.rqi = rqd->id;
> + d.max_weight = rqd->max_weight;
> + __trace_var(TRC_CSCHED2_RUNQ_MAX_WEIGHT, 1,
> + sizeof(d),
> + (unsigned char *)&d);
> + }
> +}
> +
> +/* Add and remove from runqueue assignment (not active run queue) */
> +static void
> +_runq_assign(struct csched2_vcpu *svc, struct csched2_runqueue_data *rqd)
> +{
> +
> + svc->rqd = rqd;
> + list_add_tail(&svc->rqd_elem, &svc->rqd->svc);
> +
> + update_max_weight(svc->rqd, svc->weight, 0);
> +
> + /* Expected new load based on adding this vcpu */
> + rqd->b_avgload += svc->avgload;
> +
> + if ( unlikely(tb_init_done) )
> + {
> + struct {
> + unsigned vcpu:16, dom:16;
> + unsigned rqi:16;
> + } d;
> + d.dom = svc->vcpu->domain->domain_id;
> + d.vcpu = svc->vcpu->vcpu_id;
> + d.rqi=rqd->id;
> + __trace_var(TRC_CSCHED2_RUNQ_ASSIGN, 1,
> + sizeof(d),
> + (unsigned char *)&d);
> + }
> +
> }
>
> -/*
> - * Time-to-credit, credit-to-time.
> - *
> - * We keep track of the "residual" time to make sure that frequent short
> - * schedules still get accounted for in the end.
> - *
> - * FIXME: Do pre-calculated division?
> - */
> -static void t2c_update(struct csched2_runqueue_data *rqd, s_time_t time,
> - struct csched2_vcpu *svc)
> +static void
> +runq_assign(const struct scheduler *ops, struct vcpu *vc)
> {
> - uint64_t val = time * rqd->max_weight + svc->residual;
> + struct csched2_vcpu *svc = vc->sched_priv;
>
> - svc->residual = do_div(val, svc->weight);
> - svc->credit -= val;
> + ASSERT(svc->rqd == NULL);
> +
> + _runq_assign(svc, c2rqd(ops, vc->processor));
> }
>
> -static s_time_t c2t(struct csched2_runqueue_data *rqd, s_time_t credit,
> struct csched2_vcpu *svc)
> +static void
> +_runq_deassign(struct csched2_vcpu *svc)
> {
> - return credit * svc->weight / rqd->max_weight;
> -}
> + struct csched2_runqueue_data *rqd = svc->rqd;
>
> -/*
> - * Runqueue related code
> - */
> + ASSERT(!vcpu_on_runq(svc));
> + ASSERT(!(svc->flags & CSFLAG_scheduled));
>
> -static inline int vcpu_on_runq(struct csched2_vcpu *svc)
> -{
> - return !list_empty(&svc->runq_elem);
> + list_del_init(&svc->rqd_elem);
> + update_max_weight(rqd, 0, svc->weight);
> +
> + /* Expected new load based on removing this vcpu */
> + rqd->b_avgload = max_t(s_time_t, rqd->b_avgload - svc->avgload, 0);
> +
> + svc->rqd = NULL;
> }
>
> -static struct csched2_vcpu * runq_elem(struct list_head *elem)
> +static void
> +runq_deassign(const struct scheduler *ops, struct vcpu *vc)
> {
> - return list_entry(elem, struct csched2_vcpu, runq_elem);
> + struct csched2_vcpu *svc = vc->sched_priv;
> +
> + ASSERT(svc->rqd == c2rqd(ops, vc->processor));
> +
> + _runq_deassign(svc);
> }
>
> /*
> @@ -1218,51 +1420,6 @@ void burn_credits(struct csched2_runqueue_data *rqd,
> }
> }
>
> -/* Find the domain with the highest weight. */
> -static void update_max_weight(struct csched2_runqueue_data *rqd, int
> new_weight,
> - int old_weight)
> -{
> - /* Try to avoid brute-force search:
> - * - If new_weight is larger, max_weigth <- new_weight
> - * - If old_weight != max_weight, someone else is still max_weight
> - * (No action required)
> - * - If old_weight == max_weight, brute-force search for max weight
> - */
> - if ( new_weight > rqd->max_weight )
> - {
> - rqd->max_weight = new_weight;
> - SCHED_STAT_CRANK(upd_max_weight_quick);
> - }
> - else if ( old_weight == rqd->max_weight )
> - {
> - struct list_head *iter;
> - int max_weight = 1;
> -
> - list_for_each( iter, &rqd->svc )
> - {
> - struct csched2_vcpu * svc = list_entry(iter, struct
> csched2_vcpu, rqd_elem);
> -
> - if ( svc->weight > max_weight )
> - max_weight = svc->weight;
> - }
> -
> - rqd->max_weight = max_weight;
> - SCHED_STAT_CRANK(upd_max_weight_full);
> - }
> -
> - if ( unlikely(tb_init_done) )
> - {
> - struct {
> - unsigned rqi:16, max_weight:16;
> - } d;
> - d.rqi = rqd->id;
> - d.max_weight = rqd->max_weight;
> - __trace_var(TRC_CSCHED2_RUNQ_MAX_WEIGHT, 1,
> - sizeof(d),
> - (unsigned char *)&d);
> - }
> -}
> -
> #ifndef NDEBUG
> static inline void
> csched2_vcpu_check(struct vcpu *vc)
> @@ -1327,72 +1484,6 @@ csched2_alloc_vdata(const struct scheduler *ops,
> struct vcpu *vc, void *dd)
> return svc;
> }
>
> -/* Add and remove from runqueue assignment (not active run queue) */
> -static void
> -_runq_assign(struct csched2_vcpu *svc, struct csched2_runqueue_data *rqd)
> -{
> -
> - svc->rqd = rqd;
> - list_add_tail(&svc->rqd_elem, &svc->rqd->svc);
> -
> - update_max_weight(svc->rqd, svc->weight, 0);
> -
> - /* Expected new load based on adding this vcpu */
> - rqd->b_avgload += svc->avgload;
> -
> - if ( unlikely(tb_init_done) )
> - {
> - struct {
> - unsigned vcpu:16, dom:16;
> - unsigned rqi:16;
> - } d;
> - d.dom = svc->vcpu->domain->domain_id;
> - d.vcpu = svc->vcpu->vcpu_id;
> - d.rqi=rqd->id;
> - __trace_var(TRC_CSCHED2_RUNQ_ASSIGN, 1,
> - sizeof(d),
> - (unsigned char *)&d);
> - }
> -
> -}
> -
> -static void
> -runq_assign(const struct scheduler *ops, struct vcpu *vc)
> -{
> - struct csched2_vcpu *svc = vc->sched_priv;
> -
> - ASSERT(svc->rqd == NULL);
> -
> - _runq_assign(svc, c2rqd(ops, vc->processor));
> -}
> -
> -static void
> -_runq_deassign(struct csched2_vcpu *svc)
> -{
> - struct csched2_runqueue_data *rqd = svc->rqd;
> -
> - ASSERT(!vcpu_on_runq(svc));
> - ASSERT(!(svc->flags & CSFLAG_scheduled));
> -
> - list_del_init(&svc->rqd_elem);
> - update_max_weight(rqd, 0, svc->weight);
> -
> - /* Expected new load based on removing this vcpu */
> - rqd->b_avgload = max_t(s_time_t, rqd->b_avgload - svc->avgload, 0);
> -
> - svc->rqd = NULL;
> -}
> -
> -static void
> -runq_deassign(const struct scheduler *ops, struct vcpu *vc)
> -{
> - struct csched2_vcpu *svc = vc->sched_priv;
> -
> - ASSERT(svc->rqd == c2rqd(ops, vc->processor));
> -
> - _runq_deassign(svc);
> -}
> -
> static void
> csched2_vcpu_sleep(const struct scheduler *ops, struct vcpu *vc)
> {
> @@ -2776,97 +2867,6 @@ csched2_dump(const struct scheduler *ops)
> #undef cpustr
> }
>
> -static void activate_runqueue(struct csched2_private *prv, int rqi)
> -{
> - struct csched2_runqueue_data *rqd;
> -
> - rqd = prv->rqd + rqi;
> -
> - BUG_ON(!cpumask_empty(&rqd->active));
> -
> - rqd->max_weight = 1;
> - rqd->id = rqi;
> - INIT_LIST_HEAD(&rqd->svc);
> - INIT_LIST_HEAD(&rqd->runq);
> - spin_lock_init(&rqd->lock);
> -
> - __cpumask_set_cpu(rqi, &prv->active_queues);
> -}
> -
> -static void deactivate_runqueue(struct csched2_private *prv, int rqi)
> -{
> - struct csched2_runqueue_data *rqd;
> -
> - rqd = prv->rqd + rqi;
> -
> - BUG_ON(!cpumask_empty(&rqd->active));
> -
> - rqd->id = -1;
> -
> - __cpumask_clear_cpu(rqi, &prv->active_queues);
> -}
> -
> -static inline bool_t same_node(unsigned int cpua, unsigned int cpub)
> -{
> - return cpu_to_node(cpua) == cpu_to_node(cpub);
> -}
> -
> -static inline bool_t same_socket(unsigned int cpua, unsigned int cpub)
> -{
> - return cpu_to_socket(cpua) == cpu_to_socket(cpub);
> -}
> -
> -static inline bool_t same_core(unsigned int cpua, unsigned int cpub)
> -{
> - return same_socket(cpua, cpub) &&
> - cpu_to_core(cpua) == cpu_to_core(cpub);
> -}
> -
> -static unsigned int
> -cpu_to_runqueue(struct csched2_private *prv, unsigned int cpu)
> -{
> - struct csched2_runqueue_data *rqd;
> - unsigned int rqi;
> -
> - for ( rqi = 0; rqi < nr_cpu_ids; rqi++ )
> - {
> - unsigned int peer_cpu;
> -
> - /*
> - * As soon as we come across an uninitialized runqueue, use it.
> - * In fact, either:
> - * - we are initializing the first cpu, and we assign it to
> - * runqueue 0. This is handy, especially if we are dealing
> - * with the boot cpu (if credit2 is the default scheduler),
> - * as we would not be able to use cpu_to_socket() and similar
> - * helpers anyway (they're result of which is not reliable yet);
> - * - we have gone through all the active runqueues, and have not
> - * found anyone whose cpus' topology matches the one we are
> - * dealing with, so activating a new runqueue is what we want.
> - */
> - if ( prv->rqd[rqi].id == -1 )
> - break;
> -
> - rqd = prv->rqd + rqi;
> - BUG_ON(cpumask_empty(&rqd->active));
> -
> - peer_cpu = cpumask_first(&rqd->active);
> - BUG_ON(cpu_to_socket(cpu) == XEN_INVALID_SOCKET_ID ||
> - cpu_to_socket(peer_cpu) == XEN_INVALID_SOCKET_ID);
> -
> - if ( opt_runqueue == OPT_RUNQUEUE_ALL ||
> - (opt_runqueue == OPT_RUNQUEUE_CORE && same_core(peer_cpu, cpu))
> ||
> - (opt_runqueue == OPT_RUNQUEUE_SOCKET && same_socket(peer_cpu,
> cpu)) ||
> - (opt_runqueue == OPT_RUNQUEUE_NODE && same_node(peer_cpu, cpu))
> )
> - break;
> - }
> -
> - /* We really expect to be able to assign each cpu to a runqueue. */
> - BUG_ON(rqi >= nr_cpu_ids);
> -
> - return rqi;
> -}
> -
> /* Returns the ID of the runqueue the cpu is assigned to. */
> static unsigned
> init_pdata(struct csched2_private *prv, unsigned int cpu)
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> https://lists.xen.org/xen-devel
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |