UseNUMA membind Issue in openJDK

David Holmes david.holmes at oracle.com
Tue May 22 01:45:42 UTC 2018


Hi Swati,

On 22/05/2018 2:44 AM, Swati Sharma wrote:
> +Gustavo
> 
> Hi David,
> 
> Updated previous patch.Some issue was there with issinglenodeound() 
> method on SUSE, so just swapped the condition, checking in same. Please 
> review and let me know your comments.

As I originally said "I can't comment on the actual NUMA details of the 
patch.", so won't be reviewing it. Sorry.

David

> Derek : Thanks for the info :) I dint know that its already reported.
> 
> Here is the updated patch,attached too.
> ======================PATCH==============================
> diff --git a/src/hotspot/os/linux/os_linux.cpp 
> b/src/hotspot/os/linux/os_linux.cpp
> --- a/src/hotspot/os/linux/os_linux.cpp
> +++ b/src/hotspot/os/linux/os_linux.cpp
> @@ -2832,14 +2832,42 @@
>     // Map all node ids in which is possible to allocate memory. Also 
> nodes are
>     // not always consecutively available, i.e. available from 0 to the 
> highest
>     // node number.
> +  // If the nodes have been bound explicitly using numactl membind, then
> +  // allocate memory from those nodes only.
>     for (size_t node = 0; node <= highest_node_number; node++) {
> -    if (Linux::isnode_in_configured_nodes(node)) {
> +    if (Linux::isnode_in_bounded_nodes(node)) {
>         ids[i++] = node;
>       }
>     }
>     return i;
>   }
> +extern "C"  struct bitmask {
> +  unsigned long size; /* number of bits in the map */
> +  unsigned long *maskp;
> +};
> +// Check if single memory node bound.
> +// Returns true if single memory node bound.
> +bool os::Linux::issingle_node_bound() {
> +  struct bitmask* bmp = _numa_get_membind != NULL ? _numa_get_membind() 
> : NULL;
> +  if(!(bmp != NULL && bmp->maskp != NULL)) return false;
> +  int issingle = 0;
> +  // System can have more than 64 nodes so check in all the elements of
> +  // unsigned long array
> +  for (unsigned long i = 0; i < (bmp->size / (8 * sizeof(unsigned 
> long))); i++) {
> +    if (bmp->maskp[i] == 0) {
> +      continue;
> +    } else if ((bmp->maskp[i] & (bmp->maskp[i] - 1)) == 0) {
> +      issingle++;
> +    } else {
> +      return false;
> +    }
> +  }
> +  if (issingle == 1)
> +    return true;
> +  return false;
> +}
> +
>   bool os::get_page_info(char *start, page_info* info) {
>     return false;
>   }
> @@ -2930,6 +2958,10 @@
>                                                  libnuma_dlsym(handle, 
> "numa_bitmask_isbitset")));
>         set_numa_distance(CAST_TO_FN_PTR(numa_distance_func_t,
>                                          libnuma_dlsym(handle, 
> "numa_distance")));
> +      set_numa_set_membind(CAST_TO_FN_PTR(numa_set_membind_func_t,
> +                                          libnuma_dlsym(handle, 
> "numa_set_membind")));
> +      set_numa_get_membind(CAST_TO_FN_PTR(numa_get_membind_func_t,
> +                                          libnuma_v2_dlsym(handle, 
> "numa_get_membind")));
>         if (numa_available() != -1) {
>           set_numa_all_nodes((unsigned long*)libnuma_dlsym(handle, 
> "numa_all_nodes"));
> @@ -3054,6 +3086,8 @@
>   os::Linux::numa_set_bind_policy_func_t os::Linux::_numa_set_bind_policy;
>   os::Linux::numa_bitmask_isbitset_func_t os::Linux::_numa_bitmask_isbitset;
>   os::Linux::numa_distance_func_t os::Linux::_numa_distance;
> +os::Linux::numa_set_membind_func_t os::Linux::_numa_set_membind;
> +os::Linux::numa_get_membind_func_t os::Linux::_numa_get_membind;
>   unsigned long* os::Linux::_numa_all_nodes;
>   struct bitmask* os::Linux::_numa_all_nodes_ptr;
>   struct bitmask* os::Linux::_numa_nodes_ptr;
> @@ -4962,8 +4996,9 @@
>       if (!Linux::libnuma_init()) {
>         UseNUMA = false;
>       } else {
> -      if ((Linux::numa_max_node() < 1)) {
> -        // There's only one node(they start from 0), disable NUMA.
> +      if ((Linux::numa_max_node() < 1) || Linux::issingle_node_bound()) {
> +        // If there's only one node(they start from 0) or if the process
> +        // is bound explicitly to a single node using membind, disable 
> NUMA.
>           UseNUMA = false;
>         }
>       }
> diff --git a/src/hotspot/os/linux/os_linux.hpp 
> b/src/hotspot/os/linux/os_linux.hpp
> --- a/src/hotspot/os/linux/os_linux.hpp
> +++ b/src/hotspot/os/linux/os_linux.hpp
> @@ -228,6 +228,8 @@
>     typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, 
> int node);
>     typedef void (*numa_interleave_memory_func_t)(void *start, size_t 
> size, unsigned long *nodemask);
>     typedef void (*numa_interleave_memory_v2_func_t)(void *start, size_t 
> size, struct bitmask* mask);
> +  typedef void (*numa_set_membind_func_t)(struct bitmask *mask);
> +  typedef struct bitmask* (*numa_get_membind_func_t)(void);
>     typedef void (*numa_set_bind_policy_func_t)(int policy);
>     typedef int (*numa_bitmask_isbitset_func_t)(struct bitmask *bmp, 
> unsigned int n);
> @@ -244,6 +246,8 @@
>     static numa_set_bind_policy_func_t _numa_set_bind_policy;
>     static numa_bitmask_isbitset_func_t _numa_bitmask_isbitset;
>     static numa_distance_func_t _numa_distance;
> +  static numa_set_membind_func_t _numa_set_membind;
> +  static numa_get_membind_func_t _numa_get_membind;
>     static unsigned long* _numa_all_nodes;
>     static struct bitmask* _numa_all_nodes_ptr;
>     static struct bitmask* _numa_nodes_ptr;
> @@ -259,6 +263,8 @@
>     static void set_numa_set_bind_policy(numa_set_bind_policy_func_t 
> func) { _numa_set_bind_policy = func; }
>     static void set_numa_bitmask_isbitset(numa_bitmask_isbitset_func_t 
> func) { _numa_bitmask_isbitset = func; }
>     static void set_numa_distance(numa_distance_func_t func) { 
> _numa_distance = func; }
> +  static void set_numa_set_membind(numa_set_membind_func_t func) { 
> _numa_set_membind = func; }
> +  static void set_numa_get_membind(numa_get_membind_func_t func) { 
> _numa_get_membind = func; }
>     static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes 
> = ptr; }
>     static void set_numa_all_nodes_ptr(struct bitmask **ptr) { 
> _numa_all_nodes_ptr = (ptr == NULL ? NULL : *ptr); }
>     static void set_numa_nodes_ptr(struct bitmask **ptr) { 
> _numa_nodes_ptr = (ptr == NULL ? NULL : *ptr); }
> @@ -320,6 +326,15 @@
>       } else
>         return 0;
>     }
> +  // Check if node in bounded nodes
> +  static bool isnode_in_bounded_nodes(int node) {
> +    struct bitmask* bmp = _numa_get_membind != NULL ? 
> _numa_get_membind() : NULL;
> +    if (bmp != NULL && _numa_bitmask_isbitset != NULL && 
> _numa_bitmask_isbitset(bmp, node)) {
> +      return true;
> +    } else
> +      return false;
> +  }
> +  static bool issingle_node_bound();
>   };
>   #endif // OS_LINUX_VM_OS_LINUX_HPP
> 
> ==========================================================
> 
> On Fri, May 4, 2018 at 2:56 AM, White, Derek <Derek.White at cavium.com 
> <mailto:Derek.White at cavium.com>> wrote:
> 
>     Hi Swati,
> 
>     I think this was reported as JDK-8189922 "UseNUMA memory
>     interleaving allocates heap for unavailable nodes".
>     https://bugs.openjdk.java.net/browse/JDK-8189922
>     <https://bugs.openjdk.java.net/browse/JDK-8189922>
> 
>     Thanks for working on a fix for this!
> 
>       - Derek
> 
>     > -----Original Message-----
>     > From: hotspot-dev [mailto:hotspot-dev-bounces at openjdk.java.net
>     <mailto:hotspot-dev-bounces at openjdk.java.net>] On
>     > Behalf Of Swati Sharma
>     > Sent: Wednesday, May 02, 2018 6:24 AM
>     > To: David Holmes <david.holmes at oracle.com <mailto:david.holmes at oracle.com>>
>     > Cc: hotspot-dev at openjdk.java.net <mailto:hotspot-dev at openjdk.java.net>;
>     Prakash.Raghavendra at amd.com <mailto:Prakash.Raghavendra at amd.com>
>     > Subject: Re: UseNUMA membind Issue in openJDK
>     > 
>     > Hi David,
>     > 
>     > I have localized the struct bitmask declaration in os_linux.cpp.
>     > 
>     > Here is the updated patch
>     > ===================================PATCH======================
>     > =============================
>     > diff --git a/src/hotspot/os/linux/os_linux.cpp
>     > b/src/hotspot/os/linux/os_linux.cpp
>     > --- a/src/hotspot/os/linux/os_linux.cpp
>     > +++ b/src/hotspot/os/linux/os_linux.cpp
>     > @@ -2832,14 +2832,42 @@
>     >    // Map all node ids in which is possible to allocate memory. Also nodes are
>     >    // not always consecutively available, i.e. available from 0 to the highest
>     >    // node number.
>     > +  // If the nodes have been bound explicitly using numactl membind,
>      > + then  // allocate memory from those nodes only.
>     >    for (size_t node = 0; node <= highest_node_number; node++) {
>     > -    if (Linux::isnode_in_configured_nodes(node)) {
>     > +    if (Linux::isnode_in_bounded_nodes(node)) {
>     >        ids[i++] = node;
>     >      }
>     >    }
>     >    return i;
>     >  }
>     > 
>     > +extern "C"  struct bitmask {
>     > +  unsigned long size; /* number of bits in the map */
>     > +  unsigned long *maskp;
>     > +};
>     > +// Check if single memory node bound.
>     > +// Returns true if single memory node bound.
>     > +bool os::Linux::issingle_node_bound() {
>     > +  struct bitmask* bmp = _numa_get_membind != NULL ?
>     > _numa_get_membind() :
>     > NULL;
>     > +  if(bmp == NULL) return false;
>     > +  int issingle = 0;
>     > +  // System can have more than 64 nodes so check in all the elements of
>      > + // unsigned long array  for (unsigned long i = 0; i <
>     (bmp->size / (8
>      > + * sizeof(unsigned long)));
>     > i++) {
>     > +    if (bmp->maskp != NULL && (((bmp->maskp[i]) & (((bmp->maskp[i])) -
>      > + 1))
>      > == 0)) {
>      > +      issingle++;
>      > +    } else if (bmp->maskp[i] == 0) {
>      > +      continue;
>      > +    } else {
>      > +      return false;
>      > +    }
>      > +  }
>      > +  if (issingle == 1)
>      > +    return true;
>      > +  return false;
>      > +}
>      > +
>      >  bool os::get_page_info(char *start, page_info* info) {
>      >    return false;
>      >  }
>      > @@ -2930,6 +2958,10 @@
>      >                                                 libnuma_dlsym(handle,
>      > "numa_bitmask_isbitset")));
>      >        set_numa_distance(CAST_TO_FN_PTR(numa_distance_func_t,
>      >                                         libnuma_dlsym(handle,
>     "numa_distance")));
>      > +
>      > set_numa_set_membind(CAST_TO_FN_PTR(numa_set_membind_func_t,
>      > +                                          libnuma_dlsym(handle,
>      > "numa_set_membind")));
>      > +
>      > set_numa_get_membind(CAST_TO_FN_PTR(numa_get_membind_func_t,
>      > +                                          libnuma_v2_dlsym(handle,
>      > "numa_get_membind")));
>      >
>      >        if (numa_available() != -1) {
>      >          set_numa_all_nodes((unsigned long*)libnuma_dlsym(handle,
>      > "numa_all_nodes")); @@ -3054,6 +3086,8 @@
>      > os::Linux::numa_set_bind_policy_func_t
>     os::Linux::_numa_set_bind_policy;
>      > os::Linux::numa_bitmask_isbitset_func_t
>     os::Linux::_numa_bitmask_isbitset;
>      >  os::Linux::numa_distance_func_t os::Linux::_numa_distance;
>      > +os::Linux::numa_set_membind_func_t os::Linux::_numa_set_membind;
>      > +os::Linux::numa_get_membind_func_t os::Linux::_numa_get_membind;
>      >  unsigned long* os::Linux::_numa_all_nodes;  struct bitmask*
>      > os::Linux::_numa_all_nodes_ptr;  struct bitmask*
>      > os::Linux::_numa_nodes_ptr; @@ -4962,8 +4996,9 @@
>      >      if (!Linux::libnuma_init()) {
>      >        UseNUMA = false;
>      >      } else {
>      > -      if ((Linux::numa_max_node() < 1)) {
>      > -        // There's only one node(they start from 0), disable NUMA.
>      > +      if ((Linux::numa_max_node() < 1) ||
>     Linux::issingle_node_bound()) {
>      > +        // If there's only one node(they start from 0) or if the
>     process
>      > +        // is bound explicitly to a single node using membind,
>     disable
>      > NUMA.
>      >          UseNUMA = false;
>      >        }
>      >      }
>      > diff --git a/src/hotspot/os/linux/os_linux.hpp
>      > b/src/hotspot/os/linux/os_linux.hpp
>      > --- a/src/hotspot/os/linux/os_linux.hpp
>      > +++ b/src/hotspot/os/linux/os_linux.hpp
>      > @@ -228,6 +228,8 @@
>      >    typedef int (*numa_tonode_memory_func_t)(void *start, size_t
>     size, int
>      > node);
>      >    typedef void (*numa_interleave_memory_func_t)(void *start,
>     size_t size,
>      > unsigned long *nodemask);
>      >    typedef void (*numa_interleave_memory_v2_func_t)(void *start,
>     size_t
>      > size, struct bitmask* mask);
>      > +  typedef void (*numa_set_membind_func_t)(struct bitmask *mask);
>      > + typedef struct bitmask* (*numa_get_membind_func_t)(void);
>      >
>      >    typedef void (*numa_set_bind_policy_func_t)(int policy);
>      >    typedef int (*numa_bitmask_isbitset_func_t)(struct bitmask *bmp,
>      > unsigned int n); @@ -244,6 +246,8 @@
>      >    static numa_set_bind_policy_func_t _numa_set_bind_policy;
>      >    static numa_bitmask_isbitset_func_t _numa_bitmask_isbitset;
>      >    static numa_distance_func_t _numa_distance;
>      > +  static numa_set_membind_func_t _numa_set_membind;  static
>      > + numa_get_membind_func_t _numa_get_membind;
>     >    static unsigned long* _numa_all_nodes;
>     >    static struct bitmask* _numa_all_nodes_ptr;
>     >    static struct bitmask* _numa_nodes_ptr; @@ -259,6 +263,8 @@
>     >    static void set_numa_set_bind_policy(numa_set_bind_policy_func_t func)
>     > { _numa_set_bind_policy = func; }
>     >    static void set_numa_bitmask_isbitset(numa_bitmask_isbitset_func_t
>     > func) { _numa_bitmask_isbitset = func; }
>     >    static void set_numa_distance(numa_distance_func_t func) {
>     > _numa_distance = func; }
>     > +  static void set_numa_set_membind(numa_set_membind_func_t func) {
>     > _numa_set_membind = func; }
>     > +  static void set_numa_get_membind(numa_get_membind_func_t func) {
>     > _numa_get_membind = func; }
>     >    static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes =
>     > ptr; }
>     >    static void set_numa_all_nodes_ptr(struct bitmask **ptr) {
>     > _numa_all_nodes_ptr = (ptr == NULL ? NULL : *ptr); }
>     >    static void set_numa_nodes_ptr(struct bitmask **ptr) { _numa_nodes_ptr
>     > = (ptr == NULL ? NULL : *ptr); } @@ -320,6 +326,15 @@
>     >      } else
>     >        return 0;
>     >    }
>     > +  // Check if node in bounded nodes
>     > +  static bool isnode_in_bounded_nodes(int node) {
>     > +    struct bitmask* bmp = _numa_get_membind != NULL ?
>      > + _numa_get_membind()
>      > : NULL;
>      > +    if (bmp != NULL && _numa_bitmask_isbitset != NULL &&
>      > _numa_bitmask_isbitset(bmp, node)) {
>      > +      return true;
>      > +    } else
>      > +      return false;
>      > +  }
>      > +  static bool issingle_node_bound();
>      >  };
>      >
>      >  #endif // OS_LINUX_VM_OS_LINUX_HPP
>      >
>      > ===============================================================
>      > =============================
>      >
>      > Thanks,
>      > Swati
>      >
>      > On Thu, Apr 26, 2018 at 6:10 PM, David Holmes
>     <david.holmes at oracle.com <mailto:david.holmes at oracle.com>>
>      > wrote:
>      > >
>      > > Hi Swati,
>      > >
>      > > On 26/04/2018 10:20 PM, Swati Sharma wrote:
>      > >>
>      > >> Hi Everyone,
>      > >>
>      > >> I work at AMD and this is my first patch as a new member of
>     openJDK
>      > >> community.
>      > >
>      > >
>      > > Welcome!
>      > >
>      > > I can't comment on the actual NUMA details of the patch (though
>     I can
>      > > see
>      > what you're doing), but the struct bitmask declaration in os.hpp
>     should be
>      > localized in os_linux.hpp as far as I can see, as it's only
>     needed internally in
>      > the Linux code.
>      > >
>      > > Thanks,
>      > > David
>      > > -----
>      > >
>      > >
>      > >> I have found some issue while running  specjbb2015 composite
>     workload
>      > with
>      > >> the flag -XX:+UseNUMA. It seems that JVM does not allocate memory
>      > according
>      > >> to the explicit node binding done using "numactl --membind".
>      > >>
>      > >> E.g. If bound to a single memory node,  JVM divides the whole heap
>      > >> based
>      > on
>      > >> the total number of numa nodes available on the system which
>     creates
>      > >> more logical groups(lgrps) than required which cannot be used
>     except the
>      > one.
>      > >>
>      > >> The following examples will explain clearly :
>      > >> (Note : Collected GC logs with
>      > >> -Xlog:gc*=debug:file=gc.log:time,uptimemillis)
>      > >> 1) Allocating a heap of 22GB for single node divides the whole
>     heap
>      > >> in 8 lgrp(Actual no of Nodes are 8)
>      > >>      $numactl --cpunodebind=0 --membind=0 java -Xmx24g -Xms24g
>      > >> -Xmn22g -XX:+UseNUMA <composite_application>
>      > >>
>      > >>      eden space 22511616K(22GB), 12% used
>      > >>      lgrp 0 space 2813952K, 100% used                     
>       lgrp 1 space
>      > >> 2813952K, 0% used                          lgrp 2 space
>     2813952K, 0% used
>      > >>      lgrp 3 space 2813952K, 0% used                         
>       lgrp 4
>      > space
>      > >> 2813952K, 0% used                          lgrp 5 space
>     2813952K, 0% used
>      > >>      lgrp 6 space 2813952K, 0% used                         
>       lgrp 7
>      > space
>      > >> 2813952K, 0% used
>      > >>
>      > >> Observation : Instead of disabling UseNUMA for single node binding
>      > >> JVM divides the memory in 8 lgrps and allocates memory always
>     on the
>      > >> bounded node hence in eden space allocation never happens more
>     than
>      > 12%.
>      > >>
>      > >> 2) Another case of binding to node 0 and 7 results in dividing the
>      > >> heap
>      > in
>      > >> 8lgrp
>      > >>      $numactl --cpunodebind=0,7 –membind=0,7 java -Xms50g
>     -Xmx50g -
>      > Xmn45g
>      > >>   -XX:+UseNUMA <composite_application>
>      > >>
>      > >>      eden space 46718976K, 6% used
>      > >>      lgrp 0 space 5838848K, 14% used                  lgrp 1 space
>      > 5838848K,
>      > >> 0% used                              lgrp 2 space 5838848K, 0%
>     used
>      > >>      lgrp 3 space 5838848K, 0% used                    lgrp 4
>     space
>      > >> 5838848K, 0% used                              lgrp 5 space
>     5838848K, 0%
>      > >> used
>      > >>       lgrp 6 space 5838848K, 0% used                    lgrp 7
>     space
>      > >> 5847040K, 35% used
>      > >>
>      > >> Observation : Similar to first case allocation happens only on 0th
>      > >> and
>      > 7th
>      > >> node and rest of the lgrps never gets used.
>      > >>
>      > >> After applying the patch, JVM divides the given heap size
>     according
>      > >> to
>      > the
>      > >> bounded memory nodes only.
>      > >>
>      > >> 1) Binding to single node disables UseNUMA
>      > >>      eden space 46718976K(45GB), 99% used
>      > >>
>      > >> Observation : UseNUMA gets disabled hence no lgrp creation and the
>      > >> whole heap allocation happens on the bounded node.
>      > >>
>      > >> 2) Binding to node 0 and 7
>      > >>       $ numactl --cpunodebind=0,7 –membind=0,7 java -Xms50g
>     -Xmx50g
>      > -Xmn45g
>      > >>   -XX:+UseNUMA <composite_application>
>      > >>       eden space 46718976K(45GB), 99% used
>      > >>       lgrp 0 space 23359488K(23.5GB), 100% used           
>     lgrp 7 space
>      > >> 23359488K(23.5GB), 99% used
>      > >>
>      > >> Observation : Only two lgrps gets created and heap size gets
>     divided
>      > >> equally in both nodes.
>      > >>
>      > >> If there is no binding, then JVM will divide the whole heap
>     based on
>      > >> the number of NUMA nodes available on the system.
>      > >>
>      > >> The following patch fixes the issue(attached also).
>      > >> Please review and let me know your comments.
>      > >>
>      > >> Regression testing using jtreg (make -J=1 run-test-tier1
>      > >> run-test-tier2) didn't show any new failures.
>      > >>
>      > >>
>      > ===============================PATCH==========================
>      > ==============
>      > >> diff --git a/src/hotspot/os/linux/os_linux.cpp
>      > >> b/src/hotspot/os/linux/os_linux.cpp
>      > >> --- a/src/hotspot/os/linux/os_linux.cpp
>      > >> +++ b/src/hotspot/os/linux/os_linux.cpp
>      > >> @@ -2832,8 +2832,10 @@
>      > >>     // Map all node ids in which is possible to allocate
>     memory. Also
>      > nodes
>      > >> are
>      > >>     // not always consecutively available, i.e. available from
>     0 to
>      > >> the highest
>      > >>     // node number.
>      > >> +  // If the nodes have been bound explicitly using numactl
>     membind,
>      > >> + then  // allocate memory from those nodes only.
>      > >>     for (size_t node = 0; node <= highest_node_number; node++) {
>      > >> -    if (Linux::isnode_in_configured_nodes(node)) {
>      > >> +    if (Linux::isnode_in_bounded_nodes(node)) {
>      > >>         ids[i++] = node;
>      > >>       }
>      > >>     }
>      > >> @@ -2930,6 +2932,10 @@
>      > >>
>      > >> libnuma_dlsym(handle, "numa_bitmask_isbitset")));
>      > >>         set_numa_distance(CAST_TO_FN_PTR(numa_distance_func_t,
>      > >>                                          libnuma_dlsym(handle,
>      > >> "numa_distance")));
>      > >> +
>      > set_numa_set_membind(CAST_TO_FN_PTR(numa_set_membind_func_t,
>      > >> +                                          libnuma_dlsym(handle,
>      > >> "numa_set_membind")));
>      > >> +
>      > set_numa_get_membind(CAST_TO_FN_PTR(numa_get_membind_func_t,
>      > >> +                                         
>     libnuma_v2_dlsym(handle,
>      > >> "numa_get_membind")));
>      > >>
>      > >>         if (numa_available() != -1) {
>      > >>           set_numa_all_nodes((unsigned long*)libnuma_dlsym(handle,
>      > >> "numa_all_nodes")); @@ -3054,6 +3060,8 @@
>      > >>   os::Linux::numa_set_bind_policy_func_t
>      > os::Linux::_numa_set_bind_policy;
>      > >>   os::Linux::numa_bitmask_isbitset_func_t
>      > os::Linux::_numa_bitmask_isbitset;
>      > >>   os::Linux::numa_distance_func_t os::Linux::_numa_distance;
>      > >> +os::Linux::numa_set_membind_func_t os::Linux::_numa_set_membind;
>      > >> +os::Linux::numa_get_membind_func_t os::Linux::_numa_get_membind;
>      > >>   unsigned long* os::Linux::_numa_all_nodes;
>      > >>   struct bitmask* os::Linux::_numa_all_nodes_ptr;
>      > >>   struct bitmask* os::Linux::_numa_nodes_ptr; @@ -4962,8
>     +4970,9 @@
>      > >>       if (!Linux::libnuma_init()) {
>      > >>         UseNUMA = false;
>      > >>       } else {
>      > >> -      if ((Linux::numa_max_node() < 1)) {
>      > >> -        // There's only one node(they start from 0), disable
>     NUMA.
>      > >> +      if ((Linux::numa_max_node() < 1) ||
>      > >> + Linux::issingle_node_bound())
>     > {
>     > >> +        // If there's only one node(they start from 0) or if the process
>     > >> +        // is bound explicitly to a single node using membind,
>      > >> + disable
>     > >> NUMA.
>     > >>           UseNUMA = false;
>     > >>         }
>     > >>       }
>     > >> diff --git a/src/hotspot/os/linux/os_linux.hpp
>     > >> b/src/hotspot/os/linux/os_linux.hpp
>     > >> --- a/src/hotspot/os/linux/os_linux.hpp
>     > >> +++ b/src/hotspot/os/linux/os_linux.hpp
>     > >> @@ -228,6 +228,8 @@
>     > >>     typedef int (*numa_tonode_memory_func_t)(void *start, size_t
>     > >> size,
>     > int
>     > >> node);
>     > >>     typedef void (*numa_interleave_memory_func_t)(void *start, size_t
>     > size,
>     > >> unsigned long *nodemask);
>     > >>     typedef void (*numa_interleave_memory_v2_func_t)(void *start,
>     > >> size_t size, struct bitmask* mask);
>     > >> +  typedef void (*numa_set_membind_func_t)(struct bitmask *mask);
>     > >> + typedef struct bitmask* (*numa_get_membind_func_t)(void);
>     > >>
>     > >>     typedef void (*numa_set_bind_policy_func_t)(int policy);
>     > >>     typedef int (*numa_bitmask_isbitset_func_t)(struct bitmask *bmp,
>     > >> unsigned int n); @@ -244,6 +246,8 @@
>     > >>     static numa_set_bind_policy_func_t _numa_set_bind_policy;
>     > >>     static numa_bitmask_isbitset_func_t _numa_bitmask_isbitset;
>     > >>     static numa_distance_func_t _numa_distance;
>      > >> +  static numa_set_membind_func_t _numa_set_membind;  static
>      > >> + numa_get_membind_func_t _numa_get_membind;
>      > >>     static unsigned long* _numa_all_nodes;
>      > >>     static struct bitmask* _numa_all_nodes_ptr;
>      > >>     static struct bitmask* _numa_nodes_ptr; @@ -259,6 +263,8 @@
>      > >>     static void
>     set_numa_set_bind_policy(numa_set_bind_policy_func_t
>      > func) {
>      > >> _numa_set_bind_policy = func; }
>      > >>     static void
>      > >> set_numa_bitmask_isbitset(numa_bitmask_isbitset_func_t
>      > func)
>      > >> { _numa_bitmask_isbitset = func; }
>      > >>     static void set_numa_distance(numa_distance_func_t func) {
>      > >> _numa_distance = func; }
>      > >> +  static void set_numa_set_membind(numa_set_membind_func_t func)
>      > {
>      > >> _numa_set_membind = func; }
>      > >> +  static void set_numa_get_membind(numa_get_membind_func_t func)
>      > {
>      > >> _numa_get_membind = func; }
>      > >>     static void set_numa_all_nodes(unsigned long* ptr) {
>      > >> _numa_all_nodes
>      > =
>      > >> ptr; }
>      > >>     static void set_numa_all_nodes_ptr(struct bitmask **ptr) {
>      > >> _numa_all_nodes_ptr = (ptr == NULL ? NULL : *ptr); }
>      > >>     static void set_numa_nodes_ptr(struct bitmask **ptr) {
>      > _numa_nodes_ptr =
>      > >> (ptr == NULL ? NULL : *ptr); }
>      > >> @@ -320,6 +326,34 @@
>      > >>       } else
>      > >>         return 0;
>      > >>     }
>      > >> +  // Check if node in bounded nodes
>      > >> +  static bool isnode_in_bounded_nodes(int node) {
>      > >> +    struct bitmask* bmp = _numa_get_membind != NULL ?
>      > _numa_get_membind()
>      > >> : NULL;
>      > >> +    if (bmp != NULL && _numa_bitmask_isbitset != NULL &&
>      > >> _numa_bitmask_isbitset(bmp, node)) {
>      > >> +      return true;
>      > >> +    } else
>      > >> +      return false;
>      > >> +  }
>      > >> +  // Check if a single node is bound  static bool
>      > >> + issingle_node_bound() {
>     > >> +    struct bitmask* bmp = _numa_get_membind != NULL ?
>     > _numa_get_membind()
>     > >> : NULL;
>     > >> +    if(bmp == NULL) return false;
>     > >> +    int issingle = 0;
>     > >> +    // System can have more than 64 nodes so check in all the
>      > >> + elements
>     > of
>     > >> +    // unsigned long array
>     > >> +    for (unsigned long i = 0; i < (bmp->size / (8 * sizeof(unsigned
>     > >> long))); i++) {
>     > >> +       if (bmp->maskp != NULL && (((bmp->maskp[i]) &
>      > >> + (((bmp->maskp[i]))
>      > -
>      > >> 1)) == 0)) {
>      > >> +         issingle++;
>      > >> +       } else if (bmp->maskp[i] == 0) {
>      > >> +         continue;
>      > >> +       } else {
>      > >> +         return false;
>      > >> +       }
>      > >> +    }
>      > >> +    if (issingle == 1)
>      > >> +      return true;
>      > >> +    return false;
>      > >> +  }
>      > >>   };
>      > >>
>      > >>   #endif // OS_LINUX_VM_OS_LINUX_HPP
>      > >> diff --git a/src/hotspot/share/runtime/os.hpp
>      > >> b/src/hotspot/share/runtime/os.hpp
>      > >> --- a/src/hotspot/share/runtime/os.hpp
>      > >> +++ b/src/hotspot/share/runtime/os.hpp
>      > >> @@ -81,6 +81,10 @@
>      > >>     CriticalPriority = 11      // Critical thread priority
>      > >>   };
>      > >>
>      > >> +extern "C" struct bitmask {
>      > >> +  unsigned long size; /* number of bits in the map */
>      > >> +  unsigned long *maskp;
>      > >> +};
>      > >>   // Executable parameter flag for os::commit_memory() and
>      > >>   // os::commit_memory_or_exit().
>      > >>   const bool ExecMem = true;
>      > >>
>      > >>
>      > ===============================================================
>      > ==============
>      > >>
>      > >> Thanks,
>      > >> Swati
>      > >>
> 
> 


More information about the hotspot-dev mailing list