Android Sync Framework

Android Sync Framework提供了一组API,解决在图形管线等复杂DMA环境中,消费者与生产者以及消费者之间对缓冲区的同步访问问题。通过sync_timeline、sync_pt和sync_fence等数据类型,实现跨硬件模块的同步。驱动开发者需要实现特定的同步原语,而Android框架层则使用Fence类进行交互。该框架旨在确保缓冲区在不同硬件组件间的原子性使用,并提供性能监控数据。
AI助手已提取文章相关产品:

定义

“Synchronization between consumers and producers who are from different hardware components to use a buffer atomically”

 

应用背景

在复杂的DMA管线如图形管线(多媒体,摄像头,GPU以及显示设备),一个buffer的消费者需要知道生产者什么时候完成生产(即创建一个Buffer,并往里面放置消费者所需要的数据)。同样地,生产者也需要知道消费者什么时候使用它创建的Buffer,以便它可以重新使用这个Buffer。而且,一个Buffer可能被多个不同的消费者使用不同的时间。另外,一个消费者可能需要互斥地消费多个Buffer,等等,有一个问题应运而生,就是如何保证多个消费者之间同步使用Buffer,以及生产者与消费者协调使用Buffer。因为Buffer是一个共享资源,且任何消费者或生产者对Buffer的使用都是排他性的(因为它们属于不同的硬件单元或模块),大体看来,需要解决如下两个问题:

1. 消费者与生产者之间对Buffer的同步访问。

2. 消费者之间对Buffer的同步访问。

方案提出

Android中,引入了Sync框架,它添加了一组API,可以允许生产者和消费者之间以一种通用的方式解决上面提到的同步访问问题,平台需要实现这些Driver定义的同步原语以支持这个Sync框架。

Android Sync框架的目标是:

1. 提供一个通用的API用于表达同步依赖关系。

2. 允许驱动在不同的硬件模块中实现同步。

3. 提供了一套用户空间的API,使得Compositor(等硬件模块)可以管理这些依赖。

4. 提供丰富的测量数据,可以调试图形管线变慢和停止的问题。

 

驱动代码位于drivers/staging/android/sync.c,主要定义了如下三个数据类型:

• sync_timeline

sync_timeline是一种抽象的单调递增的计数器。通常情况下,每个驱动或硬件模块上下文只有一个sync_timeline。一般需要提供硬件模块特有的Sync驱动或使用通用的sw_sync实现,它是基于CPU的一种实现方式。实现上,是通过这些底层的驱动来创建sync_timeline的。一个硬件模块如果要提供Sync支持,则必须实现创建sync_timeline逻辑的驱动。

• sync_pt

sync_pt是一个抽象的值,标记在sync_timeline上。sync_pt只能属于唯一的sync_timeline。它有三种状态:活跃,信号和错误。开始时,处于活跃状态,当sync_timeline的计数值超过了sync_pt的值,就会触发状态转换为信号状态或错误状态。

• sync_fence

sync_fence是驱动间协调同步使用Buffer的主要原语。它包含一系列的sync_pt,这些sync_pt可能来自于不同的sync_timeline。另外,sync_fence上的sync_pt一旦确定,是不可更改的。可以同步或异步等待sync_fence对象状态的改变。两个sync_fence对象也可以合并生成第三个Fence对象,它包含了合并前的两个sync_fence对象的所有sync_pt的拷贝。sync_fence与文件描述符关联,用户空间可以通过它来协调显示管线等硬件单元之间的依赖性关系,即访问Buffer的先后顺序。

 

Ownership of a fence fd
If you get a fence fd from the framework, you must close it(Sf dup fence fd and transfer the new one)

If you pass a fence fd to the framework, we will close it(If you want to keep using it, you must dup it, Sf merge fence if need transfer it)


如何使用

   一个实现Sync支持的驱动,应该拥有如下一个工作提交函数:

1. 接受一个sync_fence参数,指定什么时候开始工作。

2. sync_fence处于信号态后,异步地将对应的工作放入队列中去运行。

3. 返回一个sync_fence对象,包含工作何时结束的信息。

4. 当工作结束后,会将关联的sync_fence对象变成信号态。

 

接口声明实例:

Driver API without fence support

/*

* assumes buf is ready to be displayed.

* blocks until the buffer is on screen.

*/

void display_buffer(struct dma_buf *buf);

Driver API with fence support

/*

* will display buf when fence is signaled.

* returns immediately with a fence that will signal

* when buf  is no longer displayed.

*/

struct sync_fence* display_buffer(struct dma_buf *buf, struct sync_fence *fence);

 

Android  Sync框架的软件Stack如下图所示:



Android使用类Fence封装了sync用户接口,所以Android框架层中一般通用Fence类来使用Android Sync框架

 

Sync驱动

Sync驱动包含两部分:

  •  fence的通用操作,已经实现
  • 各个sync 驱动相关的代码,由各个硬件Vendor实现,其中,基于CPUsync驱动已经提供

主要数据结构

struct sync_timeline_ops

sync对象需要实现的一些操作

struct sync_timeline

代表一个sync对象的描述

它包含许多struct sync_pt

struct sync_pt

同步点

有三种状态

signaled(status > 0)

active(status = 0)

error(status < 0)

它位于一个sync_timeline以及sync_fence

struct sync_fence

struct sync_fence_waiter

在一个fence上异步等待的waiter的相关信息

主要API

API focomponentsr sync_time implementers

sync_timeline_create()

  创建一个sync对象

sync_timeline_destory()

销毁一个sync对象

sync_timeline_signal()

signal a status change on a sync_timeline

sync_pt_create()

创建一个同步点

sync_pt_free()

释放一个同步点

此函数仅能在该同步点未加入到一个fence前调用

sync_fence_create()

创建一个sync fence

API for sync_fence consumers

sync_fence_merge()

合并两个fence

当两个sync_pt位于同一个timeline时,需要将他们合并成一个sync_pt, 
并以触发时间最晚些的那个sync_pt那个为准


sync_fence_fdget()

根据一个fd获取对应的fence对象

sync_fence_put()

减少一次对sync fence的引用

sync_fence_install()

安装fence到一个文件描述符中

sync_fence_waiter_init()

sync_fence_wait_async()

注册和异步等待某个fence对象

sync_fence_cancel_async()

取消一个异步等待

sync_fence_wait()

等待一个fence状态变为signaled error

主要有三种IOCTL命令

SYNC_IOC_WAIT

SYNC_IOC_MERGE

SYNC_IOC_FENCE_INFO

fill_driver_data


实现一个Sync-aware的驱动

1.定义自己的timeline, pt数据结构

Mali 驱动定义的:

  struct mali_sync_timeline
  {
      struct sync_timeline timeline;
      atomic_t counter;
      atomic_t signalled;
  };
  struct mali_sync_pt
  {
      struct sync_pt pt;
      u32 order;
      s32 error;
  };

sw sync定义的:

  struct sw_sync_timeline {
      struct    sync_timeline    obj;
      u32            value;
  };
  struct sw_sync_pt {
      struct sync_pt        pt;
      u32            value;
  };

2.提供创建struct sync_timeline, struct sync_pt的接口

3.实现struct sync_timeline_ops定义的一些回调函数

sw_sync驱动实现了如下函数,它是创建sync_timeline所必需的:

static struct sync_timeline_ops sw_sync_timeline_ops = {
	.driver_name = "sw_sync",
	.dup = sw_sync_pt_dup,
	.has_signaled = sw_sync_pt_has_signaled,
	.compare = sw_sync_pt_compare,
	.fill_driver_data = sw_sync_fill_driver_data,
	.timeline_value_str = sw_sync_timeline_value_str,
	.pt_value_str = sw_sync_pt_value_str,
};

4.提供创建fence的接口

根据自身的设计,可能会提供如下两个IOCTL命令,注意区分上面提供的几个通用的IOCTL命令,以提供用户空间创建Fence的接口:

创建Fence的命令:

sw_sync中定义义了如下命令:

SW_SYNC_IOC_CREATE_FENCE

另外,sw_sync还有一个改变sync_timeline当前值的命令(每个驱动也都会提供类似的操作,根据自身的逻辑,实现方法不尽相同)

SW_SYNC_IOC_INC, 每当这个值变化时,会检查当前的值与位于sync_timeline中的syn_pt的值是否相等,以此来判断状态是否变为信号态。



您可能感兴趣的与本文相关内容

### 如何编译 Android 11 Framework 教程 #### 准备工作 为了成功编译 Android 11 的框架,需要准备合适的开发环境。这包括安装必要的工具链以及获取源码。 - **设置环境**:确保拥有 Linux 或 macOS 系统作为主机操作系统;Windows 用户建议通过 WSL (Windows Subsystem for Linux) 来构建。此外,还需下载并配置 Repo 工具用于管理多个 Git 仓库[^1]。 - **获取源代码**:访问 AOSP 官方网站按照指南初始化仓库,并拉取特定于 Android 11 版本的分支。命令如下所示: ```bash mkdir ~/android/src cd ~/android/src repo init -u https://android.googlesource.com/platform/manifest -b android-11.0.0_rXX # XX代表修订号 repo sync ``` #### 配置与定制化 完成上述准备工作之后,则可以针对目标硬件平台调整配置选项。对于大多数情况来说,默认配置已经足够满足需求,但对于某些特殊场景可能还需要额外修改 `build.prop` 文件或其他相关设置来适应具体机型的要求。 #### 编译流程 启动实际编译之前,请确认已正确设置了所需的环境变量(如 PATH)。接下来执行以下指令来进行整个系统的编译操作: ```bash source build/envsetup.sh lunch aosp_arm-eng # 根据实际情况选择适合的目标产品定义 make -j$(nproc --all) ``` 这里 `-j$(nproc --all)` 参数表示利用所有可用 CPU 核心加速编译速度。如果遇到任何错误提示,应该仔细阅读日志信息找出原因所在,并据此采取相应措施解决之。 #### 动态链接至Framework库 当涉及到应用程序级别的开发时,可能会碰到需要将 APK 应用程序同系统级的服务接口相连接的情形。此时可以通过 Gradle 构建脚本来实现这一点。例如,在项目的根目录下的 `build.gradle` 中加入下面这段话就足以让编译器知道去哪里寻找 framework.jar 进行静态或动态加载了: ```groovy gradle.projectsEvaluated { tasks.withType(JavaCompile) { options.compilerArgs << '-Xbootclasspath/p:' + rootProject.rootDir.absolutePath + '/path/to/framework.jar' } } ``` 注意替换 `/path/to/framework.jar` 成真实的路径位置[^2]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值