Hi, everyone, My name is Taowei Luo. I'm one of the students working for
GSoC this summer. My project is rewriting the vbox driver.
Before coding, I really need some discussions about how to implement it.
Here I post my first version of plan. I had show as much details as I
thought about in this plan. If anyone have ideas or suggestions about my
work, I would like to hear. My nick name in #virt IRC channel is uaedante
(or dante I used before). If I am offline in IRC, please contract me with
my email address uaedante(a)gmail.com.
Regards,
Taowei.
Plan to rewrite vbox driver
Introduction:
The existing vbox driver codes use vbox API directly. But the vbox API is
incompatible between different versions. To support all vbox API versions,
the vbox_tmpl.c file provides a template to implement all vbox drivers.
Each specified version of vbox driver includes the vbox_tmpl.c file, with
the definition in the corresponding head file, they work well. As the vbox
API defined in head files is conflict between different versions, even some
behavior of vbox APIs are changed. The vbox_tmpl.c contains lots of codes
such as “#if VBOX_API_VERSION < 4001000”. These codes is hard to manage or
adding new features.
Plan:
The core idea of my rewriting work is to add a middle layer to uniform the
API changes. This modification will not change any functions’ behavior or
sematic.
The middle layer has a global structure which contains API changes. Like
this:
struct vboxUniformedAPI {
A (*funcA)(A1 a, ….);
B (*funcB)(B1 a, ….);
}
If there is a code segment:
#if VBOX_API_VERSION < 4001000
adapter->vtbl->GetHostInterface(adapter, &hostIntUtf16);
#else /* VBOX_API_VERSION >= 4001000 */
adapter->vtbl->GetBridgedInterface(adapter, &hostIntUtf16);
#endif /* VBOX_API_VERSION >= 4001000 */
This will result to a variable in vboxUniformedAPI structure:
RetType (*GetInterface)(INetworkAdapter *a, PRUnichar *b)
When using the vbox under 4.1, this variable will points to a function that
calls GetHostInterface. When using the vbox later than 4.1 and the variable
will points to a function which calls GetBridgedInterface.
When replace these code segments with a single function, we need to do
living variable analyze and find out what is used and what is changed in
these codes. I plan to do these analyze manually.
All conflict in function prototype or function implementation will be fixed
up though this method.
When meeting a conflict in variable type, like:
#if VBOX_API_VERSION < 4001000
TypeA var;
#else /* VBOX_API_VERSION >= 4001000 */
TypeB var;
#endif /* VBOX_API_VERSION >= 4001000 */
I will add a union like this:
Union TypeC{
TypeA a;// used in some versions
TypeB b;// used in some other versions
}
If there is any operation using variables with such a union type (or
functions use it as an argument or return value), I will add a new function
in vboxUniformedAPI to handle this operation. These functions use TypeC as
parameter type, dispatch it depends on the vbox version and return TypeC
value to conceal type conflict.
We still have another kind of conflict. There are some versions have more
variables, operations or function calls than other versions. I will reserve
all variables even though they may not be used in some situation. And put
an empty function if they have nothing to do in the specified function
step. (I have a backup solution here. That is adding some flags to indicate
whether the procession is necessary in the API version and prevent upper
layer from calling a nonexistent function.)
Expected result:
After rewriting with the rules above, we will have a new vbox_tmpl.c. It
gathers version specified code and common code respectively. The common
codes use stable vbox API or functions in vboxUniformedAPI. A function
named InstallvboxUnifromedAPI will fill the vboxUniformedAPI structure
depends on the current vbox API version. In final step, I will put all vbox
APIs into the vboxUniformedAPI and make the vbox driver codes use my API
only. If this is done, the vbox driver will not be complied for each
version anymore.
Implementation:
First, define the vboxUniformedAPI structure in vbox_tmpl.c, and write the
InstallvboxUnifromedAPI function for every vbox API version.
Next, rewrite the functions which have conflict codes one by one. Each time
rewrite a new function, we can do some tests (here, I am not sure what kind
of tests is enough). When rewriting one function in vbox_tmpl.c, the others
will not change.
At this point, there will split version specified codes and common codes
But we still need to build the whole vbox_tmpl.c for each vbox API version.
If we want a single object file be generated by vbox_tmpl.c, we need to
prevent vbox_tmpl.c from calling vbox API directly. This could be done by
putting all of the vbox API calls into the middle vboxUniformedAPI layer,
and moving common codes into vbox_common.c. The vbox_common.c should only
use APIs in vboxUniformedAPI and will be complied only once.