• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_hrtime.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /**************************************************************************
00025 
00026   ink_hrtime.cc
00027 
00028   This file contains code supporting the Inktomi high-resolution timer.
00029 **************************************************************************/
00030 
00031 #include "ink_hrtime.h"
00032 #include "ink_assert.h"
00033 #include "ink_defs.h"
00034 
00035 #if defined(freebsd)
00036 #include <sys/types.h>
00037 #include <sys/param.h>
00038 #include <sys/sysctl.h>
00039 #endif
00040 #include <sys/time.h>
00041 
00042 char *
00043 int64_to_str(char *buf, unsigned int buf_size, int64_t val, unsigned int *total_chars, unsigned int req_width, char pad_char)
00044 {
00045   const unsigned int local_buf_size = 32;
00046   char local_buf[local_buf_size];
00047   bool using_local_buffer = false;
00048   bool negative = false;
00049   char *out_buf;
00050 
00051   if (buf_size < 22) {
00052     // int64_t may not fit in provided buffer, use the local one
00053     out_buf = &local_buf[local_buf_size - 1];
00054     using_local_buffer = true;
00055   } else {
00056     out_buf = &buf[buf_size - 1];
00057   }
00058 
00059   unsigned int num_chars = 1;   // includes eos
00060   *out_buf-- = 0;
00061 
00062   if (val < 0) {
00063     val = -val;
00064     negative = true;
00065   }
00066 
00067   if (val < 10) {
00068     *out_buf-- = '0' + (char) val;
00069     ++num_chars;
00070   } else {
00071     do {
00072       *out_buf-- = (char) (val % 10) + '0';
00073       val /= 10;
00074       ++num_chars;
00075     } while (val);
00076   }
00077 
00078   // pad with pad_char if needed
00079   //
00080   if (req_width) {
00081     // add minus sign if padding character is not 0
00082     if (negative && pad_char != '0') {
00083       *out_buf = '-';
00084       ++num_chars;
00085     } else {
00086       out_buf++;
00087     }
00088     if (req_width > buf_size)
00089       req_width = buf_size;
00090     unsigned int num_padding = 0;
00091     if (req_width > num_chars) {
00092       num_padding = req_width - num_chars;
00093       switch (num_padding) {
00094       case 3:
00095         *--out_buf = pad_char;
00096       case 2:
00097         *--out_buf = pad_char;
00098       case 1:
00099         *--out_buf = pad_char;
00100         break;
00101       default:
00102         for (unsigned int i = 0; i < num_padding; ++i, *--out_buf = pad_char);
00103       }
00104       num_chars += num_padding;
00105     }
00106     // add minus sign if padding character is 0
00107     if (negative && pad_char == '0') {
00108       if (num_padding) {
00109         *out_buf = '-';         // overwrite padding
00110       } else {
00111         *--out_buf = '-';
00112         ++num_chars;
00113       }
00114     }
00115   } else if (negative) {
00116     *out_buf = '-';
00117     ++num_chars;
00118   } else {
00119     out_buf++;
00120   }
00121 
00122   if (using_local_buffer) {
00123     if (num_chars <= buf_size) {
00124       memcpy(buf, out_buf, num_chars);
00125       out_buf = buf;
00126     } else {
00127       // data does not fit return NULL
00128       out_buf = NULL;
00129     }
00130   }
00131 
00132   if (total_chars)
00133     *total_chars = num_chars;
00134   return out_buf;
00135 }
00136 
00137 
00138 int
00139 squid_timestamp_to_buf(char *buf, unsigned int buf_size, long timestamp_sec, long timestamp_usec)
00140 {
00141   int res;
00142   const unsigned int tmp_buf_size = 32;
00143   char tmp_buf[tmp_buf_size];
00144 
00145   unsigned int num_chars_s;
00146   char *ts_s = int64_to_str(tmp_buf, tmp_buf_size - 4, timestamp_sec, &num_chars_s, 0, '0');
00147   ink_assert(ts_s);
00148 
00149   // convert milliseconds
00150   //
00151   tmp_buf[tmp_buf_size - 5] = '.';
00152   int ms = timestamp_usec / 1000;
00153   unsigned int num_chars_ms;
00154   char ATS_UNUSED *ts_ms = int64_to_str(&tmp_buf[tmp_buf_size - 4], 4, ms, &num_chars_ms, 4, '0');
00155   ink_assert(ts_ms && num_chars_ms == 4);
00156 
00157   unsigned int chars_to_write = num_chars_s + 3;        // no eos
00158 
00159   if (buf_size >= chars_to_write) {
00160     memcpy(buf, ts_s, chars_to_write);
00161     res = chars_to_write;
00162   } else {
00163     res = -((int) chars_to_write);
00164   }
00165 
00166   return res;
00167 }
00168 
00169 #ifdef USE_TIME_STAMP_COUNTER_HRTIME
00170 uint32_t
00171 init_hrtime_TCS()
00172 {
00173   int freqlen = sizeof(hrtime_freq);
00174   if (sysctlbyname("machdep.tsc_freq", &hrtime_freq, (size_t *) & freqlen, NULL, 0) < 0) {
00175     perror("sysctl: machdep.tsc_freq");
00176     exit(1);
00177   }
00178   hrtime_freq_float = (double) 1000000000 / (double) hrtime_freq;
00179   return hrtime_freq;
00180 }
00181 
00182 double hrtime_freq_float = 0.5; // 500 Mhz
00183 uint32_t hrtime_freq = init_hrtime_TCS();
00184 #endif
00185 
00186 #ifdef NEED_HRTIME_BASIS
00187 timespec timespec_basis;
00188 ink_hrtime hrtime_offset;
00189 ink_hrtime hrtime_basis = init_hrtime_basis();
00190 
00191 ink_hrtime
00192 init_hrtime_basis()
00193 {
00194   ink_hrtime t1, t2, b, now;
00195   timespec ts;
00196 #ifdef USE_TIME_STAMP_COUNTER_HRTIME
00197   init_hrtime_TCS();
00198 #endif
00199   do {
00200     t1 = ink_get_hrtime_internal();
00201 #if HAVE_CLOCK_GETTIME
00202     ink_assert(!clock_gettime(CLOCK_REALTIME, &timespec_basis));
00203 #else
00204     {
00205       struct timeval tnow;
00206       ink_assert(!gettimeofday(&tnow, NULL));
00207       timespec_basis.tv_sec = tnow.tv_sec;
00208       timespec_basis.tv_nsec = tnow.tv_usec * 1000;
00209     }
00210 #endif
00211     t2 = ink_get_hrtime_internal();
00212     // accuracy must be at least 100 microseconds
00213   } while (t2 - t1 > HRTIME_USECONDS(100));
00214   b = (t2 + t1) / 2;
00215   now = ink_hrtime_from_timespec(&timespec_basis);
00216   ts = ink_hrtime_to_timespec(now);
00217   ink_assert(ts.tv_sec == timespec_basis.tv_sec && ts.tv_nsec == timespec_basis.tv_nsec);
00218   hrtime_offset = now - b;
00219   hrtime_basis = b;
00220   return b;
00221 }
00222 #endif

Generated by  doxygen 1.7.1