Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
B
brpc
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
brpc
Commits
94451c0e
Commit
94451c0e
authored
Sep 13, 2018
by
Ruan Kunliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix read_invariant_cpu_frequency
parent
24779b40
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
107 additions
and
22 deletions
+107
-22
time.cpp
src/butil/time.cpp
+100
-17
time.h
src/butil/time.h
+7
-5
No files found.
src/butil/time.cpp
View file @
94451c0e
...
...
@@ -25,6 +25,7 @@
#endif
#include <string.h> // memmem
#undef _GNU_SOURCE
#include <ctype.h>
#include "butil/time.h"
...
...
@@ -81,8 +82,7 @@ int64_t monotonic_time_ns() {
namespace
detail
{
// read_cpu_frequency() is modified from source code of glibc.
int64_t
read_cpu_frequency
(
bool
*
invariant_tsc
)
{
static
int64_t
read_cpu_current_frequency
(
char
*
buf
,
ssize_t
n
)
{
/* We read the information from the /proc filesystem. It contains at
least one line like
cpu MHz : 497.840237
...
...
@@ -90,17 +90,8 @@ int64_t read_cpu_frequency(bool* invariant_tsc) {
cpu MHz : 497.841
We search for this line and convert the number in an integer. */
const
int
fd
=
open
(
"/proc/cpuinfo"
,
O_RDONLY
);
if
(
fd
<
0
)
{
return
0
;
}
int64_t
result
=
0
;
char
buf
[
4096
];
// should be enough
const
ssize_t
n
=
read
(
fd
,
buf
,
sizeof
(
buf
));
if
(
n
>
0
)
{
char
*
mhz
=
static_cast
<
char
*>
(
memmem
(
buf
,
n
,
"cpu MHz"
,
7
));
if
(
mhz
!=
NULL
)
{
char
*
endp
=
buf
+
n
;
int
seen_decpoint
=
0
;
...
...
@@ -127,17 +118,109 @@ int64_t read_cpu_frequency(bool* invariant_tsc) {
result
*=
10
;
}
}
return
result
;
}
if
(
invariant_tsc
)
{
char
*
flags_pos
=
static_cast
<
char
*>
(
memmem
(
buf
,
n
,
"flags"
,
5
));
*
invariant_tsc
=
(
flags_pos
&&
memmem
(
flags_pos
,
buf
+
n
-
flags_pos
,
"constant_tsc"
,
12
)
&&
memmem
(
flags_pos
,
buf
+
n
-
flags_pos
,
"nonstop_tsc"
,
11
));
static
int64_t
read_cpu_frequency_from_brand_string
(
char
*
buf
,
ssize_t
n
)
{
/* We read the information from the /proc filesystem. It may contains at
least one line like
model name : Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz
We search for this line and convert the number in an integer. */
char
*
brand
=
static_cast
<
char
*>
(
memmem
(
buf
,
n
,
"model name"
,
10
));
if
(
brand
==
NULL
)
{
return
0
;
}
char
*
end
=
buf
+
n
;
char
*
num_str
=
brand
+
10
;
while
(
num_str
!=
end
&&
*
num_str
++
!=
'@'
);
while
(
num_str
!=
end
&&
!
isdigit
(
*
num_str
))
{
num_str
++
;
}
//expect x.xxGhz
//FSB may be 0.10GHz or 0.133...GHz
if
(
end
-
num_str
<
7
||
num_str
[
1
]
!=
'.'
||
!
isdigit
(
num_str
[
2
])
||
!
isdigit
(
num_str
[
3
])
||
num_str
[
4
]
!=
'G'
)
{
return
0
;
}
int64_t
result
=
(
num_str
[
0
]
-
'0'
)
*
10
+
(
num_str
[
2
]
-
'0'
);
int64_t
last
=
num_str
[
3
]
-
'0'
;
if
(
last
==
7
)
{
last
=
6
;
}
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
result
=
result
*
10
+
last
;
}
return
result
;
}
#if defined(__x86_64__) || defined(__i386__)
#if defined(__pic__) && defined(__i386__)
static
void
__cpuid
(
uint32_t
reg
[
4
],
uint32_t
code
)
{
__asm__
volatile
(
"mov %%ebx, %%edi
\n
"
"cpuid
\n
"
"xchg %%edi, %%ebx
\n
"
:
"=a"
(
reg
[
0
]),
"=D"
(
reg
[
1
]),
"=c"
(
reg
[
2
]),
"=d"
(
reg
[
3
])
:
"a"
(
code
)
);
}
#else
static
void
__cpuid
(
uint32_t
reg
[
4
],
uint32_t
code
)
{
__asm__
volatile
(
"cpuid
\n\t
"
:
"=a"
(
reg
[
0
]),
"=b"
(
reg
[
1
]),
"=c"
(
reg
[
2
]),
"=d"
(
reg
[
3
])
:
"a"
(
code
)
);
}
#endif
#endif
static
int64_t
read_cpu_frequency_by_cpuid
()
{
int64_t
result
=
0
;
#if defined(__x86_64__) || defined(__i386__)
uint32_t
reg
[
4
];
__cpuid
(
reg
,
0
);
if
(
reg
[
0
]
>=
0x16
&&
reg
[
1
]
==
0x756e6547
&&
reg
[
2
]
==
0x6c65746e
&&
reg
[
3
]
==
0x49656e69
)
{
//Intel CPU only
__cpuid
(
reg
,
0x16
);
return
static_cast
<
uint64_t
>
(
reg
[
0
])
*
1000000UL
;
}
#endif
return
result
;
}
// read_cpu_frequency() is modified from source code of glibc.
int64_t
read_cpu_frequency
(
bool
*
invariant_tsc
)
{
const
int
fd
=
open
(
"/proc/cpuinfo"
,
O_RDONLY
);
if
(
fd
<
0
)
{
return
0
;
}
char
buf
[
4096
];
// should be enough
const
ssize_t
n
=
read
(
fd
,
buf
,
sizeof
(
buf
));
close
(
fd
);
if
(
n
<=
0
)
{
return
0
;
}
if
(
invariant_tsc
)
{
char
*
flags_pos
=
static_cast
<
char
*>
(
memmem
(
buf
,
n
,
"flags"
,
5
));
if
(
flags_pos
&&
memmem
(
flags_pos
,
buf
+
n
-
flags_pos
,
"constant_tsc"
,
12
)
&&
memmem
(
flags_pos
,
buf
+
n
-
flags_pos
,
"nonstop_tsc"
,
11
))
{
int64_t
result
=
read_cpu_frequency_by_cpuid
();
if
(
result
<=
0
)
{
result
=
read_cpu_frequency_from_brand_string
(
buf
,
n
);
}
if
(
result
>
0
)
{
*
invariant_tsc
=
true
;
return
result
;
}
}
//current frequency is usually not invariant
*
invariant_tsc
=
false
;
}
return
read_cpu_current_frequency
(
buf
,
n
);
}
// Return value must be >= 0
...
...
src/butil/time.h
View file @
94451c0e
...
...
@@ -236,13 +236,15 @@ extern int64_t invariant_cpu_freq;
// note: Inlining shortens time cost per-call for 15ns in a loop of many
// calls to this function.
inline
int64_t
cpuwide_time_ns
()
{
if
(
detail
::
invariant_cpu_freq
>
0
)
{
int64_t
cpu_freq
=
detail
::
invariant_cpu_freq
;
if
(
cpu_freq
>
0
)
{
const
uint64_t
tsc
=
detail
::
clock_cycles
();
const
uint64_t
sec
=
tsc
/
detail
::
invariant_cpu_freq
;
//Try to avoid overflow
const
uint64_t
sec
=
tsc
/
cpu_freq
;
const
uint64_t
remain
=
tsc
%
cpu_freq
;
// TODO: should be OK until CPU's frequency exceeds 16GHz.
return
(
tsc
-
sec
*
detail
::
invariant_cpu_freq
)
*
1000000000L
/
detail
::
invariant_cpu_freq
+
sec
*
1000000000L
;
}
else
if
(
!
detail
::
invariant_cpu_freq
)
{
return
remain
*
1000000000L
/
cpu_freq
+
sec
*
1000000000L
;
}
else
if
(
!
cpu_freq
)
{
// Lack of necessary features, return system-wide monotonic time instead.
return
monotonic_time_ns
();
}
else
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment