LCOV - code coverage report
Current view: top level - aicpu_schedule/common - aicpusd_util.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 86.6 % 202 175
Test Date: 2026-07-28 10:54:05 Functions: 100.0 % 25 25

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #ifndef COMMON_AICPUSD_UTIL_H
      12              : #define COMMON_AICPUSD_UTIL_H
      13              : 
      14              : #include <atomic>
      15              : #include <functional>
      16              : #include <cstring>
      17              : #include <regex.h>
      18              : #include <csignal>
      19              : #include <unistd.h>
      20              : #include <sys/time.h>
      21              : #include <sys/wait.h>
      22              : #include "metadef_types.h"
      23              : #include "aicpu_context.h"
      24              : #include "aicpusd_feature_ctrl.h"
      25              : #include "aicpusd_status.h"
      26              : #include "aicpu_event_struct.h"
      27              : #include "profiling_adp.h"
      28              : #include "securec.h"
      29              : 
      30              : namespace AicpuSchedule {
      31              : 
      32              : constexpr int32_t MAX_ENV_CHAR_NUM = 1024;
      33              : const std::string ENV_NAME_HOME = "HOME";
      34              : const std::string ENV_NAME_BLOCK_CFG_PATH = "BLOCK_CFG_PATH";
      35              : const std::string ENV_NAME_DATAMASTER_RUN_MODE = "DATAMASTER_RUN_MODE";
      36              : const std::string ENV_NAME_AICPU_MODEL_TIMEOUT = "AICPU_MODEL_TIMEOUT";
      37              : const std::string ENV_NAME_PROCMGR_AICPU_CPUSET = "PROCMGR_AICPU_CPUSET";
      38              : const std::string ENV_NAME_LD_LIBRARY_PATH = "LD_LIBRARY_PATH";
      39              : const std::string ENV_NAME_REG_ASCEND_MONITOR = "REGISTER_TO_ASCENDMONITOR";
      40              : const std::string ENV_NAME_CUST_SO_PATH = "ASCEND_CUST_AICPU_KERNEL_CACHE_PATH";
      41              : class ScopeGuard {
      42              : public:
      43           79 :     explicit ScopeGuard(const std::function<void()> exitScope)
      44           79 :         : exitScope_(exitScope)
      45           79 :     {}
      46              : 
      47           79 :     ~ScopeGuard()
      48              :     {
      49              :         try {
      50           79 :             exitScope_();
      51            0 :         } catch (std::exception &funcException) {
      52            0 :             aicpusd_err("ScopeGuard Destruct Failed, %s", funcException.what());
      53            0 :         }
      54           79 :     }
      55              : 
      56              : private:
      57              :     ScopeGuard(ScopeGuard const&) = delete;
      58              :     ScopeGuard& operator=(ScopeGuard const&) = delete;
      59              :     ScopeGuard(ScopeGuard&&) = delete;
      60              :     ScopeGuard& operator=(ScopeGuard&&) = delete;
      61              : 
      62              :     std::function<void()> exitScope_;
      63              : };
      64              : 
      65          249 : inline uint64_t TickInterval2Microsecond(const uint64_t tickStart,
      66              :                                          const uint64_t tickEnd,
      67              :                                          const uint64_t tickFreq)
      68              : {
      69          249 :     if ((tickFreq == 0ULL) || (tickEnd <= tickStart)) {
      70            3 :         return 0UL;
      71              :     }
      72              :     // tickFreq is record by second, to microsecond need multiply 1000000
      73          246 :     return ((tickEnd - tickStart) * 1000000U) / tickFreq;
      74              : }
      75              : typedef struct {
      76              :     uint64_t taskId;
      77              :     uint64_t streamId;
      78              :     uint32_t threadIndex;
      79              :     uint32_t deviceId;
      80              : } ProfIdentity;
      81              : 
      82              : class AicpuUtil {
      83              : public:
      84              :     /**
      85              :      * @ingroup AicpusdUtil
      86              :      * @brief it is used to uniformly normalized error code.
      87              :      * @param [in] errCode: original error code.
      88              :      * @return uniformly normalized error code
      89              :      */
      90          130 :     static int32_t TransformInnerErrCode(const int32_t errCode)
      91              :     {
      92          130 :         return ((errCode > AICPU_SCHEDULE_ERROR_RESERVED) ||
      93          260 :                 (errCode < AICPU_SCHEDULE_OK)) ? AICPU_SCHEDULE_ERROR_INNER_ERROR : errCode;
      94              :     }
      95              : 
      96          127 :     static void SetProfData(const std::shared_ptr<aicpu::ProfMessage> &profMsg,
      97              :                             const aicpu::aicpuProfContext_t &aicpuProfCtx,
      98              :                             const ProfIdentity &profIdentity)
      99              :     {
     100          127 :         if (profMsg != nullptr) {
     101              :             // Phase of determining whether the operator is an asynchronous operator
     102          127 :             std::string phaseOneValue;
     103          127 :             bool isPhaseOne = false;
     104          127 :             const auto ret = aicpu::GetThreadLocalCtx(aicpu::CONTEXT_KEY_PHASE_ONE_FLAG, phaseOneValue);
     105          126 :             if ((ret == aicpu::AICPU_ERROR_NONE) && (phaseOneValue == "True")) {
     106            2 :                 isPhaseOne = true;
     107              :             }
     108              :             // The profile is not written in the first phase.
     109          126 :             if (!isPhaseOne) {
     110          124 :                 const uint64_t tickAfterRun = aicpu::GetSystemTick();
     111          125 :                 const uint64_t tickFreq = aicpu::GetSystemTickFreq();
     112          125 :                 const uint64_t dispatchTime = TickInterval2Microsecond(aicpuProfCtx.drvSubmitTick,
     113          125 :                                                                        aicpuProfCtx.tickBeforeRun,
     114              :                                                                        tickFreq);
     115          125 :                 const uint64_t totalTime = TickInterval2Microsecond(aicpuProfCtx.drvSubmitTick, tickAfterRun, tickFreq);
     116              :                 (void)profMsg->SetAicpuMagicNumber(static_cast<uint16_t>(MSPROF_DATA_HEAD_MAGIC_NUM))
     117              :                     ->SetAicpuDataTag(static_cast<uint16_t>(MSPROF_AICPU_DATA_TAG))
     118          124 :                     ->SetStreamId(static_cast<uint16_t>(profIdentity.streamId))
     119          248 :                     ->SetTaskId(static_cast<uint16_t>(profIdentity.taskId))->SetThreadId(profIdentity.threadIndex)
     120          124 :                     ->SetDeviceId(profIdentity.deviceId)
     121          248 :                     ->SetKernelType(aicpuProfCtx.kernelType)->SetSubmitTick(aicpuProfCtx.drvSubmitTick)
     122          248 :                     ->SetScheduleTick(aicpuProfCtx.drvSchedTick)->SetTickBeforeRun(aicpuProfCtx.tickBeforeRun)
     123              :                     ->SetTickAfterRun(tickAfterRun)->SetDispatchTime(static_cast<uint32_t>(dispatchTime))
     124          125 :                     ->SetTotalTime(static_cast<uint32_t>(totalTime))->SetVersion(aicpu::AICPU_PROF_VERSION);
     125              :             }
     126          126 :             (void)aicpu::SetProfHandle(nullptr);
     127          127 :             (void)aicpu::SetThreadLocalCtx(aicpu::CONTEXT_KEY_PHASE_ONE_FLAG, "False");
     128          128 :         }
     129          129 :     }
     130              : 
     131           15 :     static int32_t NumElements(const int64_t * const shape, const int64_t dimSize, int64_t &elementNum)
     132              :     {
     133           15 :         if (shape == nullptr) {
     134            2 :             aicpusd_err("Shape is nullptr.");
     135            2 :             return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     136              :         }
     137              : 
     138           13 :         int64_t num = 1;
     139           22 :         for (int64_t i = 0; i < dimSize; i++) {
     140           11 :             const int64_t dim = shape[i];
     141           11 :             if (dim < 0) {
     142            2 :                 aicpusd_err("Shape[%lld] value[%lld] is invalid, must be >= 0.", i, dim);
     143            2 :                 return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     144              :             }
     145            9 :             num = (num * dim);
     146            9 :             if (num < 0) {
     147            0 :                 aicpusd_err("Shape total element num is invalid, must be < INT64_MAX.");
     148            0 :                 return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     149              :             }
     150              :         }
     151           11 :         elementNum = num;
     152           11 :         return AICPU_SCHEDULE_OK;
     153              :     }
     154              : 
     155           13 :     static int32_t CalcDataSizeByShape(const int64_t * const shape, const int64_t dimSize,
     156              :                                        const int64_t dtype, int64_t &dataSize)
     157              :     {
     158           13 :         int64_t elementNum = 0;
     159           13 :         const int32_t ret = NumElements(shape, dimSize, elementNum);
     160           13 :         if (ret != AICPU_SCHEDULE_OK) {
     161            2 :             return ret;
     162              :         }
     163              : 
     164           11 :         const int32_t elementSize = ge::GetSizeByDataType(static_cast<ge::DataType>(dtype));
     165           11 :         if (elementSize < 0) {
     166            1 :             aicpusd_err("CalcDataSizeByShape failed, elementSize[%d] must be >= 0.", elementSize);
     167            1 :             return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
     168              :         }
     169              : 
     170           10 :         dataSize = elementNum * static_cast<int64_t>(elementSize);
     171           10 :         return AICPU_SCHEDULE_OK;
     172              :     }
     173              : 
     174              :     /**
     175              :      * @ingroup AicpuUtil
     176              :      * @brief it is used to check exception by read FPSR Register.
     177              :      * @param [out] result : exception type.
     178              :      * @return has any exception, true if has
     179              :      */
     180              :     static bool CheckOverflow(int32_t &result)
     181              :     {
     182              :         (void)result;
     183              : #if (defined __ARM_ARCH) || (defined PLATFORM_AARCH64)
     184              :         int64_t regContent;
     185              :         __asm volatile(
     186              :           "MRS %0, FPSR"
     187              :           : "=r" (regContent)
     188              :           :
     189              :           : "memory"
     190              :         );
     191              :         aicpusd_info("Read FPSR:[%d].", regContent);
     192              :         if (regContent & (1UL << 3UL)) { // UFC(3)
     193              :             result = AICPU_SCHEDULE_ERROR_UNDERFLOW;
     194              :             return true;
     195              :         } else if (regContent & (1UL << 2UL)) { // OFC(2)
     196              :             result = AICPU_SCHEDULE_ERROR_OVERFLOW;
     197              :             return true;
     198              :         } else if (regContent & (1UL << 1UL)) { // DZC(1)
     199              :             result = AICPU_SCHEDULE_ERROR_DIVISIONZERO;
     200              :             return true;
     201              :         }
     202              : #endif
     203              :         return false;
     204              :     }
     205              : 
     206              :     /**
     207              :      * @ingroup AicpuUtil
     208              :      * @brief it is used to reset FPSR Register.
     209              :      */
     210              :     static void ResetFpsr()
     211              :     {
     212              : #if (defined __ARM_ARCH) || (defined PLATFORM_AARCH64)
     213              :         aicpusd_info("Reset FPSR.");
     214              :         __asm volatile(
     215              :               "BIC x0, x0, #0xffffffff \n\t"
     216              :               "MSR FPSR, x0":::"x0"
     217              :         );
     218              : #endif
     219              :     }
     220              : 
     221              :     /**
     222              :      * @ingroup AicpuUtil
     223              :      * @brief Get env value by name
     224              :      * @param [in] env : env name
     225              :      * @param [in] val : env value
     226              :      * @return bool: true, if env val is not nullptr; otherwise, false
     227              :      */
     228          229 :     __attribute__((visibility("default"))) static bool GetEnvVal(const std::string &env, std::string &val)
     229              :     {
     230          229 :         if (env.empty()) {
     231            0 :             return false;
     232              :         }
     233              : 
     234          229 :         const char *const tmpVal = std::getenv(env.c_str());
     235          229 :         if ((tmpVal == nullptr) || (strnlen(tmpVal, MAX_ENV_CHAR_NUM) >= MAX_ENV_CHAR_NUM)) {
     236          131 :             val = "";
     237          131 :             return false;
     238              :         }
     239              : 
     240           98 :         val = tmpVal;
     241           98 :         return true;
     242              :     }
     243              : 
     244              :     /**
     245              :      * @ingroup AicpuUtil
     246              :      * @brief Is env value is same as expected value
     247              :      * @param [in] env : env name
     248              :      * @param [in] expectVal : expected env value
     249              :      * @return bool: true, if env val is same as expected value; otherwise, false
     250              :      */
     251           99 :     __attribute__((visibility("default"))) static bool IsEnvValEqual(const std::string &env,
     252              :                                                                      const std::string &expectVal)
     253              :     {
     254           99 :         std::string getedEnvVal;
     255           99 :         const bool ret = GetEnvVal(env, getedEnvVal);
     256           99 :         if (!ret) {
     257           70 :             return false;
     258              :         }
     259              : 
     260           29 :         return (getedEnvVal == expectVal) ? true : false;
     261           99 :     }
     262              : 
     263            8 :     static inline bool IsUint64MulOverflow(const uint64_t num1, const uint64_t num2)
     264              :     {
     265            8 :         if ((num1 == 0UL) || (num2 == 0UL)) {
     266            1 :             return false;
     267              :         }
     268              : 
     269            7 :         if ((UINT64_MAX / num1) < num2) {
     270            2 :             return true;
     271              :         }
     272              : 
     273            5 :         return false;
     274              :     }
     275              : 
     276          196 :     static bool TransStrToInt(const std::string &para, int32_t &value)
     277              :     {
     278              :         try {
     279          196 :             value = std::stoi(para);
     280            9 :         } catch (...) {
     281            9 :             return false;
     282            9 :         }
     283              : 
     284          187 :         return true;
     285              :     }
     286              : 
     287           42 :     static bool TransStrToUint(const std::string &para, uint32_t &value)
     288              :     {
     289              :         try {
     290           42 :             value = std::stoul(para);
     291            2 :         } catch (...) {
     292            2 :             return false;
     293            2 :         }
     294              : 
     295           40 :         return true;
     296              :     }
     297              : 
     298            3 :     static bool TransStrToull(const std::string &para, uint64_t &value)
     299              :     {
     300              :         try {
     301            3 :             value = std::stoull(para);
     302            1 :         } catch (...) {
     303            1 :             return false;
     304            1 :         }
     305              : 
     306            2 :         return true;
     307              :     }
     308              : 
     309              :     /**
     310              :      * @ingroup AicpuUtil
     311              :      * @brief judge the string matching pattern
     312              :      * @param [in] str : file name
     313              :      * @param [in] mode : pattern
     314              :      * @return check code
     315              :      */
     316            2 :     static bool ValidateStr(const std::string &str, const std::string &mode)
     317              :     {
     318              :         regex_t reg;
     319            2 :         int32_t ret = regcomp(&reg, mode.c_str(), REG_EXTENDED | REG_NOSUB);
     320            2 :         if (ret != 0) {
     321            1 :             return false;
     322              :         }
     323            1 :         ret = regexec(&reg, str.c_str(), static_cast<size_t>(0), nullptr, 0);
     324            1 :         if (ret != 0) {
     325            1 :             regfree(&reg);
     326            1 :             return false;
     327              :         }
     328              : 
     329            0 :         regfree(&reg);
     330            0 :         return true;
     331              :     }
     332              : 
     333            3 :     static int32_t ExecuteCmd(const std::string &cmd)
     334              :     {
     335              :         /**
     336              :          * system() may fail due to  "No child processes".
     337              :          * if SIGCHLD is set to SIG_IGN, waitpid() may report ECHILD error because it cannot find the child process.
     338              :          * The reason is that the system() relies on a feature of the system, that is,
     339              :          * when the kernel initializes the process, the processing mode of SIGCHLD signal is SIG_IGN.
     340              :          */
     341            3 :         if (cmd.empty()) {
     342            1 :             return -1;
     343              :         }
     344              : 
     345            2 :         sighandler_t const oldHandler = signal(SIGCHLD, SIG_DFL);
     346            2 :         int32_t status = 0;
     347            2 :         int32_t pid = 0;
     348            2 :         if ((pid = vfork()) < 0) {
     349            1 :             status = -1;
     350            2 :         } else if (pid == 0) {
     351            1 :             (void)execl("/bin/sh", "sh", "-c", cmd.c_str(), nullptr);
     352            0 :             constexpr int32_t executeCmdErr = 127; // 与system实现保持一致
     353            0 :             _exit(executeCmdErr);
     354              :         } else {
     355            1 :             while (waitpid(pid, &status, 0) < 0) {
     356            0 :                 if (errno != EINTR) {
     357            0 :                     status = -1;
     358            0 :                     break;
     359              :                 }
     360              :             }
     361              :         }
     362            2 :         (void)signal(SIGCHLD, oldHandler);
     363            2 :         return status;
     364              :     }
     365              : 
     366              :     static std::string GetDTypeString(const ge::DataType curDtype);
     367              : 
     368            1 :     static void UpdateMinData(uint64_t &dstData, const uint64_t srcData)
     369              :     {
     370            1 :         if (((dstData > srcData) && (srcData != 0UL)) || (dstData == 0UL)) {
     371            1 :             dstData = srcData;
     372              :         }
     373            1 :     }
     374            1 :     static void UpdateMaxAndSubMaxData(uint64_t &maxData, uint64_t &subMaxData, const uint64_t srcData)
     375              :     {
     376            1 :         if (srcData > maxData) {
     377            0 :             subMaxData = maxData;
     378            0 :             maxData = srcData;
     379            1 :         } else if (srcData > subMaxData) {
     380            0 :             subMaxData = srcData;
     381              :         } else {
     382              :             // do nothing
     383              :         }
     384            1 :     }
     385              : 
     386            4 :     static bool BiggerMemCpy(void *dstAddr, const size_t dstLen, const void *srcAddr, const size_t srcLen)
     387              :     {
     388            4 :         if ((dstAddr == nullptr) || (srcAddr == nullptr)) {
     389            2 :             aicpusd_err("BiggerMemCpy input param is null.");
     390            2 :             return false;
     391              :         }
     392              : 
     393            2 :         if (dstLen < srcLen) {
     394            0 :             aicpusd_err("BiggerMemCpy dstLen is[%zu] less than srcLen[%zu].", dstLen, srcLen);
     395            0 :             return false;
     396              :         }
     397              : 
     398            2 :         size_t remainSize = srcLen;
     399            2 :         while (remainSize > SECUREC_MEM_MAX_LEN) {
     400            0 :             const auto eRet = memcpy_s(dstAddr, SECUREC_MEM_MAX_LEN, srcAddr, SECUREC_MEM_MAX_LEN);
     401            0 :             if (eRet != EOK) {
     402            0 :                 aicpusd_err("memcpy_s fail, ret is %d.", eRet);
     403            0 :                 return false;
     404              :             }
     405            0 :             remainSize -= SECUREC_MEM_MAX_LEN;
     406            0 :             srcAddr = ValueToPtr(PtrToValue(srcAddr) + SECUREC_MEM_MAX_LEN);
     407            0 :             dstAddr = ValueToPtr(PtrToValue(dstAddr) + SECUREC_MEM_MAX_LEN);
     408              :         }
     409            2 :         if (remainSize != 0U) {
     410            2 :             const auto eRet = memcpy_s(dstAddr, remainSize, srcAddr, remainSize);
     411            2 :             if (eRet != EOK) {
     412            0 :                 aicpusd_err("memcpy_s fail, size is %zu, ret is %d.", remainSize, eRet);
     413            0 :                 return false;
     414              :             }
     415              :         }
     416            2 :         return true;
     417              :     }
     418              : 
     419           31 :     static bool IsFpga()
     420              :     {
     421           35 :         static const bool IS_FPGA = AicpuUtil::IsEnvValEqual(ENV_NAME_DATAMASTER_RUN_MODE, "1");
     422           31 :         return IS_FPGA;
     423              :     }
     424              : 
     425              :     /**
     426              :      * @ingroup AicpuUtil
     427              :      * @brief it use to check timeout value send by ts.
     428              :      * @param [in] timeout : the timeout value.
     429              :      * @return bool: true if is valid value, otherwise false
     430              :      */
     431           12 :     static inline bool IsValidTimeoutVal(const uint32_t timeout)
     432              :     {
     433           12 :         if (timeout == 0U) {
     434            1 :             aicpusd_err("Invalid timeout value send by ts which cannot be zero.");
     435            1 :             return false;
     436              :         }
     437              : 
     438           11 :         const uint64_t sysTickFreq = aicpu::GetSystemTickFreq();
     439           11 :         if (sysTickFreq > (UINT64_MAX / static_cast<uint64_t>(timeout))) {
     440            2 :             aicpusd_err("Invalid timeout[%u] value send by ts resulting in unsigned long reverse. freq[%lu]",
     441              :                         timeout, sysTickFreq);
     442            2 :             return false;
     443              :         }
     444              : 
     445            9 :         return true;
     446              :     }
     447              : 
     448              :     /**
     449              :      * @ingroup AicpuUtil
     450              :      * @brief is use to check cust aicpu thread mode
     451              :      * @return AICPU_SCHEDULE_OK: success, other: error code
     452              :      */
     453            3 :     static inline int32_t CheckCustAicpuThreadMode()
     454              :     {
     455            3 :         uint32_t runMode = 0U;
     456            3 :         const aicpu::status_t status = aicpu::GetAicpuRunMode(runMode);
     457            3 :         if (status != aicpu::AICPU_ERROR_NONE) {
     458            1 :             aicpusd_err("Get current aicpu ctx failed.");
     459            1 :             return AICPU_SCHEDULE_ERROR_INNER_ERROR;
     460              :         }
     461              : 
     462            2 :         if (runMode != aicpu::AicpuRunMode::THREAD_MODE) {
     463            1 :             aicpusd_err("Cust aicpu process does not exist.");
     464            1 :             aicpusd_err("Only with thread mode, cust aicpu kernel can run in aicpu-sd.");
     465            1 :             return AICPU_SCHEDULE_ERROR_INNER_ERROR;
     466              :         }
     467              : 
     468            1 :         return AICPU_SCHEDULE_OK;
     469              :     }
     470              : 
     471              : private:
     472              :     AicpuUtil() = default;
     473              :     ~AicpuUtil() = default;
     474              : 
     475              :     AicpuUtil(AicpuUtil const&) = delete;
     476              :     AicpuUtil& operator=(AicpuUtil const&) = delete;
     477              :     AicpuUtil(AicpuUtil&&) = delete;
     478              :     AicpuUtil& operator=(AicpuUtil&&) = delete;
     479              : };
     480              : 
     481              : class SpinLock {
     482              : public:
     483          111 :     SpinLock() = default;
     484              : 
     485              :     ~SpinLock() = default;
     486              : 
     487       544975 :     void Lock()
     488              :     {
     489      1089950 :         while (lock_.test_and_set()) {}
     490       544975 :     }
     491              : 
     492       544975 :     void Unlock()
     493              :     {
     494       544975 :         lock_.clear();
     495       544975 :     }
     496              : 
     497              : private:
     498              :     SpinLock(const SpinLock&) = delete;
     499              :     SpinLock& operator=(const ScopeGuard&) = delete;
     500              :     SpinLock(SpinLock&&) = delete;
     501              :     SpinLock& operator=(SpinLock&&) = delete;
     502              : 
     503              :     std::atomic_flag lock_ = ATOMIC_FLAG_INIT;
     504              : };
     505              : 
     506           63 : inline uint64_t GetCurrentTime()
     507              : {
     508           63 :     uint64_t ret = 0U;
     509              :     struct timeval tv;
     510           63 :     if (gettimeofday(&tv, nullptr) == 0) {
     511           62 :         ret = (static_cast<uint64_t>(tv.tv_sec) * 1000000UL) + static_cast<uint64_t>(tv.tv_usec);
     512              :     }
     513              : 
     514           63 :     return ret;
     515              : }
     516              : 
     517              : } // namespace aicpu
     518              : 
     519              : #endif // COMMON_AICPUSD_UTIL_H
     520              : 
        

Generated by: LCOV version 2.0-1