riscv64: pass a pointer to __riscv_hwprobe() to ifunc resolvers.
This way, callees don't need to worry about whether or not their
reference to __riscv_hwprobe() has been resolved before their ifunc
resolver is called.
This matches the current glibc proposal from rivos.
Test: treehugger
Change-Id: I0d5244aa837d0d1f0e6bd7d22091dfedb8a55bdb
diff --git a/libc/bionic/bionic_call_ifunc_resolver.cpp b/libc/bionic/bionic_call_ifunc_resolver.cpp
index 0b12088..d5a812c 100644
--- a/libc/bionic/bionic_call_ifunc_resolver.cpp
+++ b/libc/bionic/bionic_call_ifunc_resolver.cpp
@@ -28,6 +28,7 @@
#include "private/bionic_call_ifunc_resolver.h"
#include <sys/auxv.h>
+#include <sys/hwprobe.h>
#include <sys/ifunc.h>
#include "bionic/macros.h"
@@ -51,20 +52,15 @@
return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(arg._hwcap | _IFUNC_ARG_HWCAP, &arg);
#elif defined(__arm__)
typedef ElfW(Addr) (*ifunc_resolver_t)(unsigned long);
- static unsigned long hwcap;
- static bool initialized = false;
- if (!initialized) {
- initialized = true;
- hwcap = getauxval(AT_HWCAP);
- }
+ static unsigned long hwcap = getauxval(AT_HWCAP);
return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap);
#elif defined(__riscv)
- // The pointer argument is currently unused, but reserved for future
+ // The third argument is currently unused, but reserved for future
// expansion. If we pass nullptr from the beginning, it'll be easier
// to recognize if/when we pass actual data (and matches glibc).
- typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, void*);
+ typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, __riscv_hwprobe_t, void*);
static uint64_t hwcap = getauxval(AT_HWCAP);
- return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap, nullptr);
+ return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap, __riscv_hwprobe, nullptr);
#else
typedef ElfW(Addr) (*ifunc_resolver_t)(void);
return reinterpret_cast<ifunc_resolver_t>(resolver_addr)();