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文本颜色属性…...
SpringCloud之认识微服务
文章目录一、传统项目转型二、走进 SpringCloud三、微服务项目搭建3.1 创建一个 SpringBoot 项目3.2 创建三个 Maven 子工程3.3 为子工程创建 application.yml3.4 引入依赖3.5 数据库 建库建表3.6 编写业务提示:以下是本篇文章正文内容,SpringCloud系列学…...
【go语言之thrift协议二之server端分析】
go语言之thrift协议二serverthrift.TProtocolFactoryTTransportReadWriteCloserContextFlusherReadSizeProviderTProtocolrunServerNewTServerSocketNewCalculatorHandlerNewCalculatorProcessorNewTSimpleServer4server.ServeListenAcceptLoopprocessRequests在上一篇文章分析…...
【办公类05-03】Python批量修改文件名前面的序号(已有的序号错了,需要改成正确的号码)
背景需求下载教程,手动输入编号,有一个编号错误,导致后面所有编号都错了。30实际是29,以此类推怎样才能快速修改编号数字?前期考虑到可能要改编号,所以在每个编号后面加“ ”(空格)&…...
定向模糊测试工具Beacon基本用法
Beacon是一个定向模糊测试工具,给定行号,能够定向探索行号附近的代码区域。主要思想是采用静态分析的方法获取到与目标有关的变量的最弱前置条件(weakest precondition)的信息,并在相关位置插入断言,来提前…...
《程序员面试金典(第6版)》面试题 02.01. 移除重复节点
题目描述 编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。 示例1: 输入:[1, 2, 3, 3, 2, 1] 输出:[1, 2, 3] -示例2: 输入:[1, 1, 1, 1, 2] 输出:[1, 2] 提示: 链表长度在[0, 20000]范…...
如何对web系统开展无障碍测试
Accessibility test(无障碍测试)是一种测试方法,旨在评估软件、网站或其他数字产品的可访问性,以确保它们能够被身体残障或其他特殊需求的用户使用。这些测试通常包括使用辅助技术,如屏幕阅读器和放大器,以…...
使用vite+vue3.0 创建一个cesium基础应用 ----01 项目搭建
使用vitevue3.0 创建一个cesium基础应用 ----01 项目搭建 1.使用yarn创建一个vite项目 我们可以在vite官网找到vite创建项目的命令 https://cn.vitejs.dev/ 可以使用yarn创建项目选择使用vue3.0框架,语言使用js 创建完成后结构如下: 2.找到vite社区中的…...
【Python学习笔记】第二十七节 Python 多线程
一、进程和线程进程:是程序的一次执行,每个进程都有自己的地址空间、内存、数据栈及其他记录运行轨迹的辅助数据。线程:所有的线程都运行在同一个进程当中,共享相同的运行环境。线程有开始、顺序执行和结束三个部分, …...
【id:18】【20分】B. DS顺序表--连续操作
题目描述建立顺序表的类,属性包括:数组、实际长度、最大长度(设定为1000)该类具有以下成员函数:构造函数:实现顺序表的初始化。插入多个数据的multiinsert(int i, int n, int item[])函数,实现在…...
vi编辑器操作指令分享
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令。由于对Unix及Linux系统的任何版本,vi编辑器是完全相同的,因此您可以在其他任何介绍vi的地方…...
网站建设需要些什么东西/seo工具在线访问
javascript浏览器Ajax请求在现代网站中大量使用。 除了使用执行Ajax请求的内置方法之外,还使用XMLHttpRequest实例,许多开发人员还使用jQuery的方法来执行相同的任务。 在本文中,我们将介绍两个替代库,它们使您可以实现相同的目标…...
问题反馈的网站怎么做/推广营销方案
*体会静坐的乐趣 *把不用的东西捐出去 *整理相片 *分类放置物品 *从家务中解放出来 *辞掉现在的工作 *种一棵树 *和孩子一起做游戏 *听听流行音乐 *多读书 &a…...
wordpress评论可见内容/国内新闻最近新闻今天
IntelliJ IDEA简介 IDEA 全称IntelliJ IDEA,是用于java语言开发的集成环境(也可用于其他语言),IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手、代码自动提示、重构、J2EE支持、Ant、JUnit、CVS整合…...
泾阳做网站/域名注册查询阿里云
正整数整数零正有理数有理数负整数正分数正分数有理数0分数负整数负整数负有理数负分数2、正数和负数用来表示具有相反意义的数。(二)数轴1、定义:规定了原点、正方向和单位长度的直线叫做数轴。2、数轴的三要素是:原点、正方向、单位长度。(三)相反数1、…...
wordpress 缩略图截图/网站优化建议
2、51单片机MAX7219数码管显示C程序/***************************************************程序名称: MAX7219 C语言控制程序*程序功能: 3线串行控制8位共阴数码管*3线定义:DIN 串行数据输入* LOAD 数据锁存* CLK 时钟输入******************…...
扁平网站设计/东莞企业网站推广
谈谈数据压缩的机制 前言 本文简单谈谈压缩数据的机制,并介绍几种压缩算法。数据压缩我们在生活中经常用到,比如把数据压缩打包为zip,rar等等。那么我们有没有思考过,数据为什么能压缩呢?它的机制是什么呢࿱…...