On Mon, Sep 15, 2014 at 2:03 PM, Alex Wang <al...@nicira.com> wrote:
> This commit adds support in ovs-numa module for reading a user
> specified cpu mask, which configures the availability of the cores.
>
> The cpu mask has the format of a hex string similar to the EAL '-c
> COREMASK' option input or the 'taskset' mask input.  The lowest order
> bit corresponds to the first CPU core.  Bit value '1' means the
> corresponding core is available.
>
> An upcoming patch will allow user to configure the mask via OVSDB.
>
> Signed-off-by: Alex Wang <al...@nicira.com>
> ---
>  lib/ovs-numa.c |   93 
> +++++++++++++++++++++++++++++++++++++++++++++++---------
>  lib/ovs-numa.h |    7 +++++
>  2 files changed, 86 insertions(+), 14 deletions(-)
>
> diff --git a/lib/ovs-numa.c b/lib/ovs-numa.c
> index 7da1407..c4a9727 100644
> --- a/lib/ovs-numa.c
> +++ b/lib/ovs-numa.c
> @@ -69,6 +69,7 @@ struct cpu_core {
>      struct list list_node;     /* In 'numa_node->cores' list. */
>      struct numa_node *numa;    /* numa node containing the core. */
>      int core_id;               /* Core id. */
> +    bool available;            /* If the core can be pinned. */
>      bool pinned;               /* If a thread has been pinned to the core. */
>  };
>
> @@ -123,6 +124,7 @@ discover_numa_and_core(void)
>                      list_insert(&n->cores, &c->list_node);
>                      c->core_id = core_id;
>                      c->numa = n;
> +                    c->available = true;
>                      n_cpus++;
>                  }
>              }
> @@ -222,8 +224,8 @@ ovs_numa_get_n_cores_on_numa(int numa_id)
>      return OVS_CORE_UNSPEC;
>  }
>
> -/* Returns the number of unpinned cpu cores on numa node.  Returns
> - * OVS_CORE_UNSPEC if 'numa_id' is invalid. */
> +/* Returns the number of cpu cores that are available and unpinned
> + * on numa node.  Returns OVS_CORE_UNSPEC if 'numa_id' is invalid. */
>  int
>  ovs_numa_get_n_unpinned_cores_on_numa(int numa_id)
>  {
> @@ -236,7 +238,7 @@ ovs_numa_get_n_unpinned_cores_on_numa(int numa_id)
>                                                   hash_int(numa_id, 0)),
>                              struct numa_node, hmap_node);
>          LIST_FOR_EACH(core, list_node, &numa->cores) {
> -            if (!core->pinned) {
> +            if (core->available && !core->pinned) {
>                  count++;
>              }
>          }
> @@ -248,7 +250,8 @@ ovs_numa_get_n_unpinned_cores_on_numa(int numa_id)
>  }
>
>  /* Given 'core_id', tries to pin that core.  Returns true, if succeeds.
> - * False, if the core has already been pinned or if 'core_id' is invalid. */
> + * False, if the core has already been pinned, or if it is invalid or
> + * not available. */
>  bool
>  ovs_numa_try_pin_core_specific(int core_id)
>  {
> @@ -258,7 +261,7 @@ ovs_numa_try_pin_core_specific(int core_id)
>          core = CONTAINER_OF(hmap_first_with_hash(&all_cpu_cores,
>                                                   hash_int(core_id, 0)),
>                              struct cpu_core, hmap_node);
> -        if (!core->pinned) {
> +        if (core->available && !core->pinned) {
>              core->pinned = true;
>              return true;
>          }
> @@ -267,16 +270,16 @@ ovs_numa_try_pin_core_specific(int core_id)
>      return false;
>  }
>
> -/* Searches through all cores for an unpinned core.  Returns the core_id
> - * if found and set the 'core->pinned' to true.  Otherwise, returns
> - * OVS_CORE_UNSPEC. */
> +/* Searches through all cores for an unpinned and available core.  Returns
> + * the 'core_id' if found and sets the 'core->pinned' to true.  Otherwise,
> + * returns OVS_CORE_UNSPEC. */
>  int
>  ovs_numa_get_unpinned_core_any(void)
>  {
>      struct cpu_core *core;
>
>      HMAP_FOR_EACH(core, hmap_node, &all_cpu_cores) {
> -        if (!core->pinned) {
> +        if (core->available && !core->pinned) {
>              core->pinned = true;
>              return core->core_id;
>          }
> @@ -285,9 +288,9 @@ ovs_numa_get_unpinned_core_any(void)
>      return OVS_CORE_UNSPEC;
>  }
>
> -/* Searches through all cores on numa node with 'numa_id' for an unpinned
> - * core.  Returns the core_id if found and sets the 'core->pinned' to true.
> - * Otherwise, returns OVS_CORE_UNSPEC. */
> +/* Searches through all cores on numa node with 'numa_id' for an
> + * unpinned and available core.  Returns the core_id if found and
> + * sets the 'core->pinned' to true.  Otherwise, returns OVS_CORE_UNSPEC. */
>  int
>  ovs_numa_get_unpinned_core_on_numa(int numa_id)
>  {
> @@ -299,7 +302,7 @@ ovs_numa_get_unpinned_core_on_numa(int numa_id)
>                                                   hash_int(numa_id, 0)),
>                              struct numa_node, hmap_node);
>          LIST_FOR_EACH(core, list_node, &numa->cores) {
> -            if (!core->pinned) {
> +            if (core->available && !core->pinned) {
>                  core->pinned = true;
>                  return core->core_id;
>              }
> @@ -309,7 +312,7 @@ ovs_numa_get_unpinned_core_on_numa(int numa_id)
>      return OVS_CORE_UNSPEC;
>  }
>
> -/* Resets the 'core->pinned' for the core with 'core_id'. */
> +/* Unpins the core with 'core_id'. */
>  void
>  ovs_numa_unpin_core(int core_id)
>  {
> @@ -323,4 +326,66 @@ ovs_numa_unpin_core(int core_id)
>      }
>  }
>
> +/* Reads the cpu mask configuration from 'cmask' and sets the
> + * 'available' of corresponding cores.  For unspecified cores,
> + * sets 'available' to true. */
> +void
> +ovs_numa_set_cpu_mask(const char *cmask)
> +{
> +    int core_id = 0;
> +    int i;
> +
> +    if (!found_numa_and_core) {
> +        return;
> +    }
> +
> +    /* If no mask specified, resets the 'available' to true for all cores. */
> +    if (!cmask) {
> +        struct cpu_core *core;
> +
> +        HMAP_FOR_EACH(core, hmap_node, &all_cpu_cores) {
> +            core->available = true;
> +        }
> +
> +        return;
> +    }
> +
> +    for (i = strlen(cmask) - 1; i >= 0; i--) {
> +        char hex = toupper(cmask[i]);
> +        int bin, j;
> +
> +        if (hex >= '0' && hex <= '9') {
> +            bin = hex - '0';
> +        } else if (hex >= 'A' && hex <= 'F') {
> +            bin = hex - 'A' + 10;
> +        } else {
> +            bin = 0;
> +            VLOG_WARN("Invalid cpu mask: %c", cmask[i]);
> +        }
> +
> +        for (j = 0; j < 4; j++) {
> +            struct cpu_core *core;
> +
> +            core = CONTAINER_OF(hmap_first_with_hash(&all_cpu_cores,
> +                                                     hash_int(core_id++, 0)),
> +                                struct cpu_core, hmap_node);
> +            core->available = (bin >> j) & 0x1;
This can result in NULL pointer deref if cores are not multiple of 4.
I am not sure how "(bin >> j) & 0x1" works, easier way would be to
test for bits set in bin and then lookup the core.

> +       }
> +
> +        if (core_id >= hmap_count(&all_cpu_cores)) {
> +            return;
> +        }
> +    }
> +
> +    /* For unspecified cores, sets 'available' to false.  */
> +    while (core_id < hmap_count(&all_cpu_cores)) {
> +        struct cpu_core *core;
> +
> +        core = CONTAINER_OF(hmap_first_with_hash(&all_cpu_cores,
> +                                                 hash_int(core_id++, 0)),
> +                            struct cpu_core, hmap_node);
> +        core->available = false;
> +    }
> +}
> +
>  #endif /* __linux__ */
> diff --git a/lib/ovs-numa.h b/lib/ovs-numa.h
> index 83732fc..fab2546 100644
> --- a/lib/ovs-numa.h
> +++ b/lib/ovs-numa.h
> @@ -31,6 +31,7 @@ void ovs_numa_init(void);
>  bool ovs_numa_numa_id_is_valid(int numa_id);
>  bool ovs_numa_core_id_is_valid(int core_id);
>  int ovs_numa_get_n_numas(void);
> +void ovs_numa_set_cpu_mask(const char *cmask);
>  int ovs_numa_get_n_cores(void);
>  int ovs_numa_get_numa_id(int core_id);
>  int ovs_numa_get_n_cores_on_numa(int numa_id);
> @@ -60,6 +61,12 @@ ovs_numa_core_id_is_valid(int core_id OVS_UNUSED)
>      return false;
>  }
>
> +static inline void
> +ovs_numa_set_cpu_mask(const char *cmask OVS_UNUSED)
> +{
> +    /* Nothing */
> +}
> +
>  static inline int
>  ovs_numa_get_n_numas(void)
>  {
> --
> 1.7.9.5
>
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to