目录
一 简介
二 基本原理
三 代码实现
3.1 Init
3.2 wait
3.3 signaling
3.4 callback
3.5 signaled
3.6 signal
3.7 refcount & release
四 Fence Status
一 简介
dma-fence是linux 内核中同步原语,它只有两种状态signaled和unsigned。因为其本身的精简,在融入其他概念中时,在不同的环境下,赋予了dma-fence不同的含义。所以通常需要根据dma-fence的具体使用的情况来理解其含义。
二 基本原理
一个被初始化的dma-fence,使用wait函数后,会将当前进程换出,即当前进程会sleep,而当调用signal函数时会唤醒被wait函数换出的进程。
dma-fence的使用还可以通过向dma-fence添加一个或多个callback函数,当dma-fence调用signal操作时,会依次遍历callback list,并调用每个callback函数。当调用wait函数时,会把默认的一个callback函数加入到dma-fence中,而这个函数就起到唤醒的作用。
三 代码实现
3.1 Init
dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
spinlock_t *lock, u64 context, u64 seqno)
传入参数:
dma_fence:fence这个软件同步原语(software synchronization primitive)的自身struct。
dma_fence_ops是fence回调函数,fence许多功能都是在此实现:
- use_64bit_seqno
- get_driver_name : fence所属驱动的名称
- get_timeline_name:fence所属上下文(进程)的名称,一般是task_struct-> comm
- enable_signaling:dma_fence_add_callback()和dma_fence_default_wait()调用。
- signaled:dma_fence_is_signaled()调用。
- wait:自定义实现dma_fence_wait(),否则就是用默认的dma_fence_default_wait().
- release:如果refcount等于0,会回调该函数,或者调用dma_fence_release()
- fence_value_str:用于调试,具体实现根据调试方式使用
- timeline_value_str:用字符串的形式填充时间线(timeline)
spinlock_t:自旋锁防止竞争
context:使用dma_fence_context_alloc分配一个序列号,这是整个OS管理。
seqno:一个顺序增长的数,是由驱动自身管理,用原子变量定义最好,防止竞争
作用:
初始化dma_fence中结构体成员,
实现:
有以下几个方面:
- 初始化refcount
- 挂载dma_fence_ops
- 初始化cb_list
- 初始化dma_fence ->spinlock
- 将dma_fence_context_alloc分配一个序列号赋值给context
- 将驱动自身管理的seqno赋值给dma_fence ->seqno
- fence->flags=0
- fence->error = 0
3.2 wait
dma_fence_wait(struct dma_fence *fence, bool intr)
传入参数:
intr:如果为true,请进行可中断的等待,false为不可中断的等待。
作用:
睡眠,直到fence被signaled或者超时
实现:
如果实现dma_fence_ops->wait则使用,否则使用dma_fence_default_wait(),
dma_fence_default_wait实现:
__dma_fence_enable_signaling(struct dma_fence *fence)
- 设置fence->flags为DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT
- 如果没有设置过第一步则进行dma_fence_ops->enable_signaling
- 第二步成功后执行dma_fence_signal_locked,设置DMA_FENCE_FLAG_SIGNALED_BIT,设置DMA_FENCE_FLAG_TIMESTAMP_BIT,执行cb_list中func
3.3 signaling
dma_fence_enable_sw_signaling(struct dma_fence *fence)
- 设置DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT
- 如果实现dma_fence_ops ->enable_signaling,则调用否则返回
- 如果dma_fence_ops ->enable_signaling调用失败会直接调用dma_fence_signal_locked函数signaled该fence。
3.4 callback
dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *cb,
dma_fence_func_t func)
__dma_fence_enable_signaling(struct dma_fence *fence)
- 设置fence->flags为DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT
- 如果没有设置过第一步则进行dma_fence_ops->enable_signaling
- 第二步成功后执行dma_fence_signal_locked,设置DMA_FENCE_FLAG_SIGNALED_BIT,设置DMA_FENCE_FLAG_TIMESTAMP_BIT,执行cb_list中func
- 把callback函数加入到callback list中。
3.5 signaled
dma_fence_is_signaled(struct dma_fence *fence)
作用:
查看fence是否被signaled,如果被signaled返回true,否则返回false。
实现:
- 如果实现dma_fence_ops -> signaled则调用dma_fence_ops -> signaled然后dma_fence_signal(),如果没有实现dma_fence_ops -> signaled则返回false。
3.6 signal
dma_fence_signal (struct dma_fence *fence)
作用:
完成一个fence,会调用callback list中每个callback函数
实现:
执行dma_fence_signal_locked,设置DMA_FENCE_FLAG_SIGNALED_BIT,设置DMA_FENCE_FLAG_TIMESTAMP_BIT,执行cb_list中func。
3.7 refcount & release
dma_fence_get(struct dma_fence *fence)
作用:
增加fence refcount,返回fence
dma_fence_put(struct dma_fence *fence)
作用:
减少fence refcount,返回fence,当refcount减少到0时将release fence。
实现:
- refcount减1
- 如果refcount等于0则调用dma_fence_release()
- dma_fence_release()
- 如果fence->flag= DMA_FENCE_FLAG_SIGNALED_BIT则需要signal该fence
- dma_fence_ops-> release实现则使用,否则使用dma_fence_free()释放该fence.
四 Fence Status
DMA_FENCE_FLAG_SIGNALED_BIT - fence is already signaled
DMA_FENCE_FLAG_TIMESTAMP_BIT - timestamp recorded for fence signaling
DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT - enable_signaling might have been called
DMA_FENCE_FLAG_USER_BITS - start of the unused bits, can be used by the implementer of the fence for its own purposes.
signaling fail原因是fence已经被signaled。fence有个特性是只能从signaling到signaled。