线程模型
CAmkES 组件通常是多线程的,为了防止出现争用情况,通常需要了解系统中存在哪些线程。首先,有一个活动线程。这是一个控制线程,它调用已声明的组件的组件入口点。此线程甚至存在于非控制组件中,以便执行初始化操作。
组件与之交互的每个接口(无论是传入接口还是传出接口)都会在组件中引发另一个线程。这些线程及其各种设置活动的初始同步都由生成的代码处理。请注意,即使对于您可能认为是被动的接口,此每个接口线程也存在。例如,数据端口。这只是一个实现工件,将来可能会更改。
线程优先级
CAmkES 系统中的每个线程都有一个优先级,该优先级决定了 seL4 如何调度它。这些优先级默认为命令行参数提供给运行器的值。数字越大,线程的优先级越高,即优先级为 100 的线程将在优先级为 90 的线程之前执行。
在给定的系统中,可以使用具有特定语义的属性调整特定线程的优先级。要调整控制线程的优先级,请使用以下属性:
assembly {
composition {
component Foo f;
...
}
configuration {
f._priority = 100;
}
}
要调整接口线程的优先级,请使用以接口名称和后缀“_priority”命名的属性:
component Foo {
uses MyInterface i;
}
assembly {
composition {
component Foo f;
...
}
configuration {
f.i_priority = 100;
}
}
如果要调整给定组件实例中每个线程的优先级,可以使用常规组件属性:
configuration {
f.priority = 100;
}
线程 CPU 关联
AmkES 系统中的每个线程也具有处理器关联。默认情况下,此关联会将所有线程绑定到 CPU 索引 0(引导处理器)。
component Mycomponent {
/* ... */
uses Myinterface i;
}
assembly {
composition {
component Mycomponent c;
}
configuration {
/* Run all threads in "c" on CPU 1 */
c.affinity = 1;
}
}
线程堆栈
每个 CAmkES 线程都有一个供其使用的堆栈。堆栈大小默认为 4K,但可以通过相关的生成系统配置选项调整此默认值。此外,可以使用属性设置组件中各个线程的堆栈:
configuration {
// Assign foo's control thread an 8K stack
foo._stack_size = 8192;
// Assign the interface thread for inf in foo a 16K stack
foo.inf_stack_size = 16384;
}
请注意,堆栈的大小必须为 4K 对齐,因此,如果为线程分配的堆栈大小未与 4K 对齐,则该堆栈大小将被向上舍入。
调度域
在 CAmkES 中,可以通过设置属性来指定每个线程所属的域。每个组件实例的每个接口都有一个关联的线程,并且每个组件将有一个附加线程来执行初始化,并选择性地充当控制线程。对于接口线程,可以通过设置实例的属性来指定其域。对于控制线程,可以设置实例的属性。
component Foo {
control;
uses iface i;
}
component Bar {
provides iface o;
}
assembly {
composition {
component Foo f;
component Bar b;
connection seL4RPCCall c(from f.i, to b.o);
...
}
configuration {
f._domain = 0; // domain of control thread of f
b.o_domain = 1; // domain of o interface of b
...
}
}