常用或优秀代码段

一、CPU相关

1. 相关路由宏

task_cpu(p) //获取task所在的CPU
task_rq() //task所在的rq
cpu_of(rq) //获取指定rq的CPU
cpu_rq() //获取指定CPU的 rq
this_rq() //获取当前CPU的rq
raw_rq() //raw_cpu_ptr(&runqueue) 不关抢占获取per-cpu变量的

cpu_curr() rq上当前运行的task

task_of(se) //由se得到p
cfs_rq_of(se) //由se得到其挂载在的cfs_rq
group_cfs_rq(gse) //由gse得到其自己的my_q

2. cpu相关信息

idle_cpu(cpu) 判断是否是idle cpu
system_32bit_el0_cpumask() //返回32bit app能使用的cpu
capacity_curr_of(cpu) //考虑cpu大小和当前频点的cpu的算力
get_cpu_temp(cpu) //获取cpu温度
cpu_dev=get_cpu_device(cpu); //由cpu得到其device结构
cpufreq_cpu_get(first_cpu); //由cpu得到其cpufreq_policy结构
cpu_cur_freq(cpu) //cpu的当前频点,5.4内核才有

3. per-cpu注册回调
on_each_cpu(smp_call_func_t func, void *info, int wait) //对每个cpu都调用回调func()

4. 字符串解析cpu掩码
cpulist_parse(const char *buf, struct cpumask *dstp) //将字符串中的cpu解析到掩码中

5. 拓扑
cpus_share_cache(cpu1, cpu2) //判断两个cpu是否共享cache,即是否属于同一cluster
sched_domain_span(sd) //此 sched_domain 中包含哪些cpu
arch_get_cluster_id() //从导出的cpu_topology[]中很容易得到cluster_id,很容易得到整个cpu的拓扑信息
topology_physical_package_id(first_cpu); //由cpu id得到其cluster id

6. 过滤合适的cpu
mtk_select_task_rq_rt --> for_each_cpu_and(cpu, p->cpus_ptr, cpu_active_mask)

for_each_cpu(i, &domain->possible_cpus) {
if (!cpu_online(i) || cpu_isolated(i) || !cpumask_test_cpu(i, tsk_cpus_allow))
continue;
...
}

7. cpu online判断
//(1) 有保护
cpus_read_lock();
cpu_is_offline(cpu)
cpus_read_unlock();

//(2) 没保护
rcu_core
cpu_is_offline(smp_processor_id())

//(3) 没保护
sched_tick_remote
cpu_is_offline(cpu)

TODO: 什么时候需要保护,什么时候不需要保护?


二、task相关

1. 任务运行状态
task_running(p) //任务p是否正在运行
task_current(rq, p) //判断一个任务是否正在此rq上运行
task_on_rq_queued(p) //表示一个线程是否在runqueue上,判断是否是runnable状态
rt_rq_is_runnable(rt_rq) //判断是否有rt任务runnable

2. 进程线程遍历
for_each_process(p) //遍历进程
for_each_process_thread //遍历线程

3. 任务属性判断
p->flags & PF_KTHREAD //判断是否是内核线程
__sched_setscheduler 中使用 !p->mm 判断是内核线程还是用户空间线程
is_idle_task(p) 判断是否是idle进程。

do_exit --> if (!tsk->pid) panic("Attempted to kill the idle task!"); //idle任务的pid==0
task_has_rt_policy(p) //通过policy判断是否为RT线程
test_task_is_rt(p) //通过prio判断是否为RT线程

is_per_cpu_kthread //判断是不是per-cpu或绑定单个CPU的内核线程

4. 任务线程个数
get_nr_threads(){return task->signal->nr_threads;} //cat /proc/pid/sched 打印出来的"init (1, #threads: 3)"线程个数是通过它获取的。

5. 任务限制
task_rlimit(task, RLIMIT_RTPRIO); //获取对task任务用户空间RT优先级设置最大值的限制,用户空间优先级数值越大,优先级越高。

6. 任务创建
sugov_kthread_create()/trace_wakeup_test_thread() //创建了 deadline 内核线程
cpu_stop_threads.create -- cpu_stop_create -- sched_set_stop_task -- p->sched_class = &stop_sched_class; //"migration/%u" 通过此方法设置为stop调度类

7. 任务负载
cpu_util_without(cpu, p) //cpu减去任务p后的util

8. 获取父任务
sched_show_task:
rcu_read_lock();
if (pid_alive(p))
ppid = task_pid_nr(rcu_dereference(p->real_parent));
rcu_read_unlock();


三、trace相关

1. trace中封装了
#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4)) //trace中已经有帮忙封装 __builtin_return_address(n)了


四、文件系统相关

1. 由per-task的proc文件节点找出这个文件节点是哪个任务的
timerslack_ns_write:
struct inode *inode = file_inode(file);
struct task_struct *p = get_proc_task(inode);

 

 

杂项

1. 判断内核版本

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
#else
#endif

2. 以25为基向上圆整

ret = ((value%25) ? 1 : 0) + value/25; //以25为基的向上圆整

 

posted on 2023-02-10 15:19  Hello-World3  阅读(285)  评论(0编辑  收藏  举报

导航