Prepare use if IFUNC functions outside libc.so.
authorUlrich Drepper <drepper@redhat.com>
Wed, 29 Jul 2009 22:22:28 +0000 (15:22 -0700)
committerUlrich Drepper <drepper@redhat.com>
Wed, 29 Jul 2009 22:22:28 +0000 (15:22 -0700)
We use a callback function into libc.so to get access to the data
structure with the information and have special versions of the test
macros which automatically use this function.

include/libc-symbols.h
sysdeps/x86_64/multiarch/init-arch.c
sysdeps/x86_64/multiarch/init-arch.h

index 68da77c..252141e 100644 (file)
@@ -1,6 +1,6 @@
 /* Support macros for making weak and strong aliases for symbols,
    and for using symbol sets and linker warnings with GNU ld.
-   Copyright (C) 1995-1998, 2000-2006, 2008 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998,2000-2006,2008,2009 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -845,6 +845,17 @@ for linking")
   }                                                                    \
   __asm__ (".type " #name ", %gnu_indirect_function");
 
+/* The body of the function is supposed to use __get_cpu_features
+   which will, if necessary, initialize the data first.  */
+#define libm_ifunc(name, expr)                                         \
+  extern void *name##_ifunc (void) __asm__ (#name);                    \
+  void *name##_ifunc (void)                                            \
+  {                                                                    \
+    __typeof (name) *res = expr;                                       \
+    return res;                                                                \
+  }                                                                    \
+  __asm__ (".type " #name ", %gnu_indirect_function");
+
 #ifdef HAVE_ASM_SET_DIRECTIVE
 # define libc_ifunc_hidden_def1(local, name)                           \
     __asm__ (declare_symbol_alias_1_stringify (ASM_GLOBAL_DIRECTIVE)   \
index 35fd19a..49b421e 100644 (file)
@@ -86,3 +86,13 @@ __init_cpu_features (void)
   else
     __cpu_features.kind = arch_kind_other;
 }
+
+
+const struct cpu_features *
+__get_cpu_features (void)
+{
+  if (__cpu_features.kind == arch_kind_unknown)
+    __init_cpu_features ();
+
+  return &__cpu_features;
+}
index 48a2127..0151e8b 100644 (file)
@@ -54,10 +54,28 @@ extern void __init_cpu_features (void) attribute_hidden;
       __init_cpu_features ();                          \
   while (0)
 
+/* Used from outside libc.so to get access to the CPU features structure.  */
+extern const struct cpu_features *__get_cpu_features (void)
+     __attribute__ ((const));
+
 /* Following are the feature tests used throughout libc.  */
 
-#define HAS_POPCOUNT \
+#ifndef NOT_IN_libc
+# define HAS_POPCOUNT \
   ((__cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx & (1 << 23)) != 0)
 
-#define HAS_SSE4_2 \
+# define HAS_SSE4_2 \
   ((__cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx & (1 << 20)) != 0)
+
+# define HAS_FMA \
+  ((__cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx & (1 << 12)) != 0)
+#else
+# define HAS_POPCOUNT \
+  ((__get_cpu_features ()->cpuid[COMMON_CPUID_INDEX_1].ecx & (1 << 23)) != 0)
+
+# define HAS_SSE4_2 \
+  ((__get_cpu_features ()->cpuid[COMMON_CPUID_INDEX_1].ecx & (1 << 20)) != 0)
+
+# define HAS_FMA \
+  ((__get_cpu_features ()->cpuid[COMMON_CPUID_INDEX_1].ecx & (1 << 12)) != 0)
+#endif