Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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;
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
00079
00080 if (req_width) {
00081
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
00107 if (negative && pad_char == '0') {
00108 if (num_padding) {
00109 *out_buf = '-';
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
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
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;
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;
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, ×pec_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
00213 } while (t2 - t1 > HRTIME_USECONDS(100));
00214 b = (t2 + t1) / 2;
00215 now = ink_hrtime_from_timespec(×pec_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