--- crash-7.0.2/task.c.orig
+++ crash-7.0.2/task.c
@@ -489,6 +489,7 @@ task_init(void)
}
sort_context_array();
+ sort_tgid_array();
if (pc->flags & SILENT)
initialize_task_state();
@@ -635,6 +636,11 @@ allocate_task_space(int cnt)
malloc(cnt * sizeof(struct task_context))))
error(FATAL, "cannot malloc context array (%d tasks)",
cnt);
+ if (!(tt->tgid_array = (struct tgid_context *)
+ malloc(cnt * sizeof(struct tgid_context))))
+ error(FATAL, "cannot malloc tgid array (%d tasks)",
+ cnt);
+
} else {
if (!(tt->task_local = (void *)
realloc(tt->task_local, cnt * sizeof(void *))))
@@ -648,6 +654,13 @@ allocate_task_space(int cnt)
error(FATAL,
"%scannot realloc context array (%d tasks)",
(pc->flags & RUNTIME) ? "" : "\n", cnt);
+
+ if (!(tt->tgid_array = (struct tgid_context *)
+ realloc(tt->tgid_array,
+ cnt * sizeof(struct tgid_context))))
+ error(FATAL,
+ "%scannot realloc tgid array (%d tasks)",
+ (pc->flags & RUNTIME) ? "" : "\n", cnt);
}
}
@@ -2272,13 +2285,14 @@ retry_active:
static struct task_context *
store_context(struct task_context *tc, ulong task, char *tp)
{
- pid_t *pid_addr;
+ pid_t *pid_addr, *tgid_addr;
char *comm_addr;
int *processor_addr;
ulong *parent_addr;
ulong *mm_addr;
int has_cpu;
int do_verify;
+ struct tgid_context *tg;
processor_addr = NULL;
@@ -2301,6 +2315,7 @@ store_context(struct task_context *tc, u
tc = tt->context_array + tt->running_tasks;
pid_addr = (pid_t *)(tp + OFFSET(task_struct_pid));
+ tgid_addr = (pid_t *)(tp + OFFSET(task_struct_tgid));
comm_addr = (char *)(tp + OFFSET(task_struct_comm));
if (tt->flags & THREAD_INFO) {
tc->thread_info = ULONG(tp + OFFSET(task_struct_thread_info));
@@ -2326,6 +2341,14 @@ store_context(struct task_context *tc, u
tc->task = task;
tc->tc_next = NULL;
+ /*
+ * Fill a tgid_context structure with the data from
+ * the incoming task.
+ */
+ tg = tt->tgid_array + tt->running_tasks;
+ tg->tgid = *tgid_addr;
+ tg->task = task;
+
if (do_verify && !verify_task(tc, do_verify)) {
error(INFO, "invalid task address: %lx\n", tc->task);
BZERO(tc, sizeof(struct task_context));
@@ -2441,6 +2464,33 @@ sort_context_array_by_last_run(void)
}
/*
+ * Set the tgid_context array by tgid number.
+ */
+void
+sort_tgid_array(void)
+{
+ if (VALID_MEMBER(mm_struct_rss) || (!VALID_MEMBER(task_struct_rss_stat)))
+ return;
+
+ qsort((void *)tt->tgid_array, (size_t)tt->running_tasks,
+ sizeof(struct tgid_context), sort_by_tgid);
+
+ tt->last_tgid = tt->tgid_array;
+}
+
+int
+sort_by_tgid(const void *arg1, const void *arg2)
+{
+ struct tgid_context *t1, *t2;
+
+ t1 = (struct tgid_context *)arg1;
+ t2 = (struct tgid_context *)arg2;
+
+ return (t1->tgid < t2->tgid ? -1 :
+ t1->tgid == t2->tgid ? 0 : 1);
+}
+
+/*
* Keep a stash of the last task_struct accessed. Chances are it will
* be hit several times before the next task is accessed.
*/
@@ -6320,6 +6370,7 @@ dump_task_table(int verbose)
{
int i, j, more, nr_cpus;
struct task_context *tc;
+ struct tgid_context *tg;
char buf[BUFSIZE];
int others, wrap, flen;
@@ -6340,6 +6391,12 @@ dump_task_table(int verbose)
fprintf(fp, " .tc_next: %lx\n", (ulong)tc->tc_next);
}
fprintf(fp, " context_array: %lx\n", (ulong)tt->context_array);
+ fprintf(fp, " tgid_array: %lx\n", (ulong)tt->tgid_array);
+ fprintf(fp, " tgid_searches: %ld\n", tt->tgid_searches);
+ fprintf(fp, " tgid_cache_hits: %ld (%ld%%)\n", tt->tgid_cache_hits,
+ tt->tgid_searches ?
+ tt->tgid_cache_hits * 100 / tt->tgid_searches : 0);
+ fprintf(fp, " last_tgid: %lx\n", (ulong)tt->last_tgid);
fprintf(fp, "refresh_task_table: ");
if (tt->refresh_task_table == refresh_fixed_task_table)
fprintf(fp, "refresh_fixed_task_table()\n");
@@ -6434,6 +6491,8 @@ dump_task_table(int verbose)
fprintf(fp, " task_struct: %lx\n", (ulong)tt->task_struct);
fprintf(fp, " mm_struct: %lx\n", (ulong)tt->mm_struct);
fprintf(fp, " init_pid_ns: %lx\n", tt->init_pid_ns);
+ fprintf(fp, " filepages: %ld\n", tt->filepages);
+ fprintf(fp, " anonpages: %ld\n", tt->anonpages);
wrap = sizeof(void *) == SIZEOF_32BIT ? 8 : 4;
@@ -6649,6 +6708,13 @@ dump_task_table(int verbose)
i, tc->task, tc->pid, tc->processor, tc->ptask,
(ulong)tc->mm_struct, tc->comm);
}
+
+ fprintf(fp, "\nINDEX TASK TGID (COMM)\n");
+ for (i = 0; i < RUNNING_TASKS(); i++) {
+ tg = &tt->tgid_array[i];
+ tc = task_to_context(tg->task);
+ fprintf(fp, "[%3d] %lx %ld (%s)\n", i, tg->task, tg->tgid, tc->comm);
+ }
}
/*
--- crash-7.0.2/main.c.orig
+++ crash-7.0.2/main.c
@@ -747,6 +747,7 @@ reattempt:
} else if (!(pc->flags & MINIMAL_MODE)) {
tt->refresh_task_table();
sort_context_array();
+ sort_tgid_array();
}
}
if (!STREQ(pc->curcmd, pc->program_name))
--- crash-7.0.2/defs.h.orig
+++ crash-7.0.2/defs.h
@@ -749,6 +749,11 @@ struct task_context {
struct task_context *tc_next;
};
+struct tgid_context { /* tgid and task stored for each task */
+ ulong tgid;
+ ulong task;
+};
+
struct task_table { /* kernel/local task table data */
struct task_context *current;
struct task_context *context_array;
@@ -782,6 +787,12 @@ struct task_table {
char *thread_info;
char *mm_struct;
ulong init_pid_ns;
+ struct tgid_context *tgid_array;
+ struct tgid_context *last_tgid;
+ ulong tgid_searches;
+ ulong tgid_cache_hits;
+ long filepages;
+ long anonpages;
};
#define TASK_INIT_DONE (0x1)
@@ -4710,6 +4721,8 @@ ulong generic_get_stackbase(ulong);
ulong generic_get_stacktop(ulong);
void dump_task_table(int);
void sort_context_array(void);
+void sort_tgid_array(void);
+int sort_by_tgid(const void *, const void *);
int in_irq_ctx(ulonglong, int, ulong);
/*
--- crash-7.0.2/memory.c.orig
+++ crash-7.0.2/memory.c
@@ -215,6 +215,7 @@ static int next_module_vaddr(ulong, ulon
static int next_identity_mapping(ulong, ulong *);
static int vm_area_page_dump(ulong, ulong, ulong, ulong, ulong,
struct reference *);
+static void rss_page_types_init(void);
static int dump_swap_info(ulong, ulong *, ulong *);
static void swap_info_init(void);
static char *get_swapdev(ulong, char *);
@@ -1040,6 +1041,8 @@ vm_init(void)
page_flags_init();
+ rss_page_types_init();
+
vt->flags |= VM_INIT;
}
@@ -4001,6 +4004,54 @@ in_user_stack(ulong task, ulong vaddr)
}
/*
+ * Set the const value of filepages and anonpages
+ * according to MM_FILEPAGES and MM_ANONPAGES.
+ */
+static void
+rss_page_types_init(void)
+{
+ long anonpages, filepages;
+
+ if (VALID_MEMBER(mm_struct_rss))
+ return;
+
+ if (VALID_MEMBER(mm_struct_rss_stat))
+ {
+ if (!enumerator_value("MM_FILEPAGES", &filepages) ||
+ !enumerator_value("MM_ANONPAGES", &anonpages))
+ {
+ filepages = 0;
+ anonpages = 1;
+ }
+ tt->filepages = filepages;
+ tt->anonpages = anonpages;
+ }
+}
+
+static struct tgid_context *
+tgid_quick_search(ulong tgid)
+{
+ struct tgid_context *last, *next;
+
+ tt->tgid_searches++;
+
+ last = tt->last_tgid;
+ if (tgid == last->tgid) {
+ tt->tgid_cache_hits++;
+ return last;
+ }
+
+ next = last + 1;
+ if ((next < (tt->tgid_array + RUNNING_TASKS())) &&
+ (tgid == next->tgid)) {
+ tt->tgid_cache_hits++;
+ return next;
+ }
+
+ return NULL;
+}
+
+/*
* Fill in the task_mem_usage structure with the RSS, virtual memory size,
* percent of physical memory being used, and the mm_struct address.
*/
@@ -4037,11 +4088,8 @@ get_task_mem_usage(ulong task, struct ta
if (VALID_MEMBER(mm_struct_rss_stat)) {
long anonpages, filepages;
- if (!enumerator_value("MM_FILEPAGES", &filepages) ||
- !enumerator_value("MM_ANONPAGES", &anonpages)) {
- filepages = 0;
- anonpages = 1;
- }
+ anonpages = tt->anonpages;
+ filepages = tt->filepages;
rss += LONG(tt->mm_struct +
OFFSET(mm_struct_rss_stat) +
OFFSET(mm_rss_stat_count) +
@@ -4054,19 +4102,35 @@ get_task_mem_usage(ulong task, struct ta
/* Check whether SPLIT_RSS_COUNTING is enabled */
if (VALID_MEMBER(task_struct_rss_stat)) {
- int i, sync_rss;
- ulong tgid;
- struct task_context *tc1;
-
- tgid = task_tgid(task);
-
- tc1 = FIRST_CONTEXT();
- for (i = 0; i < RUNNING_TASKS(); i++, tc1++) {
- if (task_tgid(tc1->task) != tgid)
- continue;
+ int sync_rss;
+ struct tgid_context tgid, *tgid_array, *tg, *first, *last;
+
+ tgid_array = tt->tgid_array;
+ tgid.tgid = task_tgid(task);
+ if (!(tg = tgid_quick_search(tgid.tgid)))
+ tg = (struct tgid_context *)bsearch(&tgid, tgid_array, RUNNING_TASKS(),
+ sizeof(struct tgid_context), sort_by_tgid);
+
+ if (tg == NULL)
+ error(FATAL, "bsearch for tgid failed: task: %lx tgid: %ld\n",
+ task, tgid.tgid);
+
+ /* find the first element which has the same tgid */
+ first = tg;
+ while ((first > tgid_array) && ((first - 1)->tgid == first->tgid))
+ first--;
+
+ /* find the last element which have same tgid */
+ last = tg;
+ while ((last < (tgid_array + (RUNNING_TASKS() - 1))) &&
+ (last->tgid == (last + 1)->tgid))
+ last++;
+
+ while (first <= last)
+ {
/* count 0 -> filepages */
- if (!readmem(tc1->task +
+ if (!readmem(first->task +
OFFSET(task_struct_rss_stat) +
OFFSET(task_rss_stat_count), KVADDR,
&sync_rss,
@@ -4078,7 +4142,7 @@ get_task_mem_usage(ulong task, struct ta
rss += sync_rss;
/* count 1 -> anonpages */
- if (!readmem(tc1->task +
+ if (!readmem(first->task +
OFFSET(task_struct_rss_stat) +
OFFSET(task_rss_stat_count) +
sizeof(int),
@@ -4089,7 +4153,13 @@ get_task_mem_usage(ulong task, struct ta
continue;
rss += sync_rss;
+
+ if(first == last)
+ break;
+ first++;
}
+
+ tt->last_tgid = last;
}
/*