diff options
author | Lukas Larsson <[email protected]> | 2015-07-16 15:36:44 +0200 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2016-02-02 10:45:22 +0100 |
commit | 6090f9c7e9b0ddbccef357641c1455475b348e94 (patch) | |
tree | 05651df115da49195739fa11009bc9c225f85ce8 | |
parent | 0399f5fc547ef035c4eb5e383f30b28ae73d936e (diff) | |
download | otp-6090f9c7e9b0ddbccef357641c1455475b348e94.tar.gz otp-6090f9c7e9b0ddbccef357641c1455475b348e94.tar.bz2 otp-6090f9c7e9b0ddbccef357641c1455475b348e94.zip |
erts: Add power saving cpu feature tests and use them
-rw-r--r-- | erts/emulator/sys/unix/sys_time.c | 16 | ||||
-rw-r--r-- | erts/include/internal/ethread.h | 50 | ||||
-rw-r--r-- | erts/lib_src/common/ethr_aux.c | 29 |
3 files changed, 69 insertions, 26 deletions
diff --git a/erts/emulator/sys/unix/sys_time.c b/erts/emulator/sys/unix/sys_time.c index 9738a8c352..03d39c7ce6 100644 --- a/erts/emulator/sys/unix/sys_time.c +++ b/erts/emulator/sys/unix/sys_time.c @@ -971,18 +971,18 @@ static ErtsSysPerfCounter calculate_perf_counter_unit(void) { static int have_rdtscp(void) { #if defined(ETHR_X86_RUNTIME_CONF__) - /* On early x86 cpu's the tsc varies with - the current speed of the cpu, which means that the time per - tick vary depending on the current load of the cpu. We do not - want this as it would give very scewed numbers when the cpu is - mostly idle. - If we have the rdtscp feature it is a sign that the cpu is - relatively modern, and thus the tsc quite stable so we use it then. + /* On early x86 cpu's the tsc varies with the current speed of the cpu, + which means that the time per tick vary depending on the current + load of the cpu. We do not want this as it would give very scewed + numbers when the cpu is mostly idle. + The linux kernel seems to think that checking for constant and + reliable is enough to trust the counter so we do the same. If this test is not good enough, I don't know what we'll do. Maybe fallback on erts_sys_hrtime always, but that would be a shame as rdtsc is about 3 times faster than hrtime... */ - return ETHR_X86_RUNTIME_CONF_HAVE_RDTSCP__; + return ETHR_X86_RUNTIME_CONF_HAVE_CONSTANT_TSC__ && + ETHR_X86_RUNTIME_CONF_HAVE_TSC_RELIABLE__; #else return 0; #endif diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h index 9956473057..e5c5cdfa33 100644 --- a/erts/include/internal/ethread.h +++ b/erts/include/internal/ethread.h @@ -274,18 +274,40 @@ ETHR_PROTO_NORETURN__ ethr_fatal_error__(const char *file, || (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64)))) # define ETHR_X86_RUNTIME_CONF__ -# define ETHR_X86_RUNTIME_CONF_HAVE_DW_CMPXCHG__ \ - (__builtin_expect(ethr_runtime__.conf.have_dw_cmpxchg != 0, 1)) -# define ETHR_X86_RUNTIME_CONF_HAVE_NO_DW_CMPXCHG__ \ - (__builtin_expect(ethr_runtime__.conf.have_dw_cmpxchg == 0, 0)) -# define ETHR_X86_RUNTIME_CONF_HAVE_SSE2__ \ - (__builtin_expect(ethr_runtime__.conf.have_sse2 != 0, 1)) -# define ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__ \ - (__builtin_expect(ethr_runtime__.conf.have_sse2 == 0, 0)) -# define ETHR_X86_RUNTIME_CONF_HAVE_RDTSCP__ \ - (__builtin_expect(ethr_runtime__.conf.have_rdtscp != 0, 1)) -# define ETHR_X86_RUNTIME_CONF_HAVE_NO_RDTSCP__ \ - (__builtin_expect(ethr_runtime__.conf.have_rdtscp == 0, 0)) +# define ETHR_X86_RUNTIME_CONF_HAVE_META(feature) \ + (__builtin_expect(ethr_runtime__.conf.have_##feature != 0, 1)) +# define ETHR_X86_RUNTIME_CONF_HAVE_NO_META(feature) \ + (__builtin_expect(ethr_runtime__.conf.have_##feature == 0, 0)) + +# define ETHR_X86_RUNTIME_CONF_HAVE_DW_CMPXCHG__ \ + ETHR_X86_RUNTIME_CONF_HAVE_META(dw_cmpxchg) +# define ETHR_X86_RUNTIME_CONF_HAVE_NO_DW_CMPXCHG__ \ + ETHR_X86_RUNTIME_CONF_HAVE_NO_META(dw_cmpxchg) +# define ETHR_X86_RUNTIME_CONF_HAVE_SSE2__ \ + ETHR_X86_RUNTIME_CONF_HAVE_META(sse2) +# define ETHR_X86_RUNTIME_CONF_HAVE_NO_SSE2__ \ + ETHR_X86_RUNTIME_CONF_HAVE_NO_META(sse2) +# define ETHR_X86_RUNTIME_CONF_HAVE_RDTSCP__ \ + ETHR_X86_RUNTIME_CONF_HAVE_META(rdtscp) +# define ETHR_X86_RUNTIME_CONF_HAVE_NO_RDTSCP__ \ + ETHR_X86_RUNTIME_CONF_HAVE_NO_META(rdtscp) +# define ETHR_X86_RUNTIME_CONF_HAVE_CONSTANT_TSC__ \ + ETHR_X86_RUNTIME_CONF_HAVE_META(constant_tsc) +# define ETHR_X86_RUNTIME_CONF_HAVE_NO_CONSTANT_TSC__ \ + ETHR_X86_RUNTIME_CONF_HAVE_NO_META(nonstop_tsc) +# define ETHR_X86_RUNTIME_CONF_HAVE_NONSTOP_TSC__ \ + ETHR_X86_RUNTIME_CONF_HAVE_META(nonstop_tsc) +# define ETHR_X86_RUNTIME_CONF_HAVE_NO_NONSTOP_TSC__ \ + ETHR_X86_RUNTIME_CONF_HAVE_NO_META(nonstop_tsc) +# define ETHR_X86_RUNTIME_CONF_HAVE_TSC_RELIABLE__ \ + ETHR_X86_RUNTIME_CONF_HAVE_META(tsc_reliable) +# define ETHR_X86_RUNTIME_CONF_HAVE_NO_TSC_RELIABLE_TSC__ \ + ETHR_X86_RUNTIME_CONF_HAVE_NO_META(tsc_reliable) +# define ETHR_X86_RUNTIME_CONF_HAVE_NONSTOP_TSC_S3__ \ + ETHR_X86_RUNTIME_CONF_HAVE_META(nonstop_tsc_s3) +# define ETHR_X86_RUNTIME_CONF_HAVE_NO_NONSTOP_TSC_S3__ \ + ETHR_X86_RUNTIME_CONF_HAVE_NO_META(nonstop_tsc_s3) + #endif #if (defined(__GNUC__) \ @@ -305,6 +327,10 @@ typedef struct { int have_dw_cmpxchg; int have_sse2; int have_rdtscp; + int have_constant_tsc; + int have_tsc_reliable; + int have_nonstop_tsc; + int have_nonstop_tsc_s3; #endif #if defined(ETHR_PPC_RUNTIME_CONF__) int have_lwsync; diff --git a/erts/lib_src/common/ethr_aux.c b/erts/lib_src/common/ethr_aux.c index fbd870c2b5..3e7aad16c7 100644 --- a/erts/lib_src/common/ethr_aux.c +++ b/erts/lib_src/common/ethr_aux.c @@ -144,16 +144,33 @@ x86_init(void) eax = 0x80000000; ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx); - if (eax >= 0x80000001) { - /* Get the extended feature set */ - eax = 0x80000001; + if (eax < 0x80000001) + return; + + if (eax >= 0x80000007) { + /* Advanced Power Management Information */ + eax = 0x80000007; ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx); - } else { - eax = ebx = ecx = edx = 0; + + /* I got the values below from: + http://lxr.free-electrons.com/source/arch/x86/include/asm/cpufeature.h + They can be gotten from the intel/amd manual as well. + */ + + ethr_runtime__.conf.have_constant_tsc = (edx & (1 << 8)); + ethr_runtime__.conf.have_tsc_reliable = (edx & (1 << 23)); + ethr_runtime__.conf.have_nonstop_tsc = (edx & (1 << 24)); + ethr_runtime__.conf.have_nonstop_tsc_s3 = (edx & (1 << 30)); + } - + + /* Extended Processor Info and Feature Bits */ + eax = 0x80000001; + ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx); + /* bit 27 of edx is set if we have rdtscp */ ethr_runtime__.conf.have_rdtscp = (edx & (1 << 27)); + } #endif /* ETHR_X86_RUNTIME_CONF__ */ |