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

Generated by: LCOV version 2.0-1