本文已参与 [新人创作礼] 活动,一起开启掘金创作之路。
目前我们的轨迹为:radeon_driver_load_kms --> radeon_device_init 。本篇来到: radeon_device_init --> radeon_gem_init。源码如下:
drivers/gpu/drm/radeon/radeon_gem.c
int radeon_gem_init(struct radeon_device *rdev)
{
INIT_LIST_HEAD(&rdev->gem.objects);
return 0;
}
终于看到一个短的函数了!那么我们就有篇幅展开一个相关知识——内核链表。
在Linux内核中,提供了一个用来创建双向循环链表的结构 list_head。虽然linux内核是用C语言写的,但是list_head的引入,使得内核数据结构也可以拥有面向对象的特性,通过使用操作list_head 的通用接口很容易实现代码的重用,有点类似于C++的继承机制。内核链表的相关代码在include/linux/list.h中,下面分别来看。
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
WRITE_ONCE(list->next, list);
list->prev = list;
}
struct list_head的定义在include/linux/types.h中
struct list_head {
struct list_head *next, *prev;
};
需要注意的一点是,头结点head是不使用的,这点需要注意。
使用list_head组织的链表的结构如下图所示:
介绍了内核链表的相关知识之后,回到radeon_gem_init函数中来。
INIT_LIST_HEAD(&rdev->gem.objects);
这一句代码中rdev是struct radeon_device的实例,struct radeon_device结构体中(参见linux内核radeon gpu源码解析6)的有一个gem成员:
struct radeon_gem gem;
其定义为:
drivers/gpu/drm/radeon/radeon.h
struct radeon_gem {
struct mutex mutex;
struct list_head objects;
};
这样函数的作用就很明确了,初始化内核链表rdev->gem.objects。