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