• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "util/time_format.h"
17 #include <securec.h>
18 #include "dfx/log/ffrt_log_api.h"
19 
20 namespace {
21 #if defined(__aarch64__)
22 const uint64_t tsc_base = ffrt::Arm64CntCt();
23 const std::chrono::steady_clock::time_point steady_base = std::chrono::steady_clock::now();
24 const uint64_t freq = ffrt::Arm64CntFrq();
25 #endif
26 }
27 namespace ffrt {
ConvertTscToSteadyClockCount(uint64_t cntCt)28 uint64_t ConvertTscToSteadyClockCount(uint64_t cntCt)
29 {
30 #if defined(__aarch64__)
31     const uint64_t delta_tsc = cntCt - tsc_base;
32     constexpr int ratio = 1000 * 1000;
33 
34     const uint64_t delta_micro = (delta_tsc * ratio) / freq;
35 
36     return static_cast<uint64_t>(std::chrono::time_point_cast<std::chrono::microseconds>(
37         steady_base + std::chrono::microseconds(delta_micro)).time_since_epoch().count());
38 #else
39     return cntCt;
40 #endif
41 }
42 
ConvertCntvctToUs(uint64_t cntCt)43 uint64_t ConvertCntvctToUs(uint64_t cntCt)
44 {
45     // 将获取到的CPU cycle数转成微秒数
46 #if defined(__aarch64__)
47     uint64_t freq = Arm64CntFrq();
48     constexpr int ratio = 1000 * 1000;
49 
50     return static_cast<uint64_t>((cntCt * ratio) / freq);
51 #else
52     return cntCt;
53 #endif
54 }
55 
ConvertUsToCntvct(uint64_t time)56 uint64_t ConvertUsToCntvct(uint64_t time)
57 {
58     // 将微秒数转成CPU cycle数
59 #if defined(__aarch64__)
60     uint64_t freq = Arm64CntFrq();
61     constexpr int ratio = 1000 * 1000;
62 
63     return static_cast<uint64_t>((time * freq) / ratio);
64 #else
65     return time;
66 #endif
67 }
68 
TimeStampCntvct()69 uint64_t TimeStampCntvct()
70 {
71     // 在非arm环境下获取std的时间戳,单位微秒
72     return static_cast<uint64_t>(std::chrono::time_point_cast<std::chrono::microseconds>(
73         std::chrono::steady_clock::now()).time_since_epoch().count());
74 }
75 
FormatDateToString(uint64_t timeStamp)76 std::string FormatDateToString(uint64_t timeStamp)
77 {
78 #if defined(__aarch64__)
79     return FormatDateString4CntCt(timeStamp, MICROSECOND);
80 #else
81     return FormatDateString4SteadyClock(timeStamp, MICROSECOND);
82 #endif
83 }
84 
Arm64CntFrq(void)85 uint64_t Arm64CntFrq(void)
86 {
87     uint64_t freq = 1;
88 #if defined(__aarch64__)
89     asm volatile("mrs %0, cntfrq_el0" : "=r" (freq));
90 #endif
91     return freq;
92 }
93 
Arm64CntCt(void)94 uint64_t Arm64CntCt(void)
95 {
96     uint64_t tsc = 1;
97 #if defined(__aarch64__)
98     asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));
99 #endif
100     return tsc;
101 }
102 
FormatDateString4SystemClock(const std::chrono::system_clock::time_point & timePoint,TimeUnitT timeUnit)103 std::string FormatDateString4SystemClock(const std::chrono::system_clock::time_point& timePoint,
104     TimeUnitT timeUnit)
105 {
106     constexpr int maxMsLength = 3;
107     constexpr int msPerSecond = 1000;
108     constexpr int datetimeStringLength = 80;
109     constexpr int maxUsLength = 6;
110     constexpr int usPerSecond = 1000 * 1000;
111 
112     std::string remainder;
113     if (timeUnit == MICROSECOND) {
114         auto tp = std::chrono::time_point_cast<std::chrono::microseconds>(timePoint);
115         auto us = tp.time_since_epoch().count() % usPerSecond;
116         remainder = std::to_string(us);
117         if (remainder.length() < maxUsLength) {
118             remainder = std::string(maxUsLength - remainder.length(), '0') + remainder;
119         }
120     } else {
121         auto tp = std::chrono::time_point_cast<std::chrono::milliseconds>(timePoint);
122         auto ms = tp.time_since_epoch().count() % msPerSecond;
123         remainder = std::to_string(ms);
124         if (remainder.length() < maxMsLength) {
125             remainder = std::string(maxMsLength - remainder.length(), '0') + remainder;
126         }
127     }
128     auto tt = std::chrono::system_clock::to_time_t(timePoint);
129     struct tm curTime;
130     if (memset_s(&curTime, sizeof(curTime), 0, sizeof(curTime)) != EOK) {
131         FFRT_LOGE("Fail to memset");
132         return "";
133     }
134     localtime_r(&tt, &curTime);
135     char sysTime[datetimeStringLength];
136     std::strftime(sysTime, sizeof(char) * datetimeStringLength, "%Y-%m-%d %H:%M:%S.", &curTime);
137     return std::string(sysTime) + remainder;
138 }
139 
FormatDateString4SteadyClock(uint64_t steadyClockTimeStamp,TimeUnitT timeUnit)140 std::string FormatDateString4SteadyClock(uint64_t steadyClockTimeStamp, TimeUnitT timeUnit)
141 {
142     auto referenceTimeStamp = std::chrono::duration_cast<std::chrono::microseconds>(
143         std::chrono::steady_clock::now().time_since_epoch()).count();
144     auto referenceTp = std::chrono::system_clock::now();
145 
146     std::chrono::microseconds us(static_cast<int64_t>(steadyClockTimeStamp - referenceTimeStamp));
147     return FormatDateString4SystemClock(referenceTp + us, timeUnit);
148 }
149 
FormatDateString4CntCt(uint64_t cntCtTimeStamp,TimeUnitT timeUnit)150 std::string FormatDateString4CntCt(uint64_t cntCtTimeStamp, TimeUnitT timeUnit)
151 {
152     constexpr int ratio = 1000 * 1000;
153 
154     int64_t referenceFreq = static_cast<int64_t>(Arm64CntFrq());
155     if (referenceFreq == 0) {
156         return "";
157     }
158     uint64_t referenceCntCt = Arm64CntCt();
159     auto globalTp = std::chrono::system_clock::now();
160     std::chrono::microseconds us(static_cast<int64_t>(cntCtTimeStamp - referenceCntCt) * ratio / referenceFreq);
161     return FormatDateString4SystemClock(globalTp + us, timeUnit);
162 }
163 } // namespace ffrt
164