在这里插入图片描述

跨核/跨线程 Fence 详细设计方案

一、项目中类似的实现分析

zephyr中已有以下跨核同步机制:
  1. rbuf 机制 (zephyr/lib/rbuf/)

    • 使用 INTER_RAM 共享内存
    • 通过 ring buffer 进行跨核消息传递
    • 支持 CPU、DSP、BT、SC 四个核心
  2. DSP Mailbox 机制 (zephyr/drivers/dsp/dsp_mailbox.c)

    • 使用共享 mailbox + 状态标志位
    • 轮询等待 ACK(wait_ack_timeout
    • 使用中断触发(mcu_trigger_irq_to_dsp
  3. BT HCI 同步 (framework/bluetooth/bt_stack/)

    • 使用 k_sem 进行同步等待
    • 同核场景,使用信号量即可
Android Fence 的核心特性

Android 的 SyncFence 包含:

  1. Timeline 机制:每个 fence 有序列号,基于 timeline
  2. 合并操作:支持 AND/OR 合并,形成树状结构
  3. 硬件 fence:支持 GPU/DMA 等硬件完成信号
  4. 引用计数:自动管理生命周期
  5. 状态查询:非阻塞查询状态
  6. 错误处理:支持错误状态传播

二、完整数据结构设计

// ========== Timeline定义 ==========
typedef struct fence_timeline {
    uint32_t id;                    // Timeline ID(如GPU、DMA等)
    atomic_t seq;                   // 当前序列号(单调递增)
    uint32_t core_id;              // 所属核心
    sys_slist_t fence_list;        // 关联的fence列表
    os_mutex mutex;                // 保护timeline
} fence_timeline_t;

// ========== Fence状态 ==========
typedef enum {
    FENCE_STATE_PENDING = 0,        // 等待中
    FENCE_STATE_SIGNALED = 1,       // 已信号
    FENCE_STATE_ERROR = 0xFFFFFFFF  // 错误状态
} fence_state_t;

// ========== Fence类型 ==========
typedef enum {
    FENCE_TYPE_SOFTWARE = 0,        // 软件fence
    FENCE_TYPE_GPU,                 // GPU硬件fence
    FENCE_TYPE_DMA,                 // DMA硬件fence
    FENCE_TYPE_MERGED               // 合并fence
} fence_type_t;

// ========== 共享内存中的Fence结构 ==========
typedef struct fence_shared {
    // 基础信息
    atomic_t state;                 // 状态(PENDING/SIGNALED/ERROR)
    atomic_t ref_count;             // 引用计数(跨核可见)
    uint32_t magic;                 // 魔数:0xFENCE1234
    uint32_t creator_core;          // 创建者核心ID
    
    // Timeline信息
    uint32_t timeline_id;           // Timeline ID
    uint32_t seq;                   // 序列号(在timeline上的位置)
    
    // 类型和标志
    uint32_t type;                  // Fence类型
    uint32_t flags;                 // 标志位
    
    // 合并fence信息(如果是合并fence)
    uint32_t merge_type;            // MERGE_AND(0) / MERGE_OR(1)
    uint32_t merge_count;           // 合并的fence数量
    uint32_t merge_fences[4];       // 合并的fence句柄(最多4个,可扩展)
    
    // 等待者信息
    atomic_t waiters_count;         // 等待者计数
    uint32_t reserved[2];           // 保留字段,保证对齐
} fence_shared_t;

// ========== 本地Fence句柄 ==========
typedef struct fence {
    fence_shared_t *shared;         // 指向共享内存
    uint32_t local_core_id;        // 本地核心ID
    
    // 本地同步原语
    os_sem local_sem;              // 本地信号量(同核使用)
    
    // Timeline关联
    fence_timeline_t *timeline;     // 关联的timeline
    
    // 合并fence的子fence列表(本地)
    sys_slist_t merged_fences;      // 如果是合并fence,存储子fence
    
    // 引用计数(本地)
    atomic_t local_ref_count;      // 本地引用计数
    
    // 回调函数(用于硬件fence)
    void (*signal_callback)(struct fence *fence, void *data);
    void *signal_data;
    
    // 链表节点(用于timeline管理)
    sys_snode_t timeline_node;
    sys_snode_t global_node;
} fence_t;

// ========== 合并操作类型 ==========
typedef enum {
    FENCE_MERGE_AND = 0,            // AND操作:所有fence都信号才信号
    FENCE_MERGE_OR = 1             // OR操作:任一fence信号就信号
} fence_merge_type_t;

三、核心 API 设计

3.1 Timeline 管理
/**
 * @brief 创建timeline
 * @param timeline_id Timeline ID(如GPU、DMA等)
 * @param core_id 所属核心
 * @return timeline句柄
 */
fence_timeline_t* fence_timeline_create(uint32_t timeline_id, uint32_t core_id);

/**
 * @brief 获取timeline的当前序列号
 */
uint32_t fence_timeline_get_seq(fence_timeline_t *timeline);

/**
 * @brief Timeline前进(硬件完成时调用)
 * @param timeline Timeline句柄
 * @param seq 完成的序列号
 */
int fence_timeline_advance(fence_timeline_t *timeline, uint32_t seq);
3.2 Fence 创建
/**
 * @brief 创建fence(基于timeline)
 * @param timeline Timeline句柄
 * @param seq 序列号(如果为0,自动分配)
 * @return fence句柄
 */
fence_t* fence_create(fence_timeline_t *timeline, uint32_t seq);

/**
 * @brief 创建硬件fence(GPU/DMA)
 * @param timeline Timeline句柄
 * @param signal_callback 信号回调(硬件完成时调用)
 * @param signal_data 回调数据
 */
fence_t* fence_create_hardware(fence_timeline_t *timeline, 
                                void (*signal_callback)(fence_t*, void*),
                                void *signal_data);

/**
 * @brief 增加fence引用计数
 */
fence_t* fence_ref(fence_t *fence);

/**
 * @brief 减少fence引用计数(引用为0时自动销毁)
 */
void fence_unref(fence_t *fence);
3.3 Fence 合并(核心特性)
/**
 * @brief 合并多个fence(类似Android Fence::merge)
 * @param fences fence数组
 * @param count fence数量
 * @param merge_type AND或OR
 * @return 合并后的fence
 */
fence_t* fence_merge(fence_t **fences, uint32_t count, fence_merge_type_t merge_type);

/**
 * @brief 合并两个fence(常用接口)
 */
fence_t* fence_merge_two(fence_t *fence1, fence_t *fence2, fence_merge_type_t merge_type);
3.4 Fence 等待
/**
 * @brief 等待fence信号
 * @param fence fence句柄
 * @param timeout_ms 超时时间(-1表示永久等待)
 * @return 0成功,-ETIMEDOUT超时,-EIO错误
 */
int fence_wait(fence_t *fence, int32_t timeout_ms);

/**
 * @brief 非阻塞查询fence状态
 * @return FENCE_STATE_PENDING/SIGNALED/ERROR
 */
fence_state_t fence_get_state(fence_t *fence);

/**
 * @brief 检查fence是否已信号(非阻塞)
 */
bool fence_is_signaled(fence_t *fence);
3.5 Fence 信号
/**
 * @brief 信号fence(软件fence)
 */
int fence_signal(fence_t *fence);

/**
 * @brief 信号错误状态
 */
int fence_signal_error(fence_t *fence);

/**
 * @brief Timeline前进时自动信号fence(硬件fence)
 * 当timeline的seq >= fence的seq时,自动信号fence
 */
void fence_timeline_advance_signal(fence_timeline_t *timeline, uint32_t seq);

四、关键实现细节

4.1 Timeline 机制实现
// Timeline管理
static sys_slist_t g_timeline_list;
static os_mutex g_timeline_list_lock;

fence_timeline_t* fence_timeline_create(uint32_t timeline_id, uint32_t core_id)
{
    fence_timeline_t *timeline = mem_malloc(sizeof(fence_timeline_t));
    if (!timeline) return NULL;
    
    timeline->id = timeline_id;
    timeline->core_id = core_id;
    atomic_set(&timeline->seq, 0);
    sys_slist_init(&timeline->fence_list);
    os_mutex_init(&timeline->mutex);
    
    os_mutex_lock(&g_timeline_list_lock, OS_FOREVER);
    sys_slist_append(&g_timeline_list, &timeline->node);
    os_mutex_unlock(&g_timeline_list_lock);
    
    return timeline;
}

int fence_timeline_advance(fence_timeline_t *timeline, uint32_t seq)
{
    fence_t *fence;
    sys_snode_t *node;
    
    os_mutex_lock(&timeline->mutex, OS_FOREVER);
    
    // 更新序列号
    uint32_t old_seq = atomic_get(&timeline->seq);
    if (seq > old_seq) {
        atomic_set(&timeline->seq, seq);
    }
    
    // 检查并信号所有seq <= 当前seq的fence
    SYS_SLIST_FOR_EACH_NODE(&timeline->fence_list, node) {
        fence = CONTAINER_OF(node, fence_t, timeline_node);
        if (fence->shared->seq <= seq && 
            atomic_get(&fence->shared->state) == FENCE_STATE_PENDING) {
            // 自动信号fence
            fence_signal_internal(fence);
        }
    }
    
    os_mutex_unlock(&timeline->mutex);
    return 0;
}
4.2 Fence 合并实现(核心)
fence_t* fence_merge(fence_t **fences, uint32_t count, fence_merge_type_t merge_type)
{
    fence_t *merged_fence;
    fence_shared_t *merged_shared;
    uint32_t i;
    
    if (count == 0 || count > 4) return NULL;
    
    // 1. 创建合并fence
    merged_fence = fence_create_internal(FENCE_TYPE_MERGED);
    merged_shared = merged_fence->shared;
    
    // 2. 设置合并信息
    merged_shared->merge_type = merge_type;
    merged_shared->merge_count = count;
    
    // 3. 保存子fence的句柄(在共享内存中)
    for (i = 0; i < count; i++) {
        merged_shared->merge_fences[i] = fence_to_handle(fences[i]);
        fence_ref(fences[i]);  // 增加子fence引用
    }
    
    // 4. 检查是否所有子fence都已信号(AND)或任一已信号(OR)
    bool should_signal = false;
    if (merge_type == FENCE_MERGE_AND) {
        // AND:检查是否所有都信号
        should_signal = true;
        for (i = 0; i < count; i++) {
            if (!fence_is_signaled(fences[i])) {
                should_signal = false;
                break;
            }
        }
    } else {
        // OR:检查是否有任一信号
        for (i = 0; i < count; i++) {
            if (fence_is_signaled(fences[i])) {
                should_signal = true;
                break;
            }
        }
    }
    
    // 5. 如果应该立即信号,直接信号
    if (should_signal) {
        fence_signal(merged_fence);
    } else {
        // 6. 注册回调,监听子fence状态变化
        for (i = 0; i < count; i++) {
            fence_register_merge_callback(fences[i], merged_fence);
        }
    }
    
    return merged_fence;
}

// 子fence信号时的回调
static void fence_merge_callback(fence_t *child_fence, void *data)
{
    fence_t *merged_fence = (fence_t *)data;
    fence_shared_t *merged_shared = merged_fence->shared;
    uint32_t i;
    bool should_signal = false;
    
    if (merged_shared->merge_type == FENCE_MERGE_AND) {
        // AND:检查所有子fence
        should_signal = true;
        for (i = 0; i < merged_shared->merge_count; i++) {
            fence_t *child = handle_to_fence(merged_shared->merge_fences[i]);
            if (child && !fence_is_signaled(child)) {
                should_signal = false;
                break;
            }
        }
    } else {
        // OR:任一信号即可
        should_signal = true;
    }
    
    if (should_signal) {
        fence_signal(merged_fence);
    }
}
4.3 硬件 Fence 集成
// GPU完成中断处理
void gpu_complete_isr(uint32_t seq)
{
    fence_timeline_t *gpu_timeline = fence_timeline_get(GPU_TIMELINE_ID);
    if (gpu_timeline) {
        // Timeline前进,自动信号所有seq <= seq的fence
        fence_timeline_advance(gpu_timeline, seq);
    }
}

// 创建GPU fence
fence_t* fence_create_gpu(uint32_t seq)
{
    fence_timeline_t *gpu_timeline = fence_timeline_get(GPU_TIMELINE_ID);
    if (!gpu_timeline) {
        gpu_timeline = fence_timeline_create(GPU_TIMELINE_ID, CPU);
    }
    
    fence_t *fence = fence_create(gpu_timeline, seq);
    fence->shared->type = FENCE_TYPE_GPU;
    
    return fence;
}
4.4 跨核 Fence 等待(增强版)
int fence_wait_cross_core(fence_t *fence, int32_t timeout_ms)
{
    fence_shared_t *shared = fence->shared;
    uint32_t curr_core = fence_get_core_id();
    
    // 1. 如果是合并fence,需要等待所有子fence
    if (shared->type == FENCE_TYPE_MERGED) {
        return fence_wait_merged(fence, timeout_ms);
    }
    
    // 2. 检查timeline(硬件fence)
    if (shared->type == FENCE_TYPE_GPU || shared->type == FENCE_TYPE_DMA) {
        fence_timeline_t *timeline = fence->timeline;
        uint32_t current_seq = fence_timeline_get_seq(timeline);
        
        // 如果timeline已经超过fence的seq,直接返回
        if (current_seq >= shared->seq) {
            return 0;
        }
    }
    
    // 3. 常规等待逻辑(同之前设计)
    // ...
}

int fence_wait_merged(fence_t *merged_fence, int32_t timeout_ms)
{
    fence_shared_t *shared = merged_fence->shared;
    uint32_t i;
    int ret = 0;
    
    if (shared->merge_type == FENCE_MERGE_AND) {
        // AND:等待所有子fence
        for (i = 0; i < shared->merge_count; i++) {
            fence_t *child = handle_to_fence(shared->merge_fences[i]);
            if (child) {
                ret = fence_wait(child, timeout_ms);
                if (ret != 0) break;
            }
        }
    } else {
        // OR:等待任一fence信号
        // 可以使用k_poll或轮询所有fence
        // ...
    }
    
    return ret;
}

五、使用示例

// ========== 示例1:GPU渲染fence ==========
void render_frame(void)
{
    fence_timeline_t *gpu_timeline = fence_timeline_get(GPU_TIMELINE_ID);
    
    // 创建GPU fence,序列号为当前timeline seq + 1
    uint32_t render_seq = fence_timeline_get_seq(gpu_timeline) + 1;
    fence_t *render_fence = fence_create_gpu(render_seq);
    
    // 提交渲染任务(传递seq给GPU)
    gpu_submit_render(render_seq);
    
    // 等待渲染完成
    fence_wait(render_fence, 1000);
    
    fence_unref(render_fence);
}

// GPU完成中断中
void gpu_isr(void)
{
    uint32_t completed_seq = gpu_get_completed_seq();
    fence_timeline_advance(gpu_timeline, completed_seq);
    // 自动信号所有seq <= completed_seq的fence
}

// ========== 示例2:合并多个fence ==========
void wait_multiple_operations(void)
{
    fence_t *gpu_fence = fence_create_gpu(seq1);
    fence_t *dma_fence = fence_create_dma(seq2);
    fence_t *cpu_fence = fence_create_software();
    
    // 合并:等待GPU和DMA都完成(AND操作)
    fence_t *merged = fence_merge_two(gpu_fence, dma_fence, FENCE_MERGE_AND);
    
    // 等待合并fence
    fence_wait(merged, 5000);
    
    // 清理
    fence_unref(merged);
    fence_unref(gpu_fence);
    fence_unref(dma_fence);
    fence_unref(cpu_fence);
}

// ========== 示例3:复杂合并 ==========
void complex_sync(void)
{
    fence_t *f1 = fence_create_gpu(seq1);
    fence_t *f2 = fence_create_dma(seq2);
    fence_t *f3 = fence_create_software();
    
    // 先合并f1和f2(AND)
    fence_t *merged1 = fence_merge_two(f1, f2, FENCE_MERGE_AND);
    
    // 再与f3合并(OR:f1&&f2完成 或 f3完成)
    fence_t *fences[] = {merged1, f3};
    fence_t *final = fence_merge(fences, 2, FENCE_MERGE_OR);
    
    fence_wait(final, -1);
    
    // 清理所有引用
    fence_unref(final);
    fence_unref(merged1);
    fence_unref(f1);
    fence_unref(f2);
    fence_unref(f3);
}

六、与 Android Fence 的对比

特性 Android Fence 本设计 说明
Timeline 基于序列号的timeline
合并操作 支持AND/OR合并
硬件fence 支持GPU/DMA等
引用计数 自动管理生命周期
跨进程 在RTOS上是跨核
状态查询 非阻塞查询
错误处理 支持错误状态
文件描述符 RTOS不需要,用句柄

七、关键点

  1. Timeline 机制:每个 fence 有序列号,硬件完成时自动信号
  2. 合并操作:支持 AND/OR,可形成树状结构
  3. 硬件集成:GPU/DMA 完成时自动信号相关 fence
  4. 引用计数:自动管理生命周期,避免内存泄漏
  5. 跨核支持:共享内存 + 中断,支持跨核同步

八、Fence 使用场景总结

一、图形渲染场景

  1. GPU 渲染完成等待

    • 等待 GPU 完成绘制后再显示
    • 避免在渲染未完成时使用缓冲区
  2. DMA2D 传输完成

    • 等待 DMA2D 完成图像拷贝/转换
    • 确保数据已写入目标缓冲区
  3. 多硬件并行渲染

    • GPU 和 DMA2D 同时工作,等待两者都完成
    • 使用合并 fence(AND 操作)
  4. Surface 双缓冲同步

    • 等待上一帧显示完成再开始新帧
    • 等待 back buffer 释放再使用
    • 避免缓冲区冲突

二、跨核通信场景

  1. CPU 等待 DSP 处理完成

    • CPU 提交音频/图像处理到 DSP
    • 等待 DSP 完成后再使用结果
  2. CPU 等待 BT CPU 完成

    • CPU 发送 HCI 命令到 BT CPU
    • 等待 BT CPU 处理完成
  3. 多核心流水线

    • CPU 准备数据 → DSP 处理 → GPU 渲染 → Display 显示
    • 每个阶段等待前一个阶段完成

三、硬件加速场景

  1. 音频编解码同步

    • 等待 DSP 完成音频编码/解码
    • 确保数据可用后再处理
  2. 视频解码同步

    • 等待硬件解码器完成一帧解码
    • 避免使用未完成的解码数据
  3. 图像处理同步

    • 等待 JPEG 硬件解码完成
    • 等待图像缩放/旋转完成

四、DMA 传输场景

  1. SPI DMA 传输完成

    • 等待 SPI DMA 完成数据传输
    • 确保数据已写入/读出
  2. MMC/SD 卡 DMA 传输

    • 等待 SD 卡 DMA 读写完成
    • 避免在传输中访问数据
  3. 音频 DMA 传输

    • 等待音频 DMA 完成播放/录制
    • 确保缓冲区可安全使用

五、显示同步场景

  1. VSync 同步

    • 等待垂直同步信号
    • 在 VSync 时 swap buffer
  2. 多图层合成

    • 等待所有图层渲染完成
    • 使用合并 fence 等待所有图层
  3. 显示引擎同步

    • 等待 Display Engine 完成一帧显示
    • 避免 tearing

六、复杂同步场景

  1. 条件等待

    • 等待 GPU 渲染完成或超时
    • 任一条件满足即继续(OR 合并)
  2. 依赖链

    • 任务 A 完成后启动任务 B
    • 任务 B 完成后启动任务 C
    • 形成依赖链
  3. 资源释放等待

    • 等待多个资源都释放(AND 合并)
    • 任一资源释放即可(OR 合并)

七、错误处理场景

  1. 超时检测

    • 硬件操作超时后标记错误
    • 通过 fence 错误状态通知上层
  2. 错误传播

    • 硬件错误通过 fence 传播
    • 合并 fence 中任一错误则整体失败

八、性能优化场景

  1. 异步渲染

    • 不阻塞主线程,异步等待渲染完成
    • 使用 fence 状态查询
  2. 批量操作

    • 提交多个渲染任务,等待全部完成
    • 使用合并 fence 提高效率
  3. 流水线并行

    • 同时处理多帧数据
    • 使用 timeline 管理多个 fence
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐