LCOV - code coverage report
Current view: top level - base_comm/primitives/api_c_adpt - aicpu_ts_sync_data_c_adpt.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.1 % 101 92
Test Date: 2026-08-25 19:18:03 Functions: 100.0 % 5 5

            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              : #include "aicpu_ts_sync_data_c_adpt.h"
      12              : 
      13              : #include <chrono>
      14              : #include <thread>
      15              : #include <atomic>
      16              : #include <cmath>
      17              : 
      18              : #include "log.h"
      19              : #include "thread.h"
      20              : #include "aicpu_ts_thread.h"
      21              : #include "externalinput_pub.h"
      22              : 
      23              : constexpr size_t MSG_TAG_SIZE_BYTE = 256;
      24              : constexpr uint32_t TIMEOUT_SIZE_BYTE = 4;      // timeout字段长度为4字节,表示超时时间,单位为秒
      25              : constexpr uint32_t CTRL_HDR_DATA_SIZE_LEN = 8; // size_t 在不同平台上长度不同,取最大值
      26              : 
      27              : // 同步等待超时(秒),复用 HCCL_EXEC_TIMEOUT 环境变量配置的算子级执行超时,向上取整为秒
      28            3 : static uint32_t GetSyncWaitTimeoutSeconds()
      29              : {
      30            3 :     return static_cast<uint32_t>(std::ceil(GetExternalInputHcclExecTimeOut()));
      31              : }
      32              : 
      33              : // Msg 数据格式如下(单位:字节):
      34              : // +----------+--------------+-----------+-------------+---------------+-----------------+
      35              : // | flag [1] | msgTag [256] | msgId [4] | timeout [4] | data size [8] | data [sizeByte] |
      36              : // +----------+--------------+-----------+-------------+---------------+-----------------+
      37              : // ^
      38              : // handle
      39              : 
      40            3 : static HcclResult WaitFlagReady(uint8_t* srcFlagPtr)
      41              : {
      42            3 :     HCCL_INFO("[%s] Polling flag START.", __func__);
      43            3 :     const auto timeStart = std::chrono::steady_clock::now();
      44            3 :     const uint32_t timeoutVal = GetSyncWaitTimeoutSeconds();
      45            3 :     HCCL_INFO("[%s] Using timeout = %u seconds.", __func__, timeoutVal);
      46            3 :     auto timeoutSec = std::chrono::seconds(timeoutVal);
      47            3 :     uint8_t flagReadValue{0};
      48            3 :     errno_t ret = EOK;
      49              :     while (true) {
      50     63732382 :         ret = memcpy_s(&flagReadValue, sizeof(flagReadValue), srcFlagPtr, sizeof(flagReadValue));
      51     63732383 :         CHK_PRT_RET(ret != EOK, HCCL_ERROR("[%s][memcpy_s] Polling flag ERROR[%d].", __func__, ret), HCCL_E_INTERNAL);
      52     63732382 :         if (flagReadValue == 1) {
      53            2 :             break;
      54              :         }
      55              :         const auto elapsed
      56     63732380 :             = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - timeStart);
      57     63732380 :         if (timeoutVal != 0 && elapsed > timeoutSec) {
      58            1 :             HCCL_ERROR("[%s] Polling flag TIMEOUT, timeout[%u]s.", __func__, timeoutVal);
      59            1 :             return HCCL_E_TIMEOUT;
      60              :         }
      61     63732379 :     }
      62            2 :     HCCL_INFO("[%s] Polling flag SUCCESS.", __func__);
      63            2 :     return HCCL_SUCCESS;
      64              : }
      65              : 
      66              : #ifdef __cplusplus
      67              : extern "C" {
      68              : #endif // __cplusplus
      69              : 
      70            2 : int32_t HcommSendRequest(MsgHandle handle, const char* msgTag, const void* src, size_t sizeByte, uint32_t* msgId)
      71              : {
      72            2 :     uint8_t* const dstOnDevShmem = reinterpret_cast<uint8_t*>(handle);
      73            2 :     CHK_PTR_NULL(dstOnDevShmem);
      74            1 :     CHK_PTR_NULL(msgTag);
      75            1 :     CHK_PTR_NULL(src);
      76              : 
      77            1 :     HCCL_INFO(
      78              :         "[%s] START. msgHandle[0x%llx], msgTag[%s], src[0x%llx], sizeByte[%zu].", __func__, handle, msgTag, src,
      79              :         sizeByte);
      80              : 
      81              :     static std::atomic<uint32_t> s_msgId{0};
      82            1 :     *msgId = s_msgId.fetch_add(1, std::memory_order_relaxed); // msgId 达 UINT32_MAX 后回绕到 0,仅保证唯一性
      83              : 
      84            1 :     const uint8_t flagWriteValue{1};
      85            1 :     uint8_t* const dstFlagPtr = dstOnDevShmem;
      86            1 :     uint8_t* const dstMsgTagPtr = dstFlagPtr + sizeof(flagWriteValue);
      87            1 :     uint8_t* const dstMsgIdPtr = dstMsgTagPtr + MSG_TAG_SIZE_BYTE;
      88            1 :     uint8_t* const dstDataPtr = dstMsgIdPtr + sizeof(*msgId) + TIMEOUT_SIZE_BYTE;
      89            1 :     errno_t ret = EOK;
      90              : 
      91            1 :     HCCL_INFO("[%s] Writing %zu bytes data from src to shared mem START.", __func__, sizeByte);
      92            1 :     ret = memcpy_s(dstDataPtr, sizeof(sizeByte), &sizeByte, sizeof(sizeByte));
      93            1 :     CHK_PRT_RET(ret != EOK, HCCL_ERROR("[%s][memcpy_s] Writing data ERROR[%d].", __func__, ret), HCCL_E_INTERNAL);
      94            1 :     ret = memcpy_s(dstDataPtr + CTRL_HDR_DATA_SIZE_LEN, sizeByte, src, sizeByte);
      95            1 :     CHK_PRT_RET(ret != EOK, HCCL_ERROR("[%s][memcpy_s] Writing data ERROR[%d].", __func__, ret), HCCL_E_INTERNAL);
      96            1 :     HCCL_INFO("[%s] Writing %zu bytes data from src to shared mem SUCCESS.", __func__, sizeByte);
      97              : 
      98            1 :     HCCL_INFO("[%s] Writing %zu bytes msgId to shared mem START. msgId = %u.", __func__, sizeof(*msgId), *msgId);
      99            1 :     ret = memcpy_s(dstMsgIdPtr, sizeof(*msgId), msgId, sizeof(*msgId));
     100            1 :     CHK_PRT_RET(ret != EOK, HCCL_ERROR("[%s][memcpy_s] Writing msgId ERROR[%d].", __func__, ret), HCCL_E_INTERNAL);
     101            1 :     HCCL_INFO("[%s] Writing %zu bytes msgId to shared mem SUCCESS. msgId = %u.", __func__, sizeof(*msgId), *msgId);
     102              : 
     103            1 :     HCCL_INFO("[%s] Writing %zu bytes msgTag to shared mem START.", __func__, MSG_TAG_SIZE_BYTE);
     104            1 :     ret = memcpy_s(dstMsgTagPtr, MSG_TAG_SIZE_BYTE, msgTag, MSG_TAG_SIZE_BYTE);
     105            1 :     CHK_PRT_RET(ret != EOK, HCCL_ERROR("[%s][memcpy_s] Writing msgTag ERROR[%d].", __func__, ret), HCCL_E_INTERNAL);
     106            1 :     HCCL_INFO("[%s] Writing %zu bytes msgTag to shared mem SUCCESS.", __func__, MSG_TAG_SIZE_BYTE);
     107              : 
     108              : #if defined(__aarch64__) || defined(__arm__)
     109              :     asm volatile("dmb sy" ::: "memory"); // 确保之前的内存写入对其他线程可见
     110              : #else
     111            1 :     asm volatile("" ::: "memory"); // 非 ARM 架构(x86)仅用编译屏障防止重排
     112              : #endif
     113              : 
     114            1 :     HCCL_INFO("[%s] Setting flag = 1 on shared mem START.", __func__);
     115            1 :     ret = memcpy_s(dstFlagPtr, sizeof(flagWriteValue), &flagWriteValue, sizeof(flagWriteValue));
     116            1 :     CHK_PRT_RET(ret != EOK, HCCL_ERROR("[%s][memcpy_s] Setting flag ERROR[%d].", __func__, ret), HCCL_E_INTERNAL);
     117            1 :     HCCL_INFO("[%s] Setting flag = 1 on shared mem SUCCESS.", __func__);
     118              : 
     119            1 :     HCCL_INFO("[%s] SUCCESS. msgId[%u].", __func__, *msgId);
     120            1 :     return HCCL_SUCCESS;
     121              : }
     122              : 
     123            3 : int32_t HcommWaitResponse(MsgHandle handle, void* dst, size_t sizeByte, uint32_t* msgId)
     124              : {
     125            3 :     uint8_t* const srcOnDevShmem = reinterpret_cast<uint8_t*>(handle);
     126            3 :     CHK_PTR_NULL(srcOnDevShmem);
     127            3 :     if (sizeByte > 0) {
     128            2 :         CHK_PTR_NULL(dst);
     129              :     }
     130            3 :     CHK_PTR_NULL(msgId);
     131              : 
     132            3 :     HCCL_INFO("[%s] START. msgHandle[0x%llx], dst[0x%llx], sizeByte[%zu].", __func__, handle, dst, sizeByte);
     133              : 
     134            3 :     constexpr size_t sizeByteMsgId = sizeof(uint32_t);
     135            3 :     uint8_t flagReadValue{0};
     136            3 :     uint8_t* const srcFlagPtr = srcOnDevShmem;
     137            3 :     uint8_t* const srcMsgIdPtr = srcFlagPtr + sizeof(flagReadValue) + MSG_TAG_SIZE_BYTE;
     138            3 :     uint8_t* const srcTimeoutPtr = srcMsgIdPtr + sizeByteMsgId;
     139            3 :     uint8_t* const srcDataPtr = srcTimeoutPtr + TIMEOUT_SIZE_BYTE;
     140            3 :     errno_t ret = EOK;
     141              : 
     142            3 :     CHK_RET(WaitFlagReady(srcFlagPtr));
     143              : 
     144            2 :     if (sizeByte > 0) {
     145            2 :         HCCL_INFO("[%s] Reading %zu bytes data from shared mem START.", __func__, sizeByte);
     146            2 :         ret = memcpy_s(dst, sizeByte, srcDataPtr, sizeByte);
     147            2 :         CHK_PRT_RET(ret != EOK, HCCL_ERROR("[%s][memcpy_s] Reading data ERROR[%d]", __func__, ret), HCCL_E_INTERNAL);
     148            2 :         HCCL_INFO("[%s] Reading %zu bytes data from shared mem SUCCESS.", __func__, sizeByte);
     149              :     }
     150              : 
     151            2 :     HCCL_INFO("[%s] Reading %zu bytes msgId from shared mem START.", __func__, sizeByteMsgId);
     152            2 :     ret = memcpy_s(msgId, sizeByteMsgId, srcMsgIdPtr, sizeByteMsgId);
     153            2 :     CHK_PRT_RET(ret != EOK, HCCL_ERROR("[%s][memcpy_s] Reading msgId ERROR[%d].", __func__, ret), HCCL_E_INTERNAL);
     154            2 :     HCCL_INFO("[%s] Reading %zu bytes msgId from shared mem SUCCESS. msgId = %u.", __func__, sizeByteMsgId, *msgId);
     155              : 
     156            2 :     HCCL_INFO("[%s] Setting flag = 0 on shared mem START.", __func__);
     157            2 :     ret = memset_s(srcFlagPtr, sizeof(flagReadValue), 0, sizeof(flagReadValue));
     158            2 :     CHK_PRT_RET(ret != EOK, HCCL_ERROR("[%s][memset_s] Resetting flag ERROR[%d]", __func__, ret), HCCL_E_INTERNAL);
     159            2 :     HCCL_INFO("[%s] Setting flag = 0 on shared mem SUCCESS.", __func__);
     160              : 
     161            2 :     HCCL_INFO("[%s] SUCCESS. msgId[%u].", __func__, *msgId);
     162            2 :     return HCCL_SUCCESS;
     163              : }
     164              : 
     165            2 : int32_t HcommThreadSynchronize(ThreadHandle thread)
     166              : {
     167            2 :     hccl::Thread* threadPtr = reinterpret_cast<hccl::Thread*>(thread);
     168            2 :     CHK_PTR_NULL(threadPtr);
     169              : 
     170            1 :     HCCL_INFO("[%s] START. thread[0x%llx].", __func__, thread);
     171              : 
     172            1 :     if (threadPtr->IsDeviceA5()) {
     173            0 :         HCCL_INFO("[%s] Running on A5.", __func__);
     174            0 :         hccl::AicpuTsThread* aicpuTsThreadPtr = dynamic_cast<hccl::AicpuTsThread*>(threadPtr);
     175            0 :         uint32_t sqHead{0};
     176            0 :         uint32_t sqTail{0};
     177            0 :         HCCL_INFO("[%s] Start waiting for RTSQ's head == tail.", __func__);
     178              :         do {
     179            0 :             CHK_RET(aicpuTsThreadPtr->GetSqHeadAndTail(sqHead, sqTail));
     180            0 :         } while (sqHead != sqTail);
     181            0 :         HCCL_INFO("[%s] SUCCESS. RTSQ's head == tail.", __func__);
     182            0 :         return HCCL_SUCCESS;
     183              :     }
     184              : 
     185            1 :     HCCL_INFO("[%s] NOT Running on A5. No implementation, return SUCCESS.", __func__);
     186            1 :     return HCCL_SUCCESS;
     187              : }
     188              : #ifdef __cplusplus
     189              : }
     190              : #endif // __cplusplus
        

Generated by: LCOV version 2.0-1