linux任务响应模型&linux实时化&RTAI 3.2分析&Adeos分析(8)
- UID
- 1029342
- 性别
- 男
|
linux任务响应模型&linux实时化&RTAI 3.2分析&Adeos分析(8)
dswitch是一个函数指针,指向一个钩子函数,这个函数在域的切换过程中被调用;esp[ADEOS_NR_CPUS]是一个指针数组,域在不同的CPU上运行的时候有不同的栈,而esp则用来在域切换之前保存当前栈的位置;estackbase[ADEOS_NR_CPUS]则保存着每个栈的栈底;domid是域的识别号,这个值对每个域都是唯一的;name则是域的名字;priority表示域的优先级,也就是域在中断管道中的优先级;cpudata和irqs都与中断处理有关,在后面分析Adeos的中断处理的时候再详细讨论;events保存着域的事件处理程序;所有以ptd_开头的字段,都和所谓的Per-thread datakey有关;m_link是一个指向域的指针,用于域睡眠时加入等待队列;p_link则是用于中断管道的连接。
------------------------
3.2.3 Adeos初始化
Adeos的初始化是在Linux的初始化过程中调用的,是由函数start_kernel来调用,初始化函数为__adeos_init();这个函数的定义在文件kernel/adeos.c中,它完成的主要工作如下:
初始化根域adeos_root_domain;
分配一个虚拟中断__adeos_printk_virq,主要用来完成其它域对根域请求的printk内核输出操作;
Adeos接管Linux的中断管理机制,这是通过调用__adeos_takeover()实现的;
__adeos_takeover()仅仅调用__adeos_enable_pipeline()来完成中断的接管操作;__adeos_enable_pipeline()定义在adeos/armv.c中,它的主要功能如下:
1.调用函数adeos_virtualize_irq指定所有根域中断的中断处理函数和中断确认函数;
2.将Linux原来的中断描述符保存在数组__adeos_std_irq_desc[]中;
3.用Adeos相关的中断屏蔽、中断响应等函数替换原有Linux的相应函数;
4.将标志变量adp_pipelined置为1;
至此,Adeos的初始化就已经完成;初始化完成后,系统中存在着一个域,那就是根域(root domain),这时Linux的中断管理机制已经由Adeos来管理。
----------------
3.2.4 域注册
Adeos系统中,除了根域(root domain)是在Adeos初始化过程中被静态创建的之外,其它的所谓的客户域(clientdomain),在使用Adeos提供的服务之前,都必须通过域注册函数int adeos_register_domain (adomain_t*adp, adattr_t*attr)先进行注册。参数adp指向将要被注册的域实体结构变量,参数attr则指向一个域属性结构变量,注册函数将根据attr中的属性对adp进行初始化;域注册函数完成的功能如下:
1.检查当前域是否是根域(Linux),只有根域才可以注册其它的域,因为在目前的Adeos实现下,其它的域都要以Linux下内核动态模块的形式存在;
2.遍历所有的域,检查当前需要注册的域是否已经存在(根据域标志domid来判断),如果已经存在,则出错返回;
3.对域结构变量内的字段进行初始化;通过__adeos_init_domain()函数对域的栈进行初始化,并给栈赋初值,为域的首次运行做好准备;
4.查找中断管道的域列表,根据域的优先级找到新域在中断管道中的位置;并将新域插入中断管道;
5.调用__adeos_switch_to()函数切换到新域;
在attr所指的域属性结构中,有一个字段attr->entry,它是一个函数指针,它指向域自己定义的初始化函数,这个函数地址在初始化域的程序栈的时候被保存在了栈中,当域第一次执行的时候,将会从栈中取出这个初始化函数的地址,执行域自己定义的初始化。
----------------------------
3.2.5 Adeos中断处理
Adeos中断处理函数的入口是asmlinkage int __adeos_handle_irq (int irq, structpt_regs*regs),它的定义在arch/arm/kernel/adeos.c中;这个函数既用来处理硬件中断,也用来处理软件中断(这里所说的软件中断是由域触发,用于域之间的通信);所以,这个函数在两个地方被调用。
第一个,是在系统的中断处理入口,在基于ARM的平台中,中断处理入口都在文件arch/arm/kernel/entry-armv.S中,Adeos用这个函数替换了Linux原来的中断处理函数do_IRQ(),例如,USER MODE模式下中断处理代码片断如下:
__irq_usr: sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ save r0 - r12
ldr r4, .LCirq
add r8, sp, #S_PC
ldmia r4, {r5 - r7} @ get saved PC, SPSR
stmia r8, {r5 - r7} @ save pc, psr, old_r0
stmdb r8, {sp, lr}^
alignment_trap r4, r7, __temp_irq
zero_fp
1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
adrsvc ne, lr, 1b
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
#ifdef CONFIG_ADEOS_CORE
bne __adeos_handle_irq
#else /* !CONFIG_ADEOS_CORE */
bne do_IRQ
#endif /* CONFIG_ADEOS_CORE */
mov why, #0
get_current_task tsk
b ret_to_user
第二个,是在函数adeos_trigger_irq中被调用,当某个域想要触发某个软件中断时,就可以调用软件中断触发函数adeos_trigger_irq产生一个软件中断,这个软件中断就会沿着中断管道传播,触发其它域执行相应的处理函数,这样就可以达到域之间通信的目的。
Adeos中断处理函数__adeos_handle_irq完成的功能如下:
1.判断标志变量adp_pipelined的值,如果为零,则说明中断管道现在不可用,则调用Linux的中断处理入口函数do_IRQ来进行中断处理;
2.依次遍历中断管道,如果域接受相应的中断,则将此中断记录在域的中断日志中,包括记录中断类型和中断次数,然后调用中断应答函数;
3.调用函数__adeos_walk_pipeline,沿着中断管道执行域的中断处理函数,在执行完域的中断处理函数后,Adeos会切换到这个域,也就是将CPU的控制权交给这个域,当这个域执行完所有的操作后,域就主动挂起,控制权交回Adeos,Adeos在执行中断管道中随后的域的中断处理程序并根据需要交换控制权,直到所有的域都执行完。
每个域与中断相关的数据主要存放在域结构变量的两个字段中,分别是cpudata和irqs,它们的定义如下: |
|
|
|
|
|