5.4.3 场景2之运行在Head域Xenomai线程调用Linux系统调用getpid

点击查看《Xenomai/IPIPE源代码情景解析》
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

5.4.3 场景2之运行在Head域Xenomai线程调用Linux系统调用getpid

参考《5.2.2 用户层:用latency演示Xenomai系统调用》,latency 是 Xenomai/Cobalt 实时内核提供的一个工具,用于测量系统的实时性能,特别是上下文切换和中断响应的延迟。它启动后,会新建一个display线程用于打印信息;会新建一个sampling线程用于延迟采样。
通过条件断点,在ipipe_handle_syscall第1200行处,抓到Xenomai实时线程运行在head域时,对Linux系统调用getpid的调用。

  • 第一步,ipipe_handle_syscall
  • 第二步,__ipipe_notify_syscall
  • 第三步,handle_head_syscall
  • 第四步,返回KEVENT_PROPAGATE到__ipipe_notify_syscall第1232行
  • 第五步,handle_root_syscall函数
  • 第六步,返回KEVENT_PROPAGATE(0)到__ipipe_notify_syscall第1232行
  • 第七步,KEVENT_PROPAGATE(0)到ipipe_handle_syscall第1200行
  • 第八步,返回0到el0_svc_common第110行

接下来对每一步进行分解:

  • 第一步,ipipe_handle_syscall

在这里插入图片描述
第1199行,条件1(local_flags & _TIP_NOTIFY)成立,因为local_flags即ti->ipipe_flags值为6(_TIP_HEAD | _TIP_NOTIFY)。参考《5.3.2 ipipe_flags之TIP_HEAD》,_TIP_HEAD代表线程当前运行在head domain。参考《5.3.3 ipipe_flags之TIP_NOTIFY》,只要是绑定到xenomai core的进程或线程,一定有TIP_NOTIFY标记!条件2(nr >= nr_syscalls)不成立,因为nr是172,小于Linux自身的系统调用数量nr_syscalls(294)。条件1和条件2是逻辑或的关系,所以第1199行的if判断成立,走到第1200行慢速路径__ipipe_notify_syscall。
第1200行,走到慢速路径__ipipe_notify_syscall

  • 第二步,__ipipe_notify_syscall
    在这里插入图片描述
    第1224行,通过__ipipe_current_domain获取当前所在的domain,存入变量caller_domain和this domain。从左上角的locals变量的值能够确认,当前所在domain是head domain。
    第1225行,设置变量ipd为ipipe_head_domain即head domain。
    第1226行,此处定义了标签next:,在不同的场景下可能会通过goto next跳转过来,形成循环。
    第1227行,通过ipd(head domain)获取当前cpu对应的struct ipipe_percpu_domain_data head指针,存入p。
    第1228行,参考《5.3.3 ipipe_flags之TIP_NOTIFY》,此处判断必然成立。
    第1229行,设置当前cpu的上下文struct ipipe_percpu_data中的curr指向存在p中保存的ipipe_percpu_domain_data head指针。
    第1232行,调用ipipe_syscall_hook。在ipipe_syscall_hook中,如果判断当前是secondary domain(即root domain)则调用handle_root_syscall。而因为在__ipipe_notify_syscall的第1229行已经把当前domain设置为head domain,所以ipipe_syscall_hook最终会调用handle_head_syscall。
int ipipe_syscall_hook(struct ipipe_domain *ipd, struct pt_regs *regs)
{
	if (unlikely(is_secondary_domain()))
		return handle_root_syscall(regs);

	return handle_head_syscall(ipd != &xnsched_primary_domain, regs);
}
  • 第三步,handle_head_syscall

handle_head_syscall函数比较长,分成两个部分来解释
(1)handle_head_syscall第494~495行
在这里插入图片描述
第494行,使用__xn_syscall_p判断系统调用号是否为Xenomai系统调用号。原理参考《5.2.3 内核层:Xenomai系统调用的流程》。当前是Linux系统调用,跳转到495行。
第495行,goto linux_syscall跳转到第647行linux_syscall标签出。

(2)handle_head_syscall第647~679行
在这里插入图片描述

第648行,xnsched_root_p 是一个内联函数,用于检查当前线程是否处于 root domain(即 Linux 非实时调度域)。该函数通过调用 xnthread_test_state 来测试当前线程的状态标志位 XNROOT,从而判断线程是否运行在 root domain。当前场景下,task_struct中的ipipe_flags有TIP_HEAD标记,肯定是运行在head domain,此处判断不成立,继续向下执行。
第669行,调用xnthread_relax(1, SIGDEBUG_MIGRATE_SYSCALL); 用于将当前线程从 head domain 切换到 root domain。参数 1表示线程需要立即切换,而不是等待调度机会。参数 SIGDEBUG_MIGRATE_SYSCALL是一个调试信号,用于在调试时跟踪线程的切换行为。
第671行,返回KEVENT_PROPAGATE(0)到第二步中的__ipipe_notify_syscall第1232行。

  • 第四步,返回KEVENT_PROPAGATE到__ipipe_notify_syscall第1232行

在这里插入图片描述
第1232行,ipipe_syscall_hook返回KEVENT_PROPAGATE(0)。
第1235行,因为在第1232行ipipe_syscall_hook执行过程中,从head domain切换到root domain,所以第1235行条件成立,跳转到第1237行。
第1237行,设置this_domain为当前domain即root domain。
第1242行,根据1237行,判断条件成立,走到第1243行。
第1243行,条件1(ipd != ipipe_root_domain)成立;条件2(ret == 0)成立,因为ipipe_syscall_hook返回KEVENT_PROPAGATE(0)。所以跳转到第1244行。
第1244~1245行,设置ipd为root domain,通过goto next跳转到第1226行。
第1229行,设置当前domain为root domain。
第1232行,进入ipipe_syscall_hook之后,因为当前domain为root domain,所以指向handle_root_syscall函数。

  • 第五步,handle_root_syscall函数
    在这里插入图片描述
    第699行,使用__xn_syscall_p判断系统调用号是否为Xenomai系统调用号。原理参考《5.2.3 内核层:Xenomai系统调用的流程》。当前是Linux系统调用,跳转到701行。
    第701行,返回KEVENT_PROPAGATE(0)到__ipipe_notify_syscall第1232行。

  • 第六步,返回KEVENT_PROPAGATE(0)到__ipipe_notify_syscall第1232行
    在这里插入图片描述
    第1232行,ipipe_syscall_hook返回KEVENT_PROPAGATE(0)。
    第1242行,根据1239行,判断条件成立,走到第1243行。
    第1243行,条件1(ipd != ipipe_root_domain)不成立;条件2(ret == 0)成立,因为ipipe_syscall_hook返回KEVENT_PROPAGATE(0)。所以不可能走到1245行执行goto next,至此next/go next循环结束。
    第1259行,KEVENT_PROPAGATE(0)到ipipe_handle_syscall第1200行。

  • 第七步,KEVENT_PROPAGATE(0)到ipipe_handle_syscall第1200行
    在这里插入图片描述
    第1202行,重新读取ti->ipipe_flags,因为已经切换到root domain,所以其中_TIP_HEAD标记已经没有了,此处判断不成立了!
    第1204行,因为ret等于KEVENT_PROPAGATE(0),所以跳转到第1208行,返回0到el0_svc_common第110行。

  • 第八步,返回0到el0_svc_common第110行

在这里插入图片描述
第110行,从ipipe_handle_syscall返回0.
第131行,通过invoke_syscall调用Linux原生系统调用gitpid的系统调用函数__arm64_sys_gitpid! 具体参考《5.1.2 内核层:ARM64 Linux系统调用的流程》。
至此,完成了此场景的分析!


点击查看《Xenomai/IPIPE源代码情景解析》
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值