LCOV - code coverage report
Current view: top level - legacy/ascend910/pub_inc - peterson_lock.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 6 6
Test Date: 2026-08-18 17:47:01 Functions: 100.0 % 3 3

            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 PETERSON_LOCK_H
      12              : #define PETERSON_LOCK_H
      13              : 
      14              : #include <string>
      15              : #include <thread>
      16              : #include <atomic>
      17              : #include <hccl/hccl_types.h>
      18              : #include "hccl_common.h"
      19              : #include "mem_device_pub.h"
      20              : 
      21              : /**
      22              :  * 这里实现Peterson算法来实现host侧与device侧的互斥访问
      23              :  *
      24              :  * 背景:host侧与device可以通过H2D/D2H等API来进行共享内存访问,
      25              :  *       那么这两者之间无法对共享变量使用类似于CAS的机制,因此不能基于
      26              :  *       原子修改类API的方式实现锁,所以这里基于Peterson算法实现,
      27              :  *       paper参考:https://zoo.cs.yale.edu/classes/cs323/doc/Peterson.pdf
      28              :  *
      29              :  * 依赖:Peterson算法虽然不依赖原子操作,但是依赖读写内存序,因此需要添加内存屏障
      30              :  *       来避免编译器与CPU的乱序执行
      31              :  *
      32              :  * 限制:目前实现只支持单个Host线程与单个Device线程互斥访问,不支持Host/Device侧多线程访问,
      33              :  *       如需单侧多线程访问请先使用std::mutex或者pthread_spinlock_t保证互斥,再使用该锁
      34              :  *
      35              :  * 内存布局:
      36              :  *      [u32 turn] [u32 hostFlag] [u32 deviceFlag]
      37              :  */
      38              : namespace hccl {
      39              : class PetersonLock {
      40              : public:
      41              :     static constexpr u64 DEFAULT_LOCK_TIMEOUT_SEC = 60; /* 默认的超时时间, 60s */
      42              : 
      43              :     /* Host侧对象构造函数,在Init()中会进行Device侧内存申请 */
      44              :     explicit PetersonLock(u64 timeoutSec);
      45              :     /* Device侧对象构造函数,devPtr是在Host申请的设备侧内存地址 */
      46              :     PetersonLock(void* devPtr, u64 timeoutSec);
      47              :     ~PetersonLock();
      48              : 
      49              :     HcclResult Init();
      50              :     HcclResult DeInit();
      51              : 
      52              :     /* 目前该接口只服务于传递地址给Device侧,所以直接返回u64而不是指针 */
      53              :     u64 GetDevMemAddr() const;
      54              : 
      55              :     HcclResult Lock();
      56              :     HcclResult Unlock();
      57              : 
      58              :     /* 显式禁用所有copy、move构造函数,因为锁不可复制,不可移动 */
      59              :     PetersonLock(const PetersonLock&) = delete;
      60              :     PetersonLock(PetersonLock&&) = delete;
      61              :     PetersonLock& operator=(const PetersonLock&) = delete;
      62              :     PetersonLock& operator=(PetersonLock&&) = delete;
      63              : 
      64              : private:
      65              :     HcclResult AllocDeviceMem();
      66              : 
      67              :     HcclResult WriteSelfFlag(u32 selfFlag);
      68              :     HcclResult WriteTurn();
      69              :     HcclResult ReadPeerFlag(u32& peerFlag);
      70              :     HcclResult ReadTurn(u32& peerTurn);
      71              : 
      72              :     static constexpr size_t MIN_SHM_LEN = 32; /* 最小的共享内存大小 */
      73              :     enum class Type : int { HOST = 0, DEVICE = 1 };
      74              : 
      75              :     static constexpr u32 TURN_FOR_HOST = 1;
      76              :     static constexpr u32 TURN_FOR_DEVICE = 0;
      77              :     static constexpr u32 FLAG_LOCK = 1;   /* 获取锁 */
      78              :     static constexpr u32 FLAG_UNLOCK = 0; /* 释放锁 */
      79              : 
      80         1197 :     void MemFence() const
      81              :     {
      82              :         /* 内存屏障,即阻止编译器重排变量读写,也阻止CPU重排变量读写 */
      83              :         std::atomic_thread_fence(std::memory_order_seq_cst);
      84         1197 :     }
      85              : 
      86         1285 :     void Wait() const
      87              :     {
      88              :         /* 无事可做暂时释放CPU */
      89         1285 :         sched_yield();
      90         1285 :     }
      91              : 
      92              :     size_t size_ = 0;
      93              :     Type type_ = Type::HOST;
      94              :     std::string typeName_;
      95              :     u64 timeout_;
      96              :     DeviceMem devMem_;
      97              :     u32 myTurn_;
      98              : 
      99              :     /*
     100              :      * 这里变量使用volatile修饰,是为了Device直接读写内存数据,而不是CPU cache
     101              :      */
     102              :     volatile u32* turn_ = nullptr;
     103              :     volatile u32* hostFlag_ = nullptr;
     104              :     volatile u32* deviceFlag_ = nullptr;
     105              : };
     106              : /**
     107              :  * 使用RAII特性使用PetersonLock,在该对象构造时加锁,析构时释放锁
     108              :  * 因为获取锁有可能失败,所以要调用IsLockFailed()去检查,只有加锁成功才能继续往下执行
     109              :  */
     110              : class PetersonLockGuard {
     111              : public:
     112              :     explicit PetersonLockGuard(PetersonLock* lock);
     113              :     ~PetersonLockGuard();
     114              : 
     115          200 :     bool IsLockFailed() const { return lockFailed_; }
     116              : 
     117              :     /* 显式禁用所有copy、move构造函数,因为锁不可复制,不可移动 */
     118              :     PetersonLockGuard(const PetersonLockGuard&) = delete;
     119              :     PetersonLockGuard(PetersonLockGuard&&) = delete;
     120              :     PetersonLockGuard& operator=(const PetersonLockGuard&) = delete;
     121              :     PetersonLockGuard& operator=(PetersonLockGuard&&) = delete;
     122              : 
     123              : private:
     124              :     PetersonLock* lock_ = nullptr;
     125              :     bool lockFailed_ = false;
     126              : };
     127              : } // namespace hccl
     128              : 
     129              : #endif
        

Generated by: LCOV version 2.0-1