aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils/os_utils.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-01-27 22:12:50 -0500
committerJack Lloyd <[email protected]>2017-01-27 22:12:50 -0500
commit641798154f2083258b6ffb0c398d73221ff8959e (patch)
tree7fdfb0a0ea21fd7d691ad8b2a98205613cf2e2ea /src/lib/utils/os_utils.cpp
parent5cbba3ad662fa76090a3bea546a1178a011737a7 (diff)
Change meaning of get_processor_timestamp
Now let it return 0 if we have no hardware timestamp, and add OS::get_high_resolution_clock for best available clock. This is mainly because it's confusing for get_processor_timestamp to return something that is not a processor timestamp and because it simplifies adding cycles/byte output if we know that something is or is not a cycle counter. Also adds Windows SEH version of run_cpu_instruction_probe. Untested, uncompiled.
Diffstat (limited to 'src/lib/utils/os_utils.cpp')
-rw-r--r--src/lib/utils/os_utils.cpp85
1 files changed, 57 insertions, 28 deletions
diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp
index c6d99237c..1cf356666 100644
--- a/src/lib/utils/os_utils.cpp
+++ b/src/lib/utils/os_utils.cpp
@@ -28,9 +28,7 @@
namespace Botan {
-namespace OS {
-
-uint32_t get_process_id()
+uint32_t OS::get_process_id()
{
#if defined(BOTAN_TARGET_OS_TYPE_IS_UNIX)
return ::getpid();
@@ -43,14 +41,16 @@ uint32_t get_process_id()
#endif
}
-uint64_t get_processor_timestamp()
+uint64_t OS::get_processor_timestamp()
{
#if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER)
LARGE_INTEGER tv;
::QueryPerformanceCounter(&tv);
return tv.QuadPart;
-#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+#elif defined(BOTAN_USE_GCC_INLINE_ASM)
+
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
if(CPUID::has_rdtsc()) // not available on all x86 CPUs
{
uint32_t rtc_low = 0, rtc_high = 0;
@@ -58,7 +58,7 @@ uint64_t get_processor_timestamp()
return (static_cast<uint64_t>(rtc_high) << 32) | rtc_low;
}
-#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_PPC64)
+#elif defined(BOTAN_TARGET_ARCH_IS_PPC64)
uint32_t rtc_low = 0, rtc_high = 0;
asm volatile("mftbu %0; mftb %1" : "=r" (rtc_high), "=r" (rtc_low));
@@ -71,33 +71,46 @@ uint64_t get_processor_timestamp()
return (static_cast<uint64_t>(rtc_high) << 32) | rtc_low;
}
-#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_ALPHA)
+#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA)
uint64_t rtc = 0;
asm volatile("rpcc %0" : "=r" (rtc));
return rtc;
// OpenBSD does not trap access to the %tick register
-#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD)
+#elif defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD)
uint64_t rtc = 0;
asm volatile("rd %%tick, %0" : "=r" (rtc));
return rtc;
-#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_IA64)
+#elif defined(BOTAN_TARGET_ARCH_IS_IA64)
uint64_t rtc = 0;
asm volatile("mov %0=ar.itc" : "=r" (rtc));
return rtc;
-#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_S390X)
+#elif defined(BOTAN_TARGET_ARCH_IS_S390X)
uint64_t rtc = 0;
asm volatile("stck 0(%0)" : : "a" (&rtc) : "memory", "cc");
return rtc;
-#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_HPPA)
+#elif defined(BOTAN_TARGET_ARCH_IS_HPPA)
uint64_t rtc = 0;
asm volatile("mfctl 16,%0" : "=r" (rtc)); // 64-bit only?
return rtc;
+
+#else
+ //#warning "OS::get_processor_timestamp not implemented"
+#endif
+
#endif
+ return 0;
+ }
+
+uint64_t OS::get_high_resolution_clock()
+ {
+ if(uint64_t cpu_clock = OS::get_processor_timestamp())
+ return cpu_clock;
+
/*
If we got here either we either don't have an asm instruction
above, or (for x86) RDTSC is not available at runtime. Try some
@@ -141,7 +154,7 @@ uint64_t get_processor_timestamp()
return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
}
-uint64_t get_system_timestamp_ns()
+uint64_t OS::get_system_timestamp_ns()
{
#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME)
struct timespec ts;
@@ -155,7 +168,7 @@ uint64_t get_system_timestamp_ns()
return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
}
-size_t get_memory_locking_limit()
+size_t OS::get_memory_locking_limit()
{
#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
/*
@@ -241,7 +254,7 @@ size_t get_memory_locking_limit()
return 0;
}
-void* allocate_locked_pages(size_t length)
+void* OS::allocate_locked_pages(size_t length)
{
#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK)
@@ -298,7 +311,7 @@ void* allocate_locked_pages(size_t length)
#endif
}
-void free_locked_pages(void* ptr, size_t length)
+void OS::free_locked_pages(void* ptr, size_t length)
{
if(ptr == nullptr || length == 0)
return;
@@ -330,8 +343,14 @@ void botan_sigill_handler(int)
}
#endif
-int run_cpu_instruction_probe(std::function<int ()> probe_fn)
+int OS::run_cpu_instruction_probe(std::function<int ()> probe_fn)
{
+ /*
+ There doesn't seem to be any way for probe_result to not be initialized
+ by some code path below, but this initializer is left as error just in case.
+ */
+ int probe_result = -3;
+
#if defined(BOTAN_TARGET_OS_TYPE_IS_UNIX)
struct sigaction old_sigaction;
struct sigaction sigaction;
@@ -345,12 +364,6 @@ int run_cpu_instruction_probe(std::function<int ()> probe_fn)
if(rc != 0)
throw Exception("run_cpu_instruction_probe sigaction failed");
- /*
- There doesn't seem to be any way for probe_result to not be initialized
- by some code path below, but this initializer is left as error just in case.
- */
- int probe_result = -3;
-
try
{
rc = ::sigsetjmp(g_sigill_jmp_buf, /*save sigs*/1);
@@ -373,18 +386,34 @@ int run_cpu_instruction_probe(std::function<int ()> probe_fn)
probe_result = -2;
}
+ // Restore old SIGILL handler, if any
rc = ::sigaction(SIGILL, &old_sigaction, nullptr);
if(rc != 0)
throw Exception("run_cpu_instruction_probe sigaction restore failed");
return probe_result;
-#else
- // TODO: Windows support
- return -9; // not supported
-#endif
- }
+#elif defined(BOTAN_TARGET_OS_IS_WINDOWS) && defined(BOTAN_TARGET_COMPILER_IS_MSVC)
-}
+ // Windows SEH
+ __try
+ {
+ try
+ {
+ return probe_fn();
+ }
+ catch(...)
+ {
+ probe_result = -2;
+ }
+ }
+ __except(::GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ probe_result = -1;
+ }
+
+#endif
+ }
}