Android HardwareComposer中的fence机制中讨论了hwc中的fence,hwc最终把layer的acqireFenceFd送进fb driver,再由fb drvier生成新的reitreFenceFd并return回user space.本篇文章我们来探讨下fb driver中的fence,看看S3CFB_WIN_CONFIG ioctl都做了些什么.
kernel代码下载地址: https://android.googlesource.com/kernel/exynos.git
文章中用到的code:
exynos/include/linux/sync.h
exynos/drivers/base/sync.c
exynos/include/linux/sw_sync.h
exynos/drivers/base/sw_sync.c
exynos/drivers/video/s3c-fb.c
在讨论fb driver中的fence之前,先来简单介绍几个和fence相关的基本数据结构:
/**
* struct sync_timeline - sync object
* @kref: reference count on fence.
* @ops: ops that define the implementaiton of the sync_timeline
* @name: name of the sync_timeline. Useful for debugging
* @destoryed: set when sync_timeline is destroyed
* @child_list_head: list of children sync_pts for this sync_timeline
* @child_list_lock: lock protecting @child_list_head, destroyed, and
* sync_pt.status
* @active_list_head: list of active (unsignaled/errored) sync_pts
* @sync_timeline_list: membership in global sync_timeline_list
*/
struct sync_timeline {
struct kref kref;
const struct sync_timeline_ops *ops;
char name[32];
/* protected by child_list_lock */
bool destroyed;
struct list_head child_list_head;
spinlock_t child_list_lock;
struct list_head active_list_head;
spinlock_t active_list_lock;
struct list_head sync_timeline_list;
};
sync_timeline中包含一个由list_head串起来的sync_pt双向链表child_list_head.
/**
* struct sync_pt - sync point
* @parent: sync_timeline to which this sync_pt belongs
* @child_list: membership in sync_timeline.child_list_head
* @active_list: membership in sync_timeline.active_list_head
* @signaled_list: membership in temorary signaled_list on stack
* @fence: sync_fence to which the sync_pt belongs
* @pt_list: membership in sync_fence.pt_list_head
* @status: 1: signaled, 0:active, <0: error
* @timestamp: time which sync_pt status transitioned from active to
* singaled or error.
*/
struct sync_pt {
struct sync_timeline *parent;
struct list_head child_list;
struct list_head active_list;
struct list_head signaled_list;
struct sync_fence *fence;
struct list_head pt_list;
/* protected by parent->active_list_lock */
int status;
ktime_t timestamp;
};
sync_pt中parent指针指向了sync_pt所属的sync_timeline,child_list表示了sync_pt在sync_timeline.child_list_head中的位置.fence指针指向了sync_pt所属的fence,pt_list表示了sync_pt在fence.pt_list_head中的位置.
/**
* struct sync_fence - sync fence
* @file: file representing this fence
* @kref: referenace count on fence.
* @name: name of sync_fence. Useful for debugging
* @pt_list_head: list of sync_pts in ths fence. immutable once fence
* is created
* @waiter_list_head: list of asynchronous waiters on this fence
* @waiter_list_lock: lock protecting @waiter_list_head and @status
* @status: 1: signaled, 0:active, <0: error
*
* @wq: wait queue for fence signaling
* @sync_fence_list: membership in global fence list
*/
struct sync_fence {
struct file *file;
struct kref kref;
char name[32];
/* this list is immutable once the fence is created */
struct list_head pt_list_head;
struct list_head waiter_list_head;
spinlock_t waiter_list_lock; /* also protects status */
int status;
wait_queue_head_t wq;
struct list_head sync_fence_list;
};
file指针表示fence所对应的file,linux中一切皆是file.pt_list_head是一个由list_head串起来的sync_pt双向链表.
sync_timeline,sync_pt和sync_fence的关系可以用下面的图来表示:
syc_timeline来管理所有在这条timeline上的sync_pt,可以决定sync_pt何时被signal.sync_fence中可以包含一个或者多个sync_pt,当sync_fence中所有的sync_pt被signal的时候,sync_fence被signal.
不过sync_timeline sync_pt有点像一个virtual class,真正在使用的时候需要"继承"它,并实现它定义的sync_timeline_ops *ops接口,s3c-fb.c 使用的是sw_sync_timeline和sw_sync_pt,定义如下:
struct sw_sync_timeline {
struct sync_timeline obj;
u32 value;
};
struct sw_sync_pt {
struct sync_pt pt;
u32 value;
};
sw_sync_timeline和sw_sync_pt相当简单,只不过是在原本的sync_timeline和sync_pt基础上多加了一个u32的value而已.另外sw_sync_timeline和sync_pt还开出了几个新的api.
struct sw_sync_timeline *sw_sync_timeline_create(const char *name);
void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc);
struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value);
上面这三个api在s3c-fb.c 中都会用到,我们在分析到对应code的时候再来深入分析.
接下来我们进入s3c-fb.c,具体看下sw_sync_timeline,sw_sync_pt和sync_fence是如何使用的.首先,s3c-fb定义了一些和处理fence相关的member
struct s3c_fb {
...
struct fb_info *fbinfo;
struct list_head updat