简图记录-android fence机制

一、概述

    fence:android4.4开始引入的一种资源同步机制,主要用于处理跨硬件场景,如CPU、GPU、HWC之间的buffer资源同步。可以将fence理解为一种资源锁。

    举个例子,customer使用producer提供的buffer,使用完成后要还给producer生产,如果没有fence,通常是customer完全使用完成后 开始归还转移buffer,拥有权/使用权 一起给到producer,producer获取到后可以马上使用。从资源并发访问的原则上看其实customer使用完成后producer已经可以写了,在buffer转移这个过程实际上没有任何人在使用这个buffer。fence的目的就是customer可以在开始用甚至是收到buffer的时候 开始归还转移buffer,同时也转移这个buffer对应的fence,producer收到buffer后 拿到拥有权但不一定能使用, 等到需要使用的时候通过wait fence来阻塞查看buffer是否被customer使用完,wait后拿到使用权开始写。理想的buffer轮转如下,保证buffer始终有人在使用。

    推荐blog:https://blog.csdn.net/jinzhuojun/article/details/39698317

二、原理

    fence的实现都在内核态完成,在实现上可以配合硬件或者单独使用软件完成。每个fence都对应一个文件描述符fd,通过fd可以实现用户态 内核态,进程之间的转移;要理解fence的原理,有以下三个重要概念:

    (1)sync_timeline:时间轴。每个流程必须有一个时间轴,时间轴是一个单调递增的计数器,时间轴由时间值组成,时间轴上可以指定有许多同步点sync_pt,当时间轴当前递增超过该sync_pt,则sync_pt状态切换(从active到signal或者error);

    (2)sync_pt:同步点,代表时间轴上一个特殊的值,有三种状态:active(刚创建,此时一般时间轴都是小于pt)/signal(时间轴增大到pt)/error

    (3)sync_fence:一系列sync_pt的集合,每个pt只能属于一个fence,一个fence包含的pt可以来自不同的timeline,fence可以合并,当fence中的所有pt被signal后,fence状态切换。fence都对应一个文件描述符来转移,需要使用fence对于的资源通过对fence进行wait进行阻塞查询状态,如果pt都被signal就唤醒wait。

     推荐blog:https://blog.csdn.net/ear5cm/article/details/45093807

三、使用举例

    A(customer)在内核态使用B(producer)生产的buffer资源,使用后利用fence机制提前把buffer拥有权给到B。

    我们做一个最简单的设计,A创建一个timeline,每次收到buffer后创建一个pt(pt的值从1开始每次++,相当于1、2、3、4.。。),然后每个pt就创建一个fence,fence绑定一个fd并将fd转移到B(producer),B需要使用buffer的时候通过fd来进行wait fence。此时A每使用完一个buffer,就对timeline++,意味着每加一次就有一个pt被signal,其对应的fence就被切换状态表示已可用。流程如下:

    (1)、A模块在初始化的时候创建timeline,保存到上下文:

        struct sw_sync_timeline *timeline = sw_sync_timeline_create("test-timeline");

    (2)、B送帧到A,A创建fence并转移fd 到B,使用完buffer后增加timeline:

        struct sync_pt *pt = sw_sync_pt_create(timeline, val);//在timeline创建pt,val从1开始每次++

        struct sync_fence *fence = sw_sync_fence_create("test-fence",pt);//用pt创建一个fence

        int fd = get_unused_fd(); sync_fence_install(fence,fd);//获取文件描述符,把fence和fd绑定

        当真正使用完buffer时,增加timeline:sw_sync_timeline_inc(timeline, 1);//对timeline加1(signal其上pt)

    (3)、B收到fd,等到需要使用该buffer时,使用wait查看fence可用状态,wait后使用buffer;

        最终在内核:struct fence *fence = sw_file_get_fence(fd);//通过文件描述符获取到fence

        sync_fence_wait(fence, 1000);//开始等待fence可用,超时timeout为1000              

四、经验总结

     (1)、关于fence的乱序问题;

        由于是通过增加timeline的方式去signal上面的pt来改变fene的状态,signal pt的方式 必然是顺序的,意味着创建fence的顺序决定释放的顺序。那么如果A模块 如果发生乱序还buffer,B等待fence去使用buffer则可能出现使用到A正在使用的buffer。

     (2)、关于fence的容错和debug建议;

        fence相对来说 debug比较困难。1、必须按顺序归还buffer,但是实际timeline++时 并不知道当前还的这个buffer addr对不对,是不是按顺序来的。2、由于wait存在timeout,很多应用timeout后 buffer管理就混乱掉了,发生退出等无法恢复的异常,这就约束了A不能持有buffer超过timeout时间,这给很多debug造成了干扰,比如我们希望在调度过程通过存buffer的内容到ddr看内容是否正确,很可能由于超时无法成功。

       建议:1、A一定要对输入buffer进行地址校验,不能同时送入2个地址相同的buffer; 2、收帧还帧必须有fence计数 create和signal,判断是否有buffer没有还的情况(特别考虑A有buffer没用完就被强制销毁,一定要保重全部buffer被signal还掉);3、预先埋入收帧 还帧地址打印,排查addr收还顺序;

  • 20
    点赞
  • 95
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值