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