sigwaittest测试超标的调试过程
1,问题描述
硬件环境:飞腾S2500(64核)
OS:kylinOS, linux preempt rt, 4.19.90
测试命令:sigwaittest -p 90 -i 1000 -a 1
测试结果:信号混洗值最大超过了80us,与飞腾其他CPU的设备相比较,增大了很多
2,调试过程
1)日志分析
使用trace-cmd命令来抓取ftrace log:trace-cmd start -e all; sigwaittest -p 90 -i 1000 -a 1 -b 80
得到如下日志:
sigwaitt-13091 1....0 1741.963614: sys_enter: NR 131 (3321, 3322, a, 20c49ba5e353f7cf, 3b9ac9ff, 44cc0)
sigwaitt-13091 1...10 1741.963615: sys_enter_tgkill: tgid: 0x00003321, pid: 0x00003322, sig: 0x0000000a
sigwaitt-13091 1d..11 1741.963616: sched_waking: comm=sigwaittest pid=13090 prio=9 target_cpu=001
sigwaitt-13091 1d..21 1741.963617: sched_wakeup: sigwaittest:13090 [9] success=1 CPU:001
sigwaitt-13091 1....1 1741.963618: signal_generate: sig=10 errno=0 code=-6 comm=sigwaittest pid=13090 grp=0 res=0
=====chensong:70us
sigwaitt-13091 1d..21 1741.963689: sched_waking: comm=sigwaittest pid=13089 prio=120 target_cpu=041
sigwaitt-13091 1d..31 1741.963690: sched_wakeup: sigwaittest:13089 [120] success=1 CPU:041
=====
sigwaitt-13091 1....0 1741.963691: kfree: (__audit_syscall_exit+0x1d8) call_site=ffff0000081d26b0 ptr=(nil)
sigwaitt-13091 1....0 1741.963691: sys_exit: NR 131 = 0
sigwaitt-13091 1...10 1741.963692: sys_exit_tgkill: 0x0对比正常时候的日志:
sigwaitt-13091 1....0 1741.962569: sys_enter: NR 131 (3321, 3322, a, 20c49ba5e353f7cf, 3b9ac9ff, 44cc0)
sigwaitt-13091 1...10 1741.962570: sys_enter_tgkill: tgid: 0x00003321, pid: 0x00003322, sig: 0x0000000a
sigwaitt-13091 1d..11 1741.962571: sched_waking: comm=sigwaittest pid=13090 prio=9 target_cpu=001
sigwaitt-13091 1d..21 1741.962572: sched_wakeup: sigwaittest:13090 [9] success=1 CPU:001
sigwaitt-13091 1....1 1741.962573: signal_generate: sig=10 errno=0 code=-6 comm=sigwaittest pid=13090 grp=0 res=0
sigwaitt-13091 1....0 1741.962574: kfree: (__audit_syscall_exit+0x1d8) call_site=ffff0000081d26b0 ptr=(nil)
sigwaitt-13091 1....0 1741.962574: sys_exit: NR 131 = 0
sigwaitt-13091 1...10 1741.962574: sys_exit_tgkill: 0x0
sigwaitt-13091 1....0 1741.962575: sys_enter: NR 137 (fffdf677e848, fffdf677e6b8, 0, 8, 0, fffdf677f0e0)
sigwaitt-13091 1...10 1741.962575: sys_enter_rt_sigtimedwait: uthese: 0xfffdf677e848, uinfo: 0xfffdf677e6b8, uts: 0x00000000, sigsetsize: 0x00000008
sigwaitt-13091 1d..10 1741.962576: rcu_utilization: Start context switch
sigwaitt-13091 1d..10 1741.962577: rcu_utilization: End context switch
sigwaitt-13091 1d..20 1741.962578: sched_switch: sigwaittest:13091 [9] S ==> sigwaittest:13090 [9]我们会发现,在signal_generate后,sigwaittest的测试线程又唤醒了一个线程,消耗了70us。
2)过程分析
命令“sigwaittest -p 90 -i 1000 -a 1 -b 80”会创建三个线程,一个主线程main thread,,是一个CFS的普通线程,很大一部分工作是打印测试的结果,一个是sender,是一个实时线程,负责发送信号,还有一个是receiver,负责接收信号,sigwaittest主要就是测试sender发送信号到receiver接收到信号所花费的时间。
3)代码分析
首先看一下发送信号的kill函数,对应内核中系统调用tgkill:
使用function_grath来看一下tgkill的调用过程:trace-cmd start -p function_graph -g sys_tgkill;sigwaittest -p 90 -i 1000 -a 1 -l 100;trace-cmd stop
# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |1) | sys_tgkill() {1) | do_tkill() {1) | __task_pid_nr_ns() {1) 0.770 us | __rcu_read_lock();1) 0.500 us | __rcu_read_unlock();1) 3.062 us | }1) | from_kuid_munged() {1) 0.500 us | map_id_up();1) 1.563 us | }1) | do_send_specific() {1) 0.479 us | __rcu_read_lock();1) 0.666 us | find_task_by_vpid();1) | __task_pid_nr_ns() {1) 0.500 us | __rcu_read_lock();1) 0.479 us | __rcu_read_unlock();1) 2.542 us | }1) | check_kill_permission() {1) | audit_signal_info() {1) | auditd_test_task() {1) 0.500 us | __rcu_read_lock();1) 0.479 us | __rcu_read_unlock();1) 2.604 us | }1) | audit_signal_info_syscall() {1) 0.500 us | __rcu_read_lock();1) 0.500 us | __rcu_read_unlock();1) 2.458 us | }1) 7.042 us | }1) 0.604 us | security_task_kill();1) 9.271 us | }1) | do_send_sig_info() {1) | __lock_task_sighand() {1) 0.500 us | __rcu_read_lock();1) | rt_spin_lock() {1) 0.500 us | __rcu_read_lock();1) 0.500 us | migrate_disable();1) 2.480 us | }1) 0.500 us | __rcu_read_unlock();1) 5.459 us | }1) | send_signal() {1) 0.563 us | siginfo_layout();1) 0.479 us | __rcu_read_lock();1) 0.500 us | __rcu_read_lock();1) 0.500 us | __rcu_read_unlock();1) 0.500 us | __rcu_read_unlock();1) 0.563 us | task_active_pid_ns();1) | __task_pid_nr_ns() {1) 0.500 us | __rcu_read_lock();1) 0.480 us | __rcu_read_unlock();1) 2.479 us | }1) | __send_signal() {1) 0.583 us | prepare_signal();1) | __sigqueue_do_alloc() {1) 0.563 us | __rcu_read_lock();1) 0.480 us | __rcu_read_unlock();1) | kmem_cache_alloc() {1) 0.479 us | should_failslab();1) 1.708 us | }1) 4.833 us | }1) | complete_signal() {1) 0.604 us | _raw_spin_lock_irqsave();1) 0.500 us | _raw_spin_unlock_irqrestore();1) | signal_wake_up_state() {1) | wake_up_state() {1) | try_to_wake_up() {1) 0.562 us | _raw_spin_lock_irqsave();1) 0.542 us | _raw_spin_lock();1) 0.541 us | update_rq_clock();1) | ttwu_do_activate() {1) | activate_task() {1) | enqueue_task_rt() {1) | dequeue_rt_stack() {1) 0.521 us | dequeue_top_rt_rq();1) 1.521 us | }1) 0.500 us | update_rt_migration();1) 0.500 us | _raw_spin_lock();1) 0.521 us | enqueue_top_rt_rq();1) 5.604 us | }1) 6.958 us | }1) | ttwu_do_wakeup() {1) | check_preempt_curr() {1) 0.625 us | check_preempt_curr_rt();1) 1.625 us | }1) 0.521 us | task_woken_rt();1) 4.605 us | }1) + 13.084 us | }1) 0.541 us | _raw_spin_unlock_irqrestore();1) + 19.104 us | }1) + 20.146 us | }1) + 21.188 us | }1) + 24.542 us | }1) + 32.709 us | }1) + 42.792 us | }1) | rt_spin_unlock() {1) 0.563 us | migrate_enable();1) 0.521 us | __rcu_read_unlock();1) 2.750 us | }1) + 53.271 us | }1) 0.541 us | __rcu_read_unlock();1) + 70.500 us | }1) + 77.562 us | }1) + 81.333 us | }------------------------------------------1) sigwait-31931 => sigwait-31930 ------------------------------------------简化一下调用过程就是:
tgkill--> do_tkill-->do_send_specific-->do_send_sig_info--> lock_task_sighand //申请锁tsk->sighand->siglocksend_signal //唤醒receiverunlock_task_sighand(p, &flags); //释放tsk->sighand->siglock在通常情况下,sender调用send_signal唤醒receiver,这个过程就结束了。但在发生错误的日志中,我们发现sender还唤醒了main thread,那么,很可能main thread也在申请tsk->sighand->siglock,这个时候它正在siglock的等待队列中等待,那么,当sender调用unlock_task_sighand的时候,就会去唤醒main thread。
我们再来看看main thread的代码:
26 while (!mustshutdown) {
527 int printed;
528 int errorlines = 0;
529
530 for (i = 0; i < num_threads; i++)
531 mustshutdown |= receiver[i].shutdown |
532 sender[i].shutdown;
533
534 if (receiver[0].samples > oldsamples || mustshutdown) {...//打印结果581 pthread_sigmask(SIG_SETMASK, &sigset, NULL);
582
583 nanosleep(&maindelay, NULL);
584
585 sigemptyset(&sigset);
586 pthread_sigmask(SIG_SETMASK, &sigset, NULL);}其中pthread_sigmask(SIG_SETMASK, &sigset, NULL)会进入内核调用:
2870 int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
2871 {
2872 struct task_struct *tsk = current;
2873 sigset_t newset;
2874
2875 /* Lockless, only current can change ->blocked, never from irq */
2876 if (oldset)
2877 *oldset = tsk->blocked;
2878
2879 switch (how) {
2880 case SIG_BLOCK:
2881 sigorsets(&newset, &tsk->blocked, set);
2882 break;
2883 case SIG_UNBLOCK:
2884 sigandnsets(&newset, &tsk->blocked, set);
2885 break;
2886 case SIG_SETMASK:
2887 newset = *set;
2888 break;
2889 default:
2890 return -EINVAL;
2891 }
2892
2893 __set_current_blocked(&newset);
2894 return 0;
2895 }
在函数 __set_current_blocked(&newset)中,也需要申请tsk->sighand->siglock
2846 void __set_current_blocked(const sigset_t *newset)
2847 {
2848 struct task_struct *tsk = current;
2849
2850 /*
2851 * In case the signal mask hasn't changed, there is nothing we need
2852 * to do. The current->blocked shouldn't be modified by other task.
2853 */
2854 if (sigequalsets(&tsk->blocked, newset))
2855 return;
2856
2857 spin_lock_irq(&tsk->sighand->siglock);
2858 __set_task_blocked(tsk, newset);
2859 spin_unlock_irq(&tsk->sighand->siglock);
2860 }
所形成的关系大概是这样
sender main threadlock_task_sighandsend_signal(sig, info, p, type) spin_lock_irq(&tsk->sighand->siglock) //被阻塞unlock_task_sighand(p, &flags) 获取锁,继续调用sigprocmask其他的事情 __set_task_blocked(tsk, newset); spin_unlock_irq(&tsk->sighand->siglock);//释放锁 本来这个锁的释放,唤醒进程都是很简短的过程,通常都是几微秒,为什么这个设备上会出现70us的问题呢,我们看sender和receiver都运行在CPU1上,而main thread是运行在CPU41上,是不是不在一个numa node上,对远端的内存访问会消耗很长时间?
3, 解决方案:将main thread与sender,receiver放到同一个node上
taskset -c 2 ./sigwaittest -p 90 -i 1000 -a 1 -b 80 //不再重现
如果将main thread强制放在CPU41上呢:
taskset -c 41 ./sigwaittest -p 90 -i 1000 -a 1 -b 80 // 很快重现
相关文章:
sigwaittest测试超标的调试过程
1,问题描述硬件环境:飞腾S2500(64核)OS:kylinOS, linux preempt rt, 4.19.90测试命令:sigwaittest -p 90 -i 1000 -a 1测试结果:信号混洗值最大超过了80us,与飞腾其他CPU…...
Python进阶-----面对对象4.0(面对对象三大特征之--继承)
目录 前言: Python的继承简介 1.什么是继承 2.继承的好处 3.object类 继承的相关用法 1.继承的定义与法则 2.对继承的重写 3.(单继承)多层继承 4.多继承 5.多继承重写时调用父类方法 前言: 在讲之前,我想说说中…...
九龙证券|利好政策密集发布,机构扎堆看好的高增长公司曝光
新能源轿车销量和保有量快速增长,带来了充电桩商场的微弱需求。 日前,商务部部长王文涛表明,本年将在落实好方针的一起,活跃出台新方针办法,比方辅导当地展开新能源轿车下乡活动,优化充电等使用环境&#x…...
stm32CubeIDE FMC 驱动LCD(8080)
一,TFT屏硬件接口16位,80并口。二,FMC介绍。FSMC(Flexible Static Memory Controller),译为灵活的静态存储控制器。STM32F1 系列芯片使用 FSMC 外设来管理扩展的存储器,它可以用于驱动包括 SRAM…...
Java 数据类型
数据类型用于对数据归类,以便开发者理解和操作。 基本数据类型 Java 确定了每种基本数据类型所占存储空间的大小,不会像其它语言那样随机器硬件架构的变化而变化,这使 Java 程序更具可移植性。 Java 中定义了如下的基本数据类型。 byte …...
Prometheus 监控云Mysql和自建Mysql(多实例)
本文您将了解到 Prometheus如何配置才能监控云Mysql(包括阿里云、腾讯云、华为云)和自建Mysql。 Prometheus 提供了很多种Exporter,用于监控第三方系统指标,如果没有提供也可以根据Exporter规范自定义Exporter。 本文将通过MySQL server exporter 来监控…...
Vue3中的h函数
文章目录简介简单使用参数使用计数器进阶使用函数组件插槽专栏目录请点击 简介 众所周知,vue内部构建的其实是虚拟DOM,而虚拟DOM是由虚拟节点生成的,实质上虚拟节点也就是一个js对象事实上,我们在vue中写的template,最终也是经过…...
阿尔法开发板 IMX6ULL 说明
一. IMX6ULL开发板 IMX6ULL开发板即正点原子的阿尔法(ALPHA)开发板,采用恩智浦芯片,cortex-A7架构的。 二. IM6ULL开发板说明 1. IO说明 对于IMX6ULL芯片,一个IO对应两个寄存器,第一个寄存器负责配置其复用功能,…...
Altium Designer19 #学习笔记# | 基础应用技巧汇总
全文目录一.元件符号库二.元件封装库1.AD09 集成元件库/封装库三.电路原理图1. 巧用查找"相似对象功能"1.1 查找相同元件1.2. 查找相同文本1.3. 查找相同网络 :E - S - C四.PCB原理图【AD PCB模式下的常用快捷键】PCB视图放大/缩小PCB视图左/右移动PCB切换…...
Python 元类编程实现一个简单的 ORM
概述 什么是ORM? ORM全称“Object Relational Mapping”,即对象-关系映射,就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样,写代码更简单,不用直接操作SQL语句。 现在我们就要实…...
《C++ Primer Plus》第18章:探讨 C++ 新标准(7)
C11 新增的其他功能 C11 增加了很多功能,本书无法全面介绍;另外,本书编写期间,其中很多功能还未得到广泛实现。然而,有些功能有必要简要地介绍一下。 并行编程 当前,为提高计算机性能,增加处…...
Redis学习(二):Redis安装测试
概述 Redis是什么 Redis, Remote Dictionary Server, 即远程字典服务。免费开源的数据库。 由C语言编写,支持网络,可基于内存亦可持久化的日志型、KV数据库,并提供所种语言的API。 Redis能干嘛 用于内存存储,持久化。rdb、ao…...
Vector - CAPL - 简介及数据结构
对于想进入车载行业或者已经在车载行业工作的朋友对于CAPL这个词都会相当的熟悉,都知道他是做车载网络测试脚本的语言,并且跟C有点类似,但是它到底是什么呢?CAPL全称(Communication Access Programming Language&#…...
20230304英语学习
What Would Happen if the Moon Disappeared Tomorrow? 如果明天月球消失了会怎样? The closest object to our planet, the Moon, may seem like Earth’s little sibling.Since its birth, the satellite has mostly just hung around, playing gravitational t…...
【基础算法】单链表的OJ练习(3) # 移除链表元素 # 相交链表 #
文章目录前言移除链表元素相交链表写在最后前言 本章的OJ练习也是相对简单的,只要能够理解解题的思路,并且依照这个思路能够快速的写出代码,我相信,你的链表水平已经足够了。 对于OJ练习(2) : ->传送门…...
【自用】SpringBoot项目通用类整理
文章目录全局Json序列化Controller日志切面全局异常拦截GlobalExceptionHandlerApiResultBusinessExceptionResponseEntityUtil全局返回体包装MP自动填充接口文档配置类自定义Async异步线程池本文主要整理各类项目中通用的配置类、工具类,便于复查自用。 全局Json序…...
动态规划法(总述)多阶段决策最优化问题
动态规划: 研究最优控制问题提出的 该问题有n个输入,问题的解由这n个输入组成,这个子集必须满足事先给定的条件,这些条件称为约束条件,满足约束条件的可行解可能不只有一个为了衡量可行解的优劣,通常以一些函数的形式&…...
MySQL跨服务器数据映射
MySQL跨服务器数据映射环境准备1. 首先是要查看数据库的federated引擎 开启/关闭 状态2. 打开任务管理器,并重启mysql服务3. 再次查看FEDERATED引擎状态,引擎已启动映射实现问题总结在日常的开发中经常进行跨数据库进行查询数据。 同服务器下跨数据库进…...
利用反射实现通过读取配置文件对类进行实例化-课后程序(JAVA基础案例教程-黑马程序员编著-第十二章-课后作业)
【案例12-3】:利用反射实现通过读取配置文件对类进行实例化 【案例介绍】 1.案例描述 现在有一个项目,项目中创建了一个Person类,在Person类中定义了一个sleep()方法。在工程中还定义了一个Student类继承Person类,在Student类中…...
1.2 CSS文本属性
CSS Text(文本)属性: 定义文本外观,颜色,装饰,缩进,行间距来修饰文本 文本样式 文本缩进 text-indent文本水平对齐方式:text-align文本修饰:text-decoration行高 line-height CSS文本颜色属性…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
向量几何的二元性:叉乘模长与内积投影的深层联系
在数学与物理的空间世界中,向量运算构成了理解几何结构的基石。叉乘(外积)与点积(内积)作为向量代数的两大支柱,表面上呈现出截然不同的几何意义与代数形式,却在深层次上揭示了向量间相互作用的…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
