root/opal/mca/timer/linux/timer_linux_component.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_info
  2. opal_timer_linux_find_freq
  3. opal_timer_linux_open
  4. opal_timer_linux_get_usec_clock_gettime
  5. opal_timer_linux_get_cycles_clock_gettime
  6. opal_timer_linux_get_cycles_sys_timer
  7. opal_timer_linux_get_usec_sys_timer
  8. opal_timer_base_get_freq

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2016 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2015      Research Organization for Information Science
  14  *                         and Technology (RIST). All rights reserved.
  15  * Copyright (c) 2015-2017 Los Alamos National Security, LLC. All rights
  16  *                         reserved.
  17  * Copyright (c) 2015-2017 Cisco Systems, Inc.  All rights reserved
  18  * Copyright (c) 2016 Broadcom Limited. All rights reserved.
  19  * $COPYRIGHT$
  20  *
  21  * Additional copyrights may follow
  22  *
  23  * $HEADER$
  24  */
  25 
  26 #include "opal_config.h"
  27 
  28 #include <string.h>
  29 
  30 #include "opal/mca/timer/timer.h"
  31 #include "opal/mca/timer/base/base.h"
  32 #include "opal/mca/timer/linux/timer_linux.h"
  33 #include "opal/constants.h"
  34 #include "opal/util/show_help.h"
  35 
  36 static opal_timer_t opal_timer_linux_get_cycles_sys_timer(void);
  37 static opal_timer_t opal_timer_linux_get_usec_sys_timer(void);
  38 
  39 /**
  40  * Define some sane defaults until we call the _init function.
  41  */
  42 #if OPAL_HAVE_CLOCK_GETTIME
  43 static opal_timer_t opal_timer_linux_get_cycles_clock_gettime(void);
  44 static opal_timer_t opal_timer_linux_get_usec_clock_gettime(void);
  45 
  46 opal_timer_t (*opal_timer_base_get_cycles)(void) =
  47     opal_timer_linux_get_cycles_clock_gettime;
  48 opal_timer_t (*opal_timer_base_get_usec)(void) =
  49     opal_timer_linux_get_usec_clock_gettime;
  50 #else
  51 opal_timer_t (*opal_timer_base_get_cycles)(void) =
  52     opal_timer_linux_get_cycles_sys_timer;
  53 opal_timer_t (*opal_timer_base_get_usec)(void) =
  54     opal_timer_linux_get_usec_sys_timer;
  55 #endif  /* OPAL_HAVE_CLOCK_GETTIME */
  56 
  57 static opal_timer_t opal_timer_linux_freq = {0};
  58 
  59 static int opal_timer_linux_open(void);
  60 
  61 const opal_timer_base_component_2_0_0_t mca_timer_linux_component = {
  62     /* First, the mca_component_t struct containing meta information
  63        about the component itself */
  64     .timerc_version = {
  65         OPAL_TIMER_BASE_VERSION_2_0_0,
  66 
  67         /* Component name and version */
  68         .mca_component_name = "linux",
  69         MCA_BASE_MAKE_VERSION(component, OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION,
  70                               OPAL_RELEASE_VERSION),
  71 
  72         /* Component open and close functions */
  73         .mca_open_component = opal_timer_linux_open,
  74     },
  75     .timerc_data = {
  76         /* The component is checkpoint ready */
  77         MCA_BASE_METADATA_PARAM_CHECKPOINT
  78     },
  79 };
  80 
  81 static char *
  82 find_info(FILE* fp, char *str, char *buf, size_t buflen)
  83 {
  84     char *tmp;
  85 
  86     rewind(fp);
  87     while (NULL != fgets(buf, buflen, fp)) {
  88         if (strncmp(buf, str, strlen(str)) == 0) {
  89             /* we found the line.  Now eat everything up to,
  90                including, and one past the : */
  91             for (tmp = buf ; (*tmp != '\0') && (*tmp != ':') ; ++tmp) ;
  92             if (*tmp == '\0') {
  93                 continue;
  94             }
  95             for ( ++tmp ; *tmp == ' ' ; ++tmp);
  96             if ('\0' != *tmp) {
  97                 return tmp;
  98             }
  99         }
 100     }
 101 
 102     return NULL;
 103 }
 104 
 105 static int opal_timer_linux_find_freq(void)
 106 {
 107     FILE *fp;
 108     char *loc;
 109     float cpu_f;
 110     int ret;
 111     char buf[1024];
 112 
 113     fp = fopen("/proc/cpuinfo", "r");
 114     if (NULL == fp) {
 115         return OPAL_ERR_IN_ERRNO;
 116     }
 117 
 118     opal_timer_linux_freq = 0;
 119 
 120 #if OPAL_HAVE_SYS_TIMER_GET_FREQ
 121     opal_timer_linux_freq = opal_sys_timer_get_freq();
 122 #endif
 123 
 124     if (0 == opal_timer_linux_freq) {
 125         /* first, look for a timebase field.  probably only on PPC,
 126            but one never knows */
 127         loc = find_info(fp, "timebase", buf, 1024);
 128         if (NULL != loc) {
 129             int freq;
 130             ret = sscanf(loc, "%d", &freq);
 131             if (1 == ret) {
 132                 opal_timer_linux_freq = freq;
 133             }
 134         }
 135     }
 136 
 137 #if ((OPAL_ASSEMBLY_ARCH == OPAL_IA32) || (OPAL_ASSEMBLY_ARCH == OPAL_X86_64))
 138     if (0 == opal_timer_linux_freq && opal_sys_timer_is_monotonic()) {
 139         /* tsc is exposed through bogomips ~> loops_per_jiffy ~> tsc_khz */
 140         loc = find_info(fp, "bogomips", buf, 1024);
 141         if (NULL != loc) {
 142             ret = sscanf(loc, "%f", &cpu_f);
 143             if (1 == ret) {
 144                 /* number is in MHz * 2 and has 2 decimal digits
 145                    convert to Hz and make an integer */
 146                 opal_timer_linux_freq = (opal_timer_t) (cpu_f * 100.0f) * 5000;
 147             }
 148         }
 149     }
 150 #endif
 151 
 152     if (0 == opal_timer_linux_freq) {
 153         /* find the CPU speed - most timers are 1:1 with CPU speed */
 154         loc = find_info(fp, "cpu MHz", buf, 1024);
 155         if (NULL != loc) {
 156             ret = sscanf(loc, "%f", &cpu_f);
 157             if (1 == ret) {
 158                 /* numer is in MHz - convert to Hz and make an integer */
 159                 opal_timer_linux_freq = (opal_timer_t) (cpu_f * 1000000);
 160             }
 161         }
 162     }
 163 
 164     if (0 == opal_timer_linux_freq) {
 165         /* look for the sparc way of getting cpu frequency */
 166         loc = find_info(fp, "Cpu0ClkTck", buf, 1024);
 167         if (NULL != loc) {
 168             unsigned int freq;
 169             ret = sscanf(loc, "%x", &freq);
 170             if (1 == ret) {
 171                 opal_timer_linux_freq = freq;
 172             }
 173         }
 174     }
 175 
 176     fclose(fp);
 177 
 178     /* convert the timer frequency to MHz to avoid an extra operation when
 179      * converting from cycles to usec */
 180     opal_timer_linux_freq /= 1000000;
 181 
 182     return OPAL_SUCCESS;
 183 }
 184 
 185 int opal_timer_linux_open(void)
 186 {
 187     int ret = OPAL_SUCCESS;
 188 
 189     if (mca_timer_base_monotonic && !opal_sys_timer_is_monotonic ()) {
 190 #if OPAL_HAVE_CLOCK_GETTIME && (0 == OPAL_TIMER_MONOTONIC)
 191         struct timespec res;
 192         if( 0 == clock_getres(CLOCK_MONOTONIC, &res)) {
 193             opal_timer_linux_freq = 1.e3;
 194             opal_timer_base_get_cycles = opal_timer_linux_get_cycles_clock_gettime;
 195             opal_timer_base_get_usec = opal_timer_linux_get_usec_clock_gettime;
 196             return ret;
 197         }
 198 #else
 199         /* Monotonic time requested but cannot be found. Complain! */
 200         opal_show_help("help-opal-timer-linux.txt", "monotonic not supported", true);
 201 #endif  /* OPAL_HAVE_CLOCK_GETTIME && (0 == OPAL_TIMER_MONOTONIC) */
 202     }
 203     ret = opal_timer_linux_find_freq();
 204     opal_timer_base_get_cycles = opal_timer_linux_get_cycles_sys_timer;
 205     opal_timer_base_get_usec = opal_timer_linux_get_usec_sys_timer;
 206     return ret;
 207 }
 208 
 209 #if OPAL_HAVE_CLOCK_GETTIME
 210 opal_timer_t opal_timer_linux_get_usec_clock_gettime(void)
 211 {
 212     struct timespec tp = {.tv_sec = 0, .tv_nsec = 0};
 213 
 214     (void) clock_gettime (CLOCK_MONOTONIC, &tp);
 215 
 216     return (tp.tv_sec * 1e6 + tp.tv_nsec/1000);
 217 }
 218 
 219 opal_timer_t opal_timer_linux_get_cycles_clock_gettime(void)
 220 {
 221     struct timespec tp = {.tv_sec = 0, .tv_nsec = 0};
 222 
 223     (void) clock_gettime(CLOCK_MONOTONIC, &tp);
 224 
 225     return (tp.tv_sec * 1e9 + tp.tv_nsec);
 226 }
 227 #endif  /* OPAL_HAVE_CLOCK_GETTIME */
 228 
 229 opal_timer_t opal_timer_linux_get_cycles_sys_timer(void)
 230 {
 231 #if OPAL_HAVE_SYS_TIMER_GET_CYCLES
 232     return opal_sys_timer_get_cycles();
 233 #else
 234     return 0;
 235 #endif
 236 }
 237 
 238 
 239 opal_timer_t opal_timer_linux_get_usec_sys_timer(void)
 240 {
 241 #if OPAL_HAVE_SYS_TIMER_GET_CYCLES
 242     /* freq is in MHz, so this gives usec */
 243     return opal_sys_timer_get_cycles()  / opal_timer_linux_freq;
 244 #else
 245     return 0;
 246 #endif
 247 }
 248 
 249 opal_timer_t opal_timer_base_get_freq(void)
 250 {
 251     return opal_timer_linux_freq * 1000000;
 252 }

/* [<][>][^][v][top][bottom][index][help] */