Nouveau源码分析(二)
在讨论Nouveau对Nvidia设备的初始化前,我准备先说一下Nouveau结构体的基本框架
Nouveau的很多结构体都可以看作是C++中的类,之间有很多相似的东西,比如继承关系,virtual成员函数等.
模拟继承
先尝试阅读一下这个代码:
- #include <stdlib.h>
-
- struct abc
- {
- int a;
- int b;
- int c;
- };
-
- struct def
- {
- struct abc base;
- int d;
- int e;
- int f;
- };
-
- #define abc_create(a,b,c,pabc) \
- abc_create_(a,b,c,sizeof(**pabc),(void **)pabc)
-
- int abc_create_(int a,int b,int c,
- size_t size,void **pabc)
- {
- struct abc *abc_ = (struct abc *)malloc(size);
-
- abc_->a = a;
- abc_->b = b;
- abc_->c = c;
-
- *pabc = abc_;
- return 0;
- }
-
- #define def_create(a,b,c,d,e,f,pdef) \
- def_create_(a,b,c,d,e,f,sizeof(**pdef),(void **)pdef)
-
- int def_create_(int a,int b,int c,int d,int e,int f,
- size_t size,void **pdef)
- {
- struct def *def_;
- abc_create_(a,b,c,size,pdef);
- def_ = (struct def *)*pdef;
-
- def_->d = d;
- def_->e = e;
- def_->f = f;
- return 0;
- }
-
- int main(void)
- {
- struct def *d;
- def_create(1,2,3,4,5,6,&d);
- return 0;
- }
Nouveau中大部分的结构体都是这种模式的,模拟C++的继承关系
当然一般还会有配套使用的宏,比如这个例子中可以有:
- #define nv_abc(a) ((struct abc *)a)
-
-
-
- struct def *b;
-
- nv_abc(b)->a = 7;
[注意:实际在nouveau代码中,还有一种关系是parent关系,这和此处讨论的继承关系无关]
模拟virtual函数
改造一下上面写的程序,改成这样:
- #include <stdlib.h>
- #include <stdio.h>
-
- struct oclass
- {
- int (*test)(int);
- };
-
-
- struct abc
- {
- struct oclass *oclass;
- int a;
- int b;
- int c;
- };
-
- int abc_test(int a)
- {
- return a * a;
- }
-
- struct oclass abc_oclass = {abc_test};
-
- #define nv_abc(a) ((struct abc *)a)
-
- #define abc_create(a,b,c,pabc) \
- abc_create_(&abc_oclass, \
- a,b,c,sizeof(**pabc),(void **)pabc)
-
- int abc_create_(struct oclass *oclass,int a,int b,int c,
- size_t size,void **pabc)
- {
- struct abc *abc_ = (struct abc *)malloc(size);
-
- abc_->a = a;
- abc_->b = b;
- abc_->c = c;
- abc_->oclass = oclass;
-
- *pabc = abc_;
- return 0;
- }
-
-
- struct def
- {
- struct abc base;
- int d;
- int e;
- int f;
- };
-
-
- int def_test(int a)
- {
- return a;
- }
-
- struct oclass def_oclass = {def_test};
-
- #define nv_def(a) ((struct def *)a)
-
- #define def_create(a,b,c,d,e,f,pdef) \
- def_create_(a,b,c,d,e,f,sizeof(**pdef),(void **)pdef)
-
- int def_create_(int a,int b,int c,int d,int e,int f,
- size_t size,void **pdef)
- {
- struct def *def_;
- abc_create_(&def_oclass,a,b,c,size,pdef);
- def_ = (struct def *)*pdef;
-
- def_->d = d;
- def_->e = e;
- def_->f = f;
- return 0;
- }
-
- int main(void)
- {
- struct def *d;
- struct abc *a;
- def_create(1,2,3,4,5,6,&d);
- abc_create(1,2,3,&a);
-
- printf("%d %d\n",nv_abc(d)->oclass->test(3),
- nv_abc(a)->oclass->test(3));
- return 0;
- }
利用这个,就可以用同一个接口nouveau_object,实现对很多不同设备模块的访问
使用标识符获得oclass
还有一种情况,传递参数时传递的是"u32 oclass",而不是"struct nouveau_oclass *oclass",这种情况就要依照parent向上搜索,得到具体的oclass
此处不展开讨论,等看到那部分代码再详细说明