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文本颜色属性…...
 
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
 
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
 
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
 
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
 
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
 
门静脉高压——表现
一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构:由肠系膜上静脉和脾静脉汇合构成,是肝脏血液供应的主要来源。淤血后果:门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血,引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...
【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析
1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器(TI)推出的一款 汽车级同步降压转换器(DC-DC开关稳压器),属于高性能电源管理芯片。核心特性包括: 输入电压范围:2.95V–6V,输…...
