[RFC PATCH 1/2] add cpu_to_nid function
by Huang Shijie
Add cpu_to_nid function which we can use to get the NUMA node id
by the cpu id.
Signed-off-by: Huang Shijie <huangsj(a)hygon.cn>
---
defs.h | 2 ++
kernel.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
main.c | 1 +
3 files changed, 49 insertions(+)
diff --git a/defs.h b/defs.h
index a4f70b7..98a149b 100644
--- a/defs.h
+++ b/defs.h
@@ -6040,6 +6040,8 @@ ulong do_maple_tree(ulong, int, struct list_pair *);
void help_init(void);
void cmd_usage(char *, int);
void display_version(void);
+int cpu_to_nid(int cpu);
+void numa_init(void);
void display_help_screen(char *);
#ifdef ARM
#define dump_machdep_table(X) arm_dump_machdep_table(X)
diff --git a/kernel.c b/kernel.c
index eb9754c..15254a4 100644
--- a/kernel.c
+++ b/kernel.c
@@ -12207,3 +12207,49 @@ out:
pc->error_fp = error_fp_save;
}
#endif
+
+static int *cpu_to_nid_map;
+
+int
+cpu_to_nid(int cpu)
+{
+ if (!cpu_to_nid_map || cpu < 0 || cpu >= kt->cpus)
+ return -1;
+ if (vt->numnodes == 1)
+ return 0;
+ return cpu_to_nid_map[cpu];
+}
+
+static void
+cpu_to_nid_init(void)
+{
+ int i, j;
+ int fd;
+ char buf[64];
+
+ cpu_to_nid_map = malloc(kt->cpus * sizeof(int));
+ if (vt->numnodes == 1)
+ return;
+
+ memset(cpu_to_nid_map, -1, kt->cpus * sizeof(int));
+
+ for (i = 0; i < kt->cpus; i++) {
+ for (j = 0; j < vt->numnodes; j++) {
+ memset(buf, 0, sizeof(buf));
+ sprintf(buf, "/sys/devices/system/cpu/cpu%d/node%d", i, j);
+
+ fd = open(buf, O_RDONLY);
+ if (fd > 0) {
+ cpu_to_nid_map[i] = j;
+ close(fd);
+ break;
+ }
+ }
+ }
+}
+
+void
+numa_init(void)
+{
+ cpu_to_nid_init();
+}
diff --git a/main.c b/main.c
index d5f8486..a8c77f8 100644
--- a/main.c
+++ b/main.c
@@ -793,6 +793,7 @@ main_loop(void)
kernel_init();
machdep_init(POST_GDB);
vm_init();
+ numa_init();
machdep_init(POST_VM);
module_init();
help_init();
--
2.53.0
22 hours, 57 minutes
[PATCH 1/2] Fix failure of "runq -g" option on Linux 7.2 and later kernels
by HAGIO KAZUHITO(萩尾 一仁)
From: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Kernel commit b8fea7af0e40 ("sched/fair: Allocate cfs_tg_state with
percpu allocator") changed task_group.cfs_rq from a pointer array to a
per-cpu variable allocated by the per-cpu allocator.
Without the patch, the "runq -g" option fails with the following error
on the first time, and with a segmentation fault on the second time.
crash> runq -g
CPU 0
CURRENT: PID: 5687 TASK: ffff8b0bc175a2c0 COMMAND: "bash"
ROOT_TASK_GROUP: ffffffff93a55600 CFS_RQ: 0
runq: invalid kernel virtual address: 58 type: "curr"
crash> runq -g
Segmentation fault (core dumped)
Since there is no way to determine whether it is a per-cpu variable,
check wthether it is a pointer array or not.
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
Hi,
I could not find a way to determine it's a __percpu variable or not,
any better ideas?
defs.h | 2 ++
kernel.c | 14 ++++++++++++++
symbols.c | 27 +++++++++++++++++++++++++++
task.c | 30 ++++++++++++++++++++++--------
4 files changed, 65 insertions(+), 8 deletions(-)
diff --git a/defs.h b/defs.h
index a4f70b773cd7..caa4faabb73e 100644
--- a/defs.h
+++ b/defs.h
@@ -691,6 +691,7 @@ struct new_utsname {
#define KMOD_PAX (0x100ULL)
#define KMOD_MEMORY (0x200ULL)
#define IRQ_DESC_TREE_MAPLE (0x400ULL)
+#define PER_CPU_CFS_RQ (0x800ULL)
#define XEN() (kt->flags & ARCH_XEN)
#define OPENVZ() (kt->flags & ARCH_OPENVZ)
@@ -5884,6 +5885,7 @@ void parse_for_member_extended(struct datatype_member *, ulong);
void add_to_downsized(char *);
int is_downsized(char *);
int is_string(char *, char *);
+int is_ptrptr(char *, char *);
struct syment *symbol_complete_match(const char *, struct syment *);
/*
diff --git a/kernel.c b/kernel.c
index eb9754c5e082..e53038d5d8db 100644
--- a/kernel.c
+++ b/kernel.c
@@ -400,6 +400,18 @@ kernel_init()
MEMBER_OFFSET_INIT(task_group_rt_rq, "task_group", "rt_rq");
MEMBER_OFFSET_INIT(task_group_parent, "task_group", "parent");
+ /*
+ * task_group.cfs_rq was changed from a pointer array to a per-cpu
+ * variable at Linux 7.2 (b8fea7af0e40). Since there is no way to
+ * determine it, we check whether it is a pointer array or not.
+ * - struct cfs_rq **cfs_rq;
+ * + struct cfs_rq __percpu *cfs_rq;
+ */
+ if (VALID_MEMBER(task_group_cfs_rq)) {
+ if (!is_ptrptr("task_group", "cfs_rq"))
+ kt->flags2 |= PER_CPU_CFS_RQ;
+ }
+
/*
* In 2.4, smp_send_stop() sets smp_num_cpus back to 1
* in some, but not all, architectures. So if a count
@@ -6362,6 +6374,8 @@ dump_kernel_table(int verbose)
fprintf(fp, "%sKMOD_PAX", others++ ? "|" : "");
if (kt->flags2 & KMOD_MEMORY)
fprintf(fp, "%sKMOD_MEMORY", others++ ? "|" : "");
+ if (kt->flags2 & PER_CPU_CFS_RQ)
+ fprintf(fp, "%sPER_CPU_CFS_RQ", others++ ? "|" : "");
fprintf(fp, ")\n");
fprintf(fp, " stext: %lx\n", kt->stext);
diff --git a/symbols.c b/symbols.c
index 78e400ba3756..03511c8cbe8c 100644
--- a/symbols.c
+++ b/symbols.c
@@ -7933,6 +7933,33 @@ is_string(char *structure, char *member)
return retval;
}
+int
+is_ptrptr(char *structure, char *member)
+{
+ int retval;
+ char *t;
+ char buf[BUFSIZE];
+
+ retval = FALSE;
+ open_tmpfile();
+ whatis_datatype(structure, STRUCT_REQUEST, pc->tmpfile);
+ rewind(pc->tmpfile);
+ while (fgets(buf, BUFSIZE, pc->tmpfile)) {
+ if (!(t = strstr(buf, "**")))
+ continue;
+ t += 2;
+ if (t != strstr(t, member))
+ continue;
+ t += strlen(member);
+ if (*t == ';') {
+ retval = TRUE;
+ break;
+ }
+ }
+ close_tmpfile();
+
+ return retval;
+}
/*
* Generic function for dumping data structure declarations, with a small
diff --git a/task.c b/task.c
index d7f3c129a709..5920d6499687 100644
--- a/task.c
+++ b/task.c
@@ -9464,8 +9464,12 @@ print_parent_task_group_fair(void *t, int cpu)
readmem(tgi->task_group + OFFSET(task_group_cfs_rq),
KVADDR, &cfs_rq_c, sizeof(ulong),
"task_group cfs_rq", FAULT_ON_ERROR);
- readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p,
- sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR);
+
+ if (kt->flags2 & PER_CPU_CFS_RQ)
+ cfs_rq_p = cfs_rq_c + kt->__per_cpu_offset[cpu];
+ else
+ readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p,
+ sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR);
print_group_header_fair(tgi->depth, cfs_rq_p, tgi);
tgi->use = 0;
@@ -9491,8 +9495,13 @@ dump_tasks_in_lower_dequeued_cfs_rq(int depth, ulong cfs_rq, int cpu,
readmem(tgi_array[i]->task_group + OFFSET(task_group_cfs_rq),
KVADDR, &cfs_rq_c, sizeof(ulong), "task_group cfs_rq",
FAULT_ON_ERROR);
- readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p,
- sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR);
+
+ if (kt->flags2 & PER_CPU_CFS_RQ)
+ cfs_rq_p = cfs_rq_c + kt->__per_cpu_offset[cpu];
+ else
+ readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p,
+ sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR);
+
if (cfs_rq == cfs_rq_p)
continue;
@@ -10355,10 +10364,15 @@ dump_tasks_by_task_group(void)
readmem(rt_rq + cpu * sizeof(ulong), KVADDR,
&rt_rq_p, sizeof(ulong), "task_group rt_rq",
FAULT_ON_ERROR);
- if (cfs_rq)
- readmem(cfs_rq + cpu * sizeof(ulong), KVADDR,
- &cfs_rq_p, sizeof(ulong), "task_group cfs_rq",
- FAULT_ON_ERROR);
+ if (cfs_rq) {
+ if (kt->flags2 & PER_CPU_CFS_RQ)
+ cfs_rq_p = cfs_rq + kt->__per_cpu_offset[cpu];
+ else
+ readmem(cfs_rq + cpu * sizeof(ulong), KVADDR,
+ &cfs_rq_p, sizeof(ulong),
+ "task_group cfs_rq", FAULT_ON_ERROR);
+ }
+
fprintf(fp, "%sCPU %d", displayed++ ? "\n" : "", cpu);
if (hide_offline_cpu(cpu)) {
--
2.31.1
1 week, 4 days
[PATCH] task: Introduce -Y option to ps command to display scheduling policy and priority
by Aaron Tomlin
Adds a new option '-Y' to the 'ps' command to print scheduling policy
(e.g., NORMAL, FIFO, RR, etc.) and dynamic priority (prio) for each
task.
Signed-off-by: Aaron Tomlin <atomlin(a)atomlin.com>
---
Hi Tao, Hagio, Lianbo,
Please note that this patch has a dependencies on [PATCH] task: Introduce
-I option to ps command to exclude idle tasks [1].
Thank you,
[1]: https://lists.crash-utility.osci.io/archives/list/devel@lists.crash-utili...
defs.h | 3 ++-
help.c | 3 ++-
task.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 68 insertions(+), 4 deletions(-)
diff --git a/defs.h b/defs.h
index 80cc215..1ee8744 100644
--- a/defs.h
+++ b/defs.h
@@ -5404,8 +5404,9 @@ extern long _ZOMBIE_;
#define PS_POLICY (0x80000)
#define PS_ACTIVE (0x100000)
#define PS_EXCLUDE_IDLE (0x200000)
+#define PS_POLICY_DATA (0x400000)
-#define PS_EXCLUSIVE (PS_TGID_LIST|PS_ARGV_ENVP|PS_TIMES|PS_CHILD_LIST|PS_PPID_LIST|PS_LAST_RUN|PS_RLIMIT|PS_MSECS|PS_SUMMARY|PS_ACTIVE)
+#define PS_EXCLUSIVE (PS_TGID_LIST|PS_ARGV_ENVP|PS_TIMES|PS_CHILD_LIST|PS_PPID_LIST|PS_LAST_RUN|PS_RLIMIT|PS_MSECS|PS_SUMMARY|PS_ACTIVE|PS_POLICY_DATA)
#define MAX_PS_ARGS (100) /* maximum command-line specific requests */
diff --git a/help.c b/help.c
index c88797e..79bfa5b 100644
--- a/help.c
+++ b/help.c
@@ -1392,7 +1392,7 @@ NULL
char *help_ps[] = {
"ps",
"display process status information",
-"[-k|-u|-G|-I|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A|-H]\n [pid | task | command] ...",
+"[-k|-u|-G|-I|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A|-H|-Y]\n [pid | task | command] ...",
" This command displays process status for selected, or all, processes" ,
" in the system. If no arguments are entered, the process data is",
" is displayed for all processes. Specific processes may be selected",
@@ -1473,6 +1473,7 @@ char *help_ps[] = {
" -S display a summary consisting of the number of tasks in a task state.",
" -A display only the active task on each cpu.",
" -H display no header line.",
+" -Y display the task's scheduling policy and priority.",
"\nEXAMPLES",
" Show the process status of all current tasks:\n",
" %s> ps",
diff --git a/task.c b/task.c
index 25b929d..2a312de 100644
--- a/task.c
+++ b/task.c
@@ -118,6 +118,8 @@ static void parse_task_thread(int argcnt, char *arglist[], struct task_context *
static void stack_overflow_check_init(void);
static int has_sched_policy(ulong, ulong);
static ulong task_policy(ulong);
+static const char *task_policy_name(ulong);
+static int task_prio(ulong);
static ulong sched_policy_bit_from_str(const char *);
static ulong make_sched_policy(const char *);
void crash_get_current_task_info(unsigned long *, char **);
@@ -3534,7 +3536,7 @@ cmd_ps(void)
cpuspec = NULL;
flag = 0;
- while ((c = getopt(argcnt, args, "HAISgstcpkuGlmarC:y:")) != EOF) {
+ while ((c = getopt(argcnt, args, "HAISgstcpkuGlmarC:y:Y")) != EOF) {
switch(c)
{
case 'k':
@@ -3649,6 +3651,11 @@ cmd_ps(void)
flag |= PS_EXCLUDE_IDLE;
break;
+ case 'Y':
+ check_ps_exclusive(flag, PS_POLICY_DATA);
+ flag |= PS_POLICY_DATA;
+ break;
+
case 'H':
flag |= PS_NO_HEADER;
break;
@@ -3822,6 +3829,31 @@ show_ps_data(ulong flag, struct task_context *tc, struct psinfo *psi)
}
}
+ if (flag & PS_POLICY_DATA) {
+ task_active = is_task_active(tc->task);
+
+ if (task_active) {
+ if (hide_offline_cpu(tc->processor))
+ fprintf(fp, "- ");
+ else
+ fprintf(fp, "> ");
+ } else
+ fprintf(fp, " ");
+
+ fprintf(fp, "%7ld %7ld %3s %s %-12s %4d ",
+ tc->pid, task_to_pid(tc->ptask),
+ task_cpu(tc->processor, buf2, !VERBOSE),
+ task_pointer_string(tc, flag & PS_KSTACKP, buf3),
+ task_policy_name(tc->task),
+ task_prio(tc->task));
+
+ if (is_kernel_thread(tc->task))
+ fprintf(fp, "[%s]\n", tc->comm);
+ else
+ fprintf(fp, "%s\n", tc->comm);
+ return;
+ }
+
if (flag & PS_PPID_LIST) {
parent_list(tc->task);
fprintf(fp, "\n");
@@ -3902,6 +3934,14 @@ show_ps(ulong flag, struct psinfo *psi)
mkstring(buf, VADDR_PRLEN, CENTER|RJUST, "KSTACKP") :
mkstring(buf, VADDR_PRLEN, CENTER, "TASK"));
+ if ((flag & PS_POLICY_DATA) && !(flag & PS_NO_HEADER)) {
+ fprintf(fp,
+ " PID PPID CPU %s POLICY PRIO COMM\n",
+ flag & PS_KSTACKP ?
+ mkstring(buf, VADDR_PRLEN, CENTER|RJUST, "KSTACKP") :
+ mkstring(buf, VADDR_PRLEN, CENTER, "TASK"));
+ }
+
if (flag & PS_SHOW_ALL) {
if (flag & PS_TIMES) {
@@ -3994,7 +4034,7 @@ show_ps_summary(ulong flag)
char string[3];
} ps_state[MAX_STATES];
- if (flag & (PS_USER|PS_KERNEL|PS_GROUP|PS_EXCLUDE_IDLE))
+ if (flag & (PS_USER|PS_KERNEL|PS_GROUP|PS_EXCLUDE_IDLE|PS_POLICY_DATA))
error(FATAL, "-S option cannot be used with other options\n");
for (s = 0; s < MAX_STATES; s++)
@@ -6050,6 +6090,28 @@ task_policy(ulong task)
return policy;
}
+static const char *
+task_policy_name(ulong task)
+{
+ ulong policy_bit = task_policy(task);
+ struct sched_policy_info *info;
+
+ for (info = sched_policy_info; info->name; info++) {
+ if (policy_bit == (1UL << info->value))
+ return info->name;
+ }
+ return "UNKNOWN";
+}
+
+static int
+task_prio(ulong task)
+{
+ fill_task_struct(task);
+ if (!tt->last_task_read || INVALID_MEMBER(task_struct_prio))
+ return 0;
+ return INT(tt->task_struct + OFFSET(task_struct_prio));
+}
+
/*
* Return a task's tgid.
*/
base-commit: 6b6d58159fedf7ca355d49b867bb3b88d4708a55
--
2.54.0
1 week, 4 days
[PATCH] task: Introduce -I option to ps command to exclude idle tasks
by Aaron Tomlin
Adds a new option '-I' to the 'ps' command to filter out idle
threads/tasks from the output. This filters out the idle tasks from the
main ps list, CPU-specific block lists, and task time reports, while
enforcing mutual exclusivity with the summary (-S) option.
Signed-off-by: Aaron Tomlin <atomlin(a)atomlin.com>
---
defs.h | 1 +
help.c | 3 ++-
task.c | 32 ++++++++++++++++++++++++--------
3 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/defs.h b/defs.h
index a4f70b7..80cc215 100644
--- a/defs.h
+++ b/defs.h
@@ -5403,6 +5403,7 @@ extern long _ZOMBIE_;
#define PS_SUMMARY (0x40000)
#define PS_POLICY (0x80000)
#define PS_ACTIVE (0x100000)
+#define PS_EXCLUDE_IDLE (0x200000)
#define PS_EXCLUSIVE (PS_TGID_LIST|PS_ARGV_ENVP|PS_TIMES|PS_CHILD_LIST|PS_PPID_LIST|PS_LAST_RUN|PS_RLIMIT|PS_MSECS|PS_SUMMARY|PS_ACTIVE)
diff --git a/help.c b/help.c
index 5cd5c30..c88797e 100644
--- a/help.c
+++ b/help.c
@@ -1392,7 +1392,7 @@ NULL
char *help_ps[] = {
"ps",
"display process status information",
-"[-k|-u|-G|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A|-H]\n [pid | task | command] ...",
+"[-k|-u|-G|-I|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A|-H]\n [pid | task | command] ...",
" This command displays process status for selected, or all, processes" ,
" in the system. If no arguments are entered, the process data is",
" is displayed for all processes. Specific processes may be selected",
@@ -1409,6 +1409,7 @@ char *help_ps[] = {
" -k restrict the output to only kernel threads.",
" -u restrict the output to only user tasks.",
" -G display only the thread group leader in a thread group.",
+" -I exclude idle threads/tasks from the output.",
" -y policy restrict the output to tasks having a specified scheduling policy",
" expressed by its integer value or by its (case-insensitive) name;",
" multiple policies may be entered in a comma-separated list:",
diff --git a/task.c b/task.c
index d7f3c12..25b929d 100644
--- a/task.c
+++ b/task.c
@@ -107,8 +107,8 @@ static void foreach_cleanup(void *);
static void ps_cleanup(void *);
static char *task_pointer_string(struct task_context *, ulong, char *);
static int panic_context_adjusted(struct task_context *tc);
-static void show_last_run(struct task_context *, struct psinfo *);
-static void show_milliseconds(struct task_context *, struct psinfo *);
+static void show_last_run(ulong, struct task_context *, struct psinfo *);
+static void show_milliseconds(ulong, struct task_context *, struct psinfo *);
static char *translate_nanoseconds(ulonglong, char *);
static int sort_by_last_run(const void *arg1, const void *arg2);
static void sort_context_array_by_last_run(void);
@@ -3534,7 +3534,7 @@ cmd_ps(void)
cpuspec = NULL;
flag = 0;
- while ((c = getopt(argcnt, args, "HASgstcpkuGlmarC:y:")) != EOF) {
+ while ((c = getopt(argcnt, args, "HAISgstcpkuGlmarC:y:")) != EOF) {
switch(c)
{
case 'k':
@@ -3645,6 +3645,10 @@ cmd_ps(void)
flag |= PS_ACTIVE;
break;
+ case 'I':
+ flag |= PS_EXCLUDE_IDLE;
+ break;
+
case 'H':
flag |= PS_NO_HEADER;
break;
@@ -3794,6 +3798,8 @@ show_ps_data(ulong flag, struct task_context *tc, struct psinfo *psi)
return;
if ((flag & PS_POLICY) && !has_sched_policy(tc->task, psi->policy))
return;
+ if (tc && (flag & PS_EXCLUDE_IDLE) && is_idle_thread(tc->task))
+ return;
if (flag & PS_GROUP) {
if (flag & (PS_LAST_RUN|PS_MSECS))
error(FATAL, "-G not supported with -%c option\n",
@@ -3827,11 +3833,11 @@ show_ps_data(ulong flag, struct task_context *tc, struct psinfo *psi)
return;
}
if (flag & (PS_LAST_RUN)) {
- show_last_run(tc, psi);
+ show_last_run(flag, tc, psi);
return;
}
if (flag & (PS_MSECS)) {
- show_milliseconds(tc, psi);
+ show_milliseconds(flag, tc, psi);
return;
}
if (flag & PS_ARGV_ENVP) {
@@ -3988,7 +3994,7 @@ show_ps_summary(ulong flag)
char string[3];
} ps_state[MAX_STATES];
- if (flag & (PS_USER|PS_KERNEL|PS_GROUP))
+ if (flag & (PS_USER|PS_KERNEL|PS_GROUP|PS_EXCLUDE_IDLE))
error(FATAL, "-S option cannot be used with other options\n");
for (s = 0; s < MAX_STATES; s++)
@@ -4023,7 +4029,7 @@ show_ps_summary(ulong flag)
* current state.
*/
static void
-show_last_run(struct task_context *tc, struct psinfo *psi)
+show_last_run(ulong flag, struct task_context *tc, struct psinfo *psi)
{
int i, c, others;
struct task_context *tcp;
@@ -4053,6 +4059,8 @@ show_last_run(struct task_context *tc, struct psinfo *psi)
for (i = 0; i < RUNNING_TASKS(); i++, tcp++) {
if (tcp->processor != c)
continue;
+ if ((flag & PS_EXCLUDE_IDLE) && is_idle_thread(tcp->task))
+ continue;
fprintf(fp, format, task_last_run(tcp->task));
fprintf(fp, "[%s] ",
task_state_string(tcp->task, buf, !VERBOSE));
@@ -4066,6 +4074,8 @@ show_last_run(struct task_context *tc, struct psinfo *psi)
} else {
tcp = FIRST_CONTEXT();
for (i = 0; i < RUNNING_TASKS(); i++, tcp++) {
+ if ((flag & PS_EXCLUDE_IDLE) && is_idle_thread(tcp->task))
+ continue;
fprintf(fp, format, task_last_run(tcp->task));
fprintf(fp, "[%s] ", task_state_string(tcp->task, buf, !VERBOSE));
print_task_header(fp, tcp, FALSE);
@@ -4104,7 +4114,7 @@ translate_nanoseconds(ulonglong value, char *buf)
* sched_info.last_arrival and its current state.
*/
static void
-show_milliseconds(struct task_context *tc, struct psinfo *psi)
+show_milliseconds(ulong flag, struct task_context *tc, struct psinfo *psi)
{
int i, c, others, days, max_days;
struct task_context *tcp;
@@ -4154,6 +4164,8 @@ show_milliseconds(struct task_context *tc, struct psinfo *psi)
for (i = 0; i < RUNNING_TASKS(); i++, tcp++) {
if (tcp->processor != c)
continue;
+ if ((flag & PS_EXCLUDE_IDLE) && is_idle_thread(tcp->task))
+ continue;
delta = rq_clock - task_last_run(tcp->task);
if (delta < 0)
delta = 0;
@@ -4188,6 +4200,8 @@ show_milliseconds(struct task_context *tc, struct psinfo *psi)
} else {
tcp = FIRST_CONTEXT();
for (i = 0; i < RUNNING_TASKS(); i++, tcp++) {
+ if ((flag & PS_EXCLUDE_IDLE) && is_idle_thread(tcp->task))
+ continue;
if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF))
runq = rq_sp->value +
kt->__per_cpu_offset[tcp->processor];
@@ -4562,6 +4576,8 @@ show_task_times(struct task_context *tcp, ulong flags)
continue;
if ((flags & PS_KERNEL) && !is_kernel_thread(tc->task))
continue;
+ if ((flags & PS_EXCLUDE_IDLE) && is_idle_thread(tc->task))
+ continue;
if (flags & PS_GROUP) {
tgid = task_tgid(tc->task);
if (tc->pid != tgid) {
--
2.54.0
1 week, 4 days
[PATCH 0/3] RISC-V: Fix vtop warnings and improve kernel address range support
by Rui Qi
This series fixes two bugs and adds an enhancement for the riscv64
architecture support in the crash utility:
Patch 1 fixes spurious "WARNING: mem_map[] not accessible" messages
when running vtop or kmem -p on RISC-V. The root cause is that
riscv64.c never sets the VMEMMAP flag on machdep->flags, so crash
does not recognize that unmapped vmemmap holes are normal for
SPARSEMEM_VMEMMAP configurations.
Patch 2 fixes noisy "PAGE: not present" and "invalid for address"
output from the vtop page table walk functions. These messages are
printed unconditionally even when called non-verbosely by internal
routines like kmem -p or dump_mem_map. They should only appear
when verbose=1, consistent with all other diagnostic output in
these functions and with how x86_64/arm64 handle the same case.
Patch 3 adds an architecture-specific get_kvaddr_ranges callback
so that the search command can properly categorize kernel virtual
address regions including modules and vmemmap, instead of falling
back to the generic two-region default.
These patches were tested on a RISC-V 32-core machine with kernel
6.12.13.bsk.1-rc17-riscv64 and vmlinux ~700MB with debug info.
Rui Qi (3):
riscv64: Set VMEMMAP flag to fix spurious mem_map[] warnings
riscv64: Guard verbose output in vtop page table walk functions
riscv64: Add get_kvaddr_ranges callback for kernel address ranges
riscv64.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 62 insertions(+), 6 deletions(-)
--
2.20.1
1 week, 4 days
[PATCH 0/6] LoongArch64: improve dumpfile stack unwinding
by Ming Wang
This series improves LoongArch64 stack unwinding for vmcore dumpfiles.
LoongArch exception entry code may run from relocated exception handler
areas rather than from the canonical vmlinux text address. Looking up
those runtime PCs directly can fail to resolve symbols such as
handle_vint, which also breaks ORC lookup and exception-frame handoff.
The series first fixes the exception return address label to report ERA,
then maps relocated exception vector PCs back to their canonical kernel
symbols. It then adds initial LoongArch64 ORC support for core kernel
text, and uses the saved IRQ-stack state to continue unwinding active
dumpfile tasks from IRQ stack back to task stack. The last two patches
tighten fallback RA handling and only print exception pt_regs with
bt -f.
Tested:
- Built each patch separately with make lzo -j4 on LoongArch64.
- Built the final tree with make -j4 on the X86_64.
- Verified kdump vmcore backtrace still shows the sysrq panic chain.
- Verified git diff --check d0ffcb681f06..HEAD.
Ming Wang (6):
LoongArch64: print exception return address as ERA
LoongArch64: resolve relocated exception vector addresses
LoongArch64: add initial ORC unwinder support
LoongArch64: unwind dumpfile active tasks from IRQ stacks
LoongArch64: avoid replacing a valid RA with stack noise
LoongArch64: print exception registers only with bt -f
defs.h | 27 ++
loongarch64.c | 689 ++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 695 insertions(+), 21 deletions(-)
--
2.43.0
1 week, 4 days
Decoding Consumer Minds: Fresh Ideas for Marketing Research Papers
by kefag22407@haotuwu.com
Marketing is no longer just about selling — it’s about understanding why people buy, share, and stay loyal. Research papers in marketing can dive into fascinating areas like consumer psychology, digital engagement, and emotional branding. Exploring topics such as the impact of social media influencers on brand perception, consumer trust in AI-driven recommendations, or sustainability as a driver of purchase intent can help uncover what really shapes modern consumer decisions.
Another promising angle is studying data and personalization in marketing. With companies relying heavily on analytics, there’s a growing need to explore how data-driven strategies influence consumer experience and brand loyalty. Researching ethical data usage, AI in customer segmentation, or neuromarketing trends can lead to insights that bridge creativity with strategy — essential for any marketer looking to make an impact in today’s competitive landscape. Have more info at: https://thedissertationhelp.co.uk/marketing-research-paper-topics/
1 week, 5 days
[PATCH] arm64: Fix stack size and mask for 16KB pages
by Dean Liao
Dynamically configure machdep->stacksize based on page size.
Specifically, set it to 32KB for 16KB pages (default for CONFIG_ARM64_16K_PAGES)
and 64KB for 64KB pages, instead of using the hardcoded 16KB ARM64_STACK_SIZE.
Update arm64_unwind_frame and arm64_unwind_frame_v2 to use
machdep->stacksize for stack_mask calculation instead of ARM64_STACK_SIZE.
This fixes unwinding failures when the stack frame crosses the 16KB boundary
on a 32KB stack.
Signed-off-by: Dean Liao <deanliao(a)google.com>
---
arm64.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/arm64.c b/arm64.c
index d177092..3ce14aa 100644
--- a/arm64.c
+++ b/arm64.c
@@ -630,7 +630,22 @@ arm64_init(int when)
machdep->last_ptbl_read = 0;
machdep->clear_machdep_cache = arm64_clear_machdep_cache;
- machdep->stacksize = ARM64_STACK_SIZE;
+ /*
+ * Refer to arch/arm64/include/asm/memory.h in kernel source:
+ * THREAD_SIZE is PAGE_SIZE << THREAD_SIZE_ORDER.
+ * When CONFIG_VMAP_STACK is enabled, THREAD_SHIFT is at
+ * least PAGE_SHIFT.
+ * - 4KB pages -> 16KB stack (ARM64_STACK_SIZE)
+ * - 16KB pages -> 32KB stack (MIN_THREAD_SHIFT=15 if KASAN
+ * enabled, or Android default)
+ * - 64KB pages -> 64KB stack (THREAD_SHIFT=PAGE_SHIFT=16)
+ */
+ if (machdep->pagesize == 16384)
+ machdep->stacksize = 32768;
+ else if (machdep->pagesize == 65536)
+ machdep->stacksize = 65536;
+ else
+ machdep->stacksize = ARM64_STACK_SIZE;
machdep->flags |= VMEMMAP;
machdep->uvtop = arm64_uvtop;
machdep->is_uvaddr = arm64_is_uvaddr;
@@ -3311,7 +3326,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
struct arm64_pt_regs *ptregs;
struct machine_specific *ms = machdep->machspec;
- stack_mask = (unsigned long)(ARM64_STACK_SIZE) - 1;
+ stack_mask = machdep->stacksize - 1;
fp = frame->fp;
low = frame->sp;
@@ -3521,7 +3536,7 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
unsigned long irq_stack_ptr;
struct machine_specific *ms;
- stack_mask = (unsigned long)(ARM64_STACK_SIZE) - 1;
+ stack_mask = machdep->stacksize - 1;
fp = frame->fp;
low = frame->sp;
--
2.55.0.rc0.799.gd6f94ed593-goog
2 weeks, 4 days