[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#908928: Most architectures do not need to check /etc/ld.so.nohwcap



Package: glibc
Version: 2.27-6
Tags: patch

Debian's glibc includes a Debian-specific patch that makes the dynamic
linker check for the existence of /etc/ld.so.nohwcap (multiple times)
before loading a shared library, and disable loading of libraries in
hwcap paths (optimized libraries) if found. This gets created in the
libc6 (or equivalent) package preinst, and removed by the various libc
packages' postinsts once all glibc packages have been upgraded to
identical versions.

However, only two architectures have hwcap-based libc packages: i386
(which has libc6-xen), and alpha (which has libc6.1-alphaev67). Other
architectures don't have any such packages, but still spend time
checking for /etc/ld.so.nohwcap on every dynamic library load.

I measured the impact of this, by running a defconfig kernel build under
strace. These access syscalls took an average of 17us per call, and
comprised 125453 (0.66%) of the 19069475 syscalls during the build.
Overall, they added an estimated 2.1s to the build.

The attached patch makes the check for /etc/ld.so.nohwcap conditional
based on architecture, and only includes it on i386 and alpha. This
removes the overhead from all other architectures.

Note that if any future architecture ever needed to add such libraries
(and we don't have a better mechanism to handle this at that time), we
can easily add the check on that architecture.

- Josh Triplett
diff --git a/debian/patches/any/local-ldso-disable-hwcap.diff b/debian/patches/any/local-ldso-disable-hwcap.diff
index 933032ec..dccbfe6a 100644
--- a/debian/patches/any/local-ldso-disable-hwcap.diff
+++ b/debian/patches/any/local-ldso-disable-hwcap.diff
@@ -24,7 +24,7 @@
 
  #include <dl-procinfo.h>
  #include <dl-hwcaps.h>
-@@ -44,6 +46,7 @@
+@@ -43,6 +46,7 @@
    size_t cnt = platform != NULL;
    size_t n, m;
    size_t total;
@@ -32,10 +32,11 @@
    struct r_strlenpair *result;
    struct r_strlenpair *rp;
    char *cp;
-@@ -113,8 +116,22 @@
+@@ -124,8 +128,24 @@
    /* For TLS enabled builds always add 'tls'.  */
    ++cnt;
  
++#ifdef NEED_LD_SO_NOHWCAP
 +  if (__access_noerrno ("/etc/ld.so.nohwcap", F_OK) == 0)
 +    {
 +      /* If hwcap is disabled, we only have the base directory to search.  */
@@ -49,6 +50,7 @@
 +      *sz = 1;
 +      return result;
 +    }
++#endif
 +
    /* Create temporary data structure to generate result table.  */
 -  struct r_strlenpair temp[cnt];
@@ -56,14 +58,16 @@
    m = 0;
  #ifdef NEED_DL_SYSINFO_DSO
    if (dsocaps != NULL)
-@@ -199,8 +216,11 @@
+@@ -210,8 +230,13 @@
    *sz = 1 << cnt;
    result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
    if (result == NULL)
 -    _dl_signal_error (ENOMEM, NULL, NULL,
 -		      N_("cannot create capability list"));
 +    {
++#ifdef NEED_LD_SO_NOHWCAP
 +    no_memory:
++#endif
 +      _dl_signal_error (ENOMEM, NULL, NULL,
 +		     	N_("cannot create capability list"));
 +    }
@@ -82,7 +86,7 @@
  
  #ifndef _DL_PLATFORMS_COUNT
  # define _DL_PLATFORMS_COUNT 0
-@@ -248,6 +250,7 @@
+@@ -246,6 +249,7 @@
    if (cache_new != (void *) -1)
      {
        uint64_t platform;
@@ -90,17 +94,19 @@
  
        /* This is where the strings start.  */
        cache_data = (const char *) cache_new;
-@@ -261,6 +264,9 @@
+@@ -259,6 +263,11 @@
  
        uint64_t hwcap_mask = GET_HWCAP_MASK();
  
++#ifdef NEED_LD_SO_NOHWCAP
 +      if (__access_noerrno ("/etc/ld.so.nohwcap", F_OK) == 0)
 +	disable_hwcap = 1;
++#endif
 +
  #define _DL_HWCAP_TLS_MASK (1LL << 63)
        uint64_t hwcap_exclude = ~((GLRO(dl_hwcap) & hwcap_mask)
  				 | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK);
-@@ -271,6 +277,8 @@
+@@ -269,6 +278,8 @@
  	continue;							      \
        if (GLRO(dl_osversion) && lib->osversion > GLRO(dl_osversion))	      \
  	continue;							      \
@@ -109,3 +115,25 @@
        if (_DL_PLATFORMS_COUNT						      \
  	  && (lib->hwcap & _DL_HWCAP_PLATFORM) != 0			      \
  	  && (lib->hwcap & _DL_HWCAP_PLATFORM) != platform)		      \
+--- a/sysdeps/alpha/ldsodefs.h
++++ b/sysdeps/alpha/ldsodefs.h
+@@ -37,6 +37,8 @@ struct La_alpha_retval;
+ 				      struct La_alpha_retval *,		\
+ 				      const char *);
+
++#define NEED_LD_SO_NOHWCAP
++
+ #include_next <ldsodefs.h>
+
+ #endif
+--- a/sysdeps/i386/ldsodefs.h
++++ b/sysdeps/i386/ldsodefs.h
+@@ -36,6 +36,8 @@ struct La_i86_retval;
+ 				     uintptr_t *, const struct La_i86_regs *, \
+ 				     struct La_i86_retval *, const char *)
+
++#define NEED_LD_SO_NOHWCAP
++
+ #include_next <ldsodefs.h>
+ 
+ #endif

Reply to: