diff --git a/opal/include/opal/sys/amd64/timer.h b/opal/include/opal/sys/amd64/timer.h index 33d64b70202..db7983ae0ab 100644 --- a/opal/include/opal/sys/amd64/timer.h +++ b/opal/include/opal/sys/amd64/timer.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * University Research and Technology @@ -9,6 +10,8 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2016 Los Alamos National Security, LLC. ALl rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -56,7 +59,24 @@ opal_sys_timer_get_cycles(void) return ((opal_timer_t)l) | (((opal_timer_t)h) << 32); } +static inline bool opal_sys_timer_is_monotonic (void) +{ + int32_t cpuid1, cpuid2, tmp; + const int32_t level = 0x80000007; + /* cpuid clobbers ebx but it must be restored for -fPIC so save + * then restore ebx */ + __asm__ volatile ("xchgl %%ebx, %2\n" + "cpuid\n" + "xchgl %%ebx, %2\n": + "=a" (cpuid1), "=d" (cpuid2), "=r" (tmp) : + "a" (level) : + "ecx"); + /* bit 8 of edx contains the invariant tsc flag */ + return !!(cpuid2 & (1 << 8)); +} + #define OPAL_HAVE_SYS_TIMER_GET_CYCLES 1 +#define OPAL_HAVE_SYS_TIMER_IS_MONOTONIC 1 #else diff --git a/opal/include/opal/sys/timer.h b/opal/include/opal/sys/timer.h index fe97aef3ef9..8b98335a200 100644 --- a/opal/include/opal/sys/timer.h +++ b/opal/include/opal/sys/timer.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * University Research and Technology @@ -9,6 +10,8 @@ * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. + * Copyright (c) 2016 Los Alamos National Security, LLC. All rights + * reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -108,6 +111,17 @@ typedef long opal_timer_t; #endif #endif +#ifndef OPAL_HAVE_SYS_TIMER_IS_MONOTONIC + +#define OPAL_HAVE_SYS_TIMER_IS_MONOTONIC 1 + +static inline bool opal_sys_timer_is_monotonic (void) +{ + return OPAL_TIMER_MONOTONIC; +} + +#endif + END_C_DECLS #endif /* OPAL_SYS_TIMER_H */ diff --git a/opal/mca/timer/linux/timer_linux_component.c b/opal/mca/timer/linux/timer_linux_component.c index 9ebc479bca0..2e9cf0c7afd 100644 --- a/opal/mca/timer/linux/timer_linux_component.c +++ b/opal/mca/timer/linux/timer_linux_component.c @@ -12,7 +12,7 @@ * All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. - * Copyright (c) 2015 Los Alamos National Security, LLC. All rights + * Copyright (c) 2015-2016 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2015 Cisco Systems, Inc. All rights reserved. * $COPYRIGHT$ @@ -153,8 +153,8 @@ int opal_timer_linux_open(void) { int ret = OPAL_SUCCESS; - if(mca_timer_base_monotonic) { -#if OPAL_HAVE_CLOCK_GETTIME + if (mca_timer_base_monotonic && !opal_sys_timer_is_monotonic ()) { +#if OPAL_HAVE_CLOCK_GETTIME && (0 == OPAL_TIMER_MONOTONIC) struct timespec res; if( 0 == clock_getres(CLOCK_MONOTONIC, &res)) { opal_timer_linux_freq = 1.e9; @@ -163,11 +163,9 @@ int opal_timer_linux_open(void) return ret; } #else -#if (0 == OPAL_TIMER_MONOTONIC) /* Monotonic time requested but cannot be found. Complain! */ - opal_show_help("help-opal-timer-linux.txt", "monotonic not supported", 1); -#endif /* (0 == OPAL_TIMER_MONOTONIC) */ -#endif + opal_show_help("help-opal-timer-linux.txt", "monotonic not supported", true); +#endif /* OPAL_HAVE_CLOCK_GETTIME && (0 == OPAL_TIMER_MONOTONIC) */ } ret = opal_timer_linux_find_freq(); opal_timer_base_get_cycles = opal_timer_base_get_cycles_sys_timer; @@ -178,22 +176,20 @@ int opal_timer_linux_open(void) #if OPAL_HAVE_CLOCK_GETTIME opal_timer_t opal_timer_base_get_usec_clock_gettime(void) { - struct timespec tp; + struct timespec tp = {.tv_sec = 0, .tv_nsec = 0}; - if( 0 == clock_gettime(CLOCK_MONOTONIC, &tp) ) { - return (tp.tv_sec * 1e6 + tp.tv_nsec/1000); - } - return 0; + (void) clock_gettime (CLOCK_MONOTONIC, &tp); + + return (tp.tv_sec * 1e6 + tp.tv_nsec/1000); } opal_timer_t opal_timer_base_get_cycles_clock_gettime(void) { - struct timespec tp; + struct timespec tp = {.tv_sec = 0, .tv_nsec = 0}; - if( 0 == clock_gettime(CLOCK_MONOTONIC, &tp) ) { - return (tp.tv_sec * 1e9 + tp.tv_nsec); - } - return 0; + (void) clock_gettime(CLOCK_MONOTONIC, &tp); + + return (tp.tv_sec * 1e9 + tp.tv_nsec); } #endif /* OPAL_HAVE_CLOCK_GETTIME */