This patch addresses two issues:
- fixes boot hang with CONFIG_IPIPE_TRACE, !CONFIG_IPIPE_TRACE_VMALLOC,
and large CONFIG_NR_CPUS (due to the huge trace buffers this implies,
even if the system has only a few CPUs in fact)
- improves NUMA performance by allocating the buffers node-local
(hackbench indicates a speed-up of 2 on a 8-way box when the tracer
is armed)
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
---
kernel/ipipe/tracer.c | 150 +++++++++++++++++++++++---------------------------
1 file changed, 71 insertions(+), 79 deletions(-)
Index: b/kernel/ipipe/tracer.c
===================================================================
--- a/kernel/ipipe/tracer.c
+++ b/kernel/ipipe/tracer.c
@@ -2,7 +2,7 @@
* kernel/ipipe/tracer.c
*
* Copyright (C) 2005 Luotao Fu.
- * 2005-2007 Jan Kiszka.
+ * 2005-2008 Jan Kiszka.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -64,8 +64,7 @@
#define IPIPE_TFLG_CURRENT_DOMAIN(point) \
((point->flags & IPIPE_TFLG_CURRDOM_MASK) >> IPIPE_TFLG_CURRDOM_SHIFT)
-
-struct ipipe_trace_point{
+struct ipipe_trace_point {
short type;
short flags;
unsigned long eip;
@@ -74,7 +73,7 @@ struct ipipe_trace_point{
unsigned long long timestamp;
};
-struct ipipe_trace_path{
+struct ipipe_trace_path {
volatile int flags;
int dump_lock; /* separated from flags due to cross-cpu access */
int trace_pos; /* next point to fill */
@@ -100,29 +99,18 @@ enum ipipe_trace_type
#define IPIPE_TYPE_MASK 0x0007
#define IPIPE_TYPE_BITS 3
-
#ifdef CONFIG_IPIPE_TRACE_VMALLOC
-
-static struct ipipe_trace_path *trace_paths[NR_CPUS];
-
+static DEFINE_PER_CPU(struct ipipe_trace_path *, trace_path);
#else /* !CONFIG_IPIPE_TRACE_VMALLOC */
-
-static struct ipipe_trace_path trace_paths[NR_CPUS][IPIPE_TRACE_PATHS] =
- { [0 ... NR_CPUS-1] =
- { [0 ... IPIPE_TRACE_PATHS-1] =
- { .begin = -1, .end = -1 }
- }
- };
+static DEFINE_PER_CPU(struct ipipe_trace_path, trace_path[IPIPE_TRACE_PATHS]) =
+ { [0 ... IPIPE_TRACE_PATHS-1] = { .begin = -1, .end = -1 } };
#endif /* CONFIG_IPIPE_TRACE_VMALLOC */
int ipipe_trace_enable = 0;
-static int active_path[NR_CPUS] =
- { [0 ... NR_CPUS-1] = IPIPE_DEFAULT_ACTIVE };
-static int max_path[NR_CPUS] =
- { [0 ... NR_CPUS-1] = IPIPE_DEFAULT_MAX };
-static int frozen_path[NR_CPUS] =
- { [0 ... NR_CPUS-1] = IPIPE_DEFAULT_FROZEN };
+static DEFINE_PER_CPU(int, active_path) = { IPIPE_DEFAULT_ACTIVE };
+static DEFINE_PER_CPU(int, max_path) = { IPIPE_DEFAULT_MAX };
+static DEFINE_PER_CPU(int, frozen_path) = { IPIPE_DEFAULT_FROZEN };
static IPIPE_DEFINE_SPINLOCK(global_path_lock);
static int pre_trace = IPIPE_DEFAULT_PRE_TRACE;
static int post_trace = IPIPE_DEFAULT_POST_TRACE;
@@ -169,7 +157,7 @@ __ipipe_store_domain_states(struct ipipe
}
}
-static notrace int __ipipe_get_free_trace_path(int old, int cpu_id)
+static notrace int __ipipe_get_free_trace_path(int old, int cpu)
{
int new_active = old;
struct ipipe_trace_path *tp;
@@ -177,9 +165,9 @@ static notrace int __ipipe_get_free_trac
do {
if (++new_active == IPIPE_TRACE_PATHS)
new_active = 0;
- tp = &trace_paths[cpu_id][new_active];
- } while ((new_active == max_path[cpu_id]) ||
- (new_active == frozen_path[cpu_id]) ||
+ tp = &per_cpu(trace_path, cpu)[new_active];
+ } while (new_active == per_cpu(max_path, cpu) ||
+ new_active == per_cpu(frozen_path, cpu) ||
tp->dump_lock);
return new_active;
@@ -203,30 +191,30 @@ __ipipe_migrate_pre_trace(struct ipipe_t
}
static notrace struct ipipe_trace_path *
-__ipipe_trace_end(int cpu_id, struct ipipe_trace_path *tp, int pos)
+__ipipe_trace_end(int cpu, struct ipipe_trace_path *tp, int pos)
{
struct ipipe_trace_path *old_tp = tp;
- long active = active_path[cpu_id];
+ long active = per_cpu(active_path, cpu);
unsigned long long length;
/* do we have a new worst case? */
length = tp->point[tp->end].timestamp -
tp->point[tp->begin].timestamp;
- if (length > (trace_paths[cpu_id][max_path[cpu_id]]).length) {
+ if (length > per_cpu(trace_path, cpu)[per_cpu(max_path, cpu)].length) {
/* we need protection here against other cpus trying
to start a proc dump */
spin_lock(&global_path_lock);
/* active path holds new worst case */
tp->length = length;
- max_path[cpu_id] = active;
+ per_cpu(max_path, cpu) = active;
/* find next unused trace path */
- active = __ipipe_get_free_trace_path(active, cpu_id);
+ active = __ipipe_get_free_trace_path(active, cpu);
spin_unlock(&global_path_lock);
- tp = &trace_paths[cpu_id][active];
+ tp = &per_cpu(trace_path, cpu)[active];
/* migrate last entries for pre-tracing */
__ipipe_migrate_pre_trace(tp, old_tp, pos);
@@ -236,11 +224,11 @@ __ipipe_trace_end(int cpu_id, struct ipi
}
static notrace struct ipipe_trace_path *
-__ipipe_trace_freeze(int cpu_id, struct ipipe_trace_path *tp, int pos)
+__ipipe_trace_freeze(int cpu, struct ipipe_trace_path *tp, int pos)
{
struct ipipe_trace_path *old_tp = tp;
- long active = active_path[cpu_id];
- int i;
+ long active = per_cpu(active_path, cpu);
+ int n;
/* frozen paths have no core (begin=end) */
tp->begin = tp->end;
@@ -249,21 +237,21 @@ __ipipe_trace_freeze(int cpu_id, struct
* to set their frozen path or to start a proc dump */
spin_lock(&global_path_lock);
- frozen_path[cpu_id] = active;
+ per_cpu(frozen_path, cpu) = active;
/* find next unused trace path */
- active = __ipipe_get_free_trace_path(active, cpu_id);
+ active = __ipipe_get_free_trace_path(active, cpu);
/* check if this is the first frozen path */
- for (i = 0; i < NR_CPUS && trace_paths[i] != NULL; i++) {
- if ((i != cpu_id) &&
- (trace_paths[i][frozen_path[i]].end >= 0))
+ for_each_possible_cpu(n) {
+ if (n != cpu &&
+ per_cpu(trace_path, n)[per_cpu(frozen_path, n)].end >= 0)
tp->end = -1;
}
spin_unlock(&global_path_lock);
- tp = &trace_paths[cpu_id][active];
+ tp = &per_cpu(trace_path, cpu)[active];
/* migrate last entries for pre-tracing */
__ipipe_migrate_pre_trace(tp, old_tp, pos);
@@ -279,13 +267,13 @@ __ipipe_trace(enum ipipe_trace_type type
int pos, next_pos, begin;
struct ipipe_trace_point *point;
unsigned long flags;
- int cpu_id;
+ int cpu;
local_irq_save_hw_notrace(flags);
- cpu_id = ipipe_processor_id();
+ cpu = ipipe_processor_id();
restart:
- tp = old_tp = &trace_paths[cpu_id][active_path[cpu_id]];
+ tp = old_tp = &per_cpu(trace_path, cpu)[per_cpu(active_path, cpu)];
/* here starts a race window with NMIs - catched below */
@@ -312,7 +300,8 @@ __ipipe_trace(enum ipipe_trace_type type
/* check active_path again - some nasty NMI may have switched
* it meanwhile */
- if (unlikely(tp != &trace_paths[cpu_id][active_path[cpu_id]])) {
+ if (unlikely(tp !=
+ &per_cpu(trace_path, cpu)[per_cpu(active_path, cpu)])) {
/* release lock on wrong path and restart */
tp->flags &= ~IPIPE_TFLG_NMI_LOCK;
@@ -353,7 +342,7 @@ __ipipe_trace(enum ipipe_trace_type type
if ((unlikely(type == IPIPE_TRACE_FREEZE) ||
(unlikely(eip >= trigger_begin && eip <= trigger_end) &&
type == IPIPE_TRACE_FUNC)) &&
- (trace_paths[cpu_id][frozen_path[cpu_id]].begin < 0) &&
+ per_cpu(trace_path, cpu)[per_cpu(frozen_path, cpu)].begin < 0 &&
!(tp->flags & IPIPE_TFLG_FREEZING)) {
tp->post_trace = post_trace + 1;
tp->flags |= IPIPE_TFLG_FREEZING;
@@ -376,9 +365,9 @@ __ipipe_trace(enum ipipe_trace_type type
enforce_end:
if (tp->flags & IPIPE_TFLG_FREEZING)
- tp = __ipipe_trace_freeze(cpu_id, tp, pos);
+ tp = __ipipe_trace_freeze(cpu, tp, pos);
else
- tp = __ipipe_trace_end(cpu_id, tp, pos);
+ tp = __ipipe_trace_end(cpu, tp, pos);
/* reset the active path, maybe already start a new one */
tp->begin = (type == IPIPE_TRACE_BEGIN) ?
@@ -388,7 +377,7 @@ __ipipe_trace(enum ipipe_trace_type type
tp->flags = 0;
/* update active_path not earlier to avoid races with NMIs */
- active_path[cpu_id] = tp - trace_paths[cpu_id];
+ per_cpu(active_path, cpu) = tp - per_cpu(trace_path, cpu);
}
/* we still have old_tp and point,
@@ -412,14 +401,14 @@ __ipipe_trace(enum ipipe_trace_type type
static unsigned long __ipipe_global_path_lock(void)
{
unsigned long flags;
- int cpu_id;
+ int cpu;
struct ipipe_trace_path *tp;
spin_lock_irqsave(&global_path_lock, flags);
- cpu_id = ipipe_processor_id();
+ cpu = ipipe_processor_id();
restart:
- tp = &trace_paths[cpu_id][active_path[cpu_id]];
+ tp = &per_cpu(trace_path, cpu)[per_cpu(active_path, cpu)];
/* here is small race window with NMIs - catched below */
@@ -430,7 +419,7 @@ static unsigned long __ipipe_global_path
/* check active_path again - some nasty NMI may have switched
* it meanwhile */
- if (tp != &trace_paths[cpu_id][active_path[cpu_id]]) {
+ if (tp != &per_cpu(trace_path, cpu)[per_cpu(active_path, cpu)]) {
/* release lock on wrong path and restart */
tp->flags &= ~IPIPE_TFLG_NMI_LOCK;
@@ -444,14 +433,14 @@ static unsigned long __ipipe_global_path
static void __ipipe_global_path_unlock(unsigned long flags)
{
- int cpu_id;
+ int cpu;
struct ipipe_trace_path *tp;
/* release spinlock first - it's not involved in the NMI issue */
__ipipe_spin_unlock_irqbegin(&global_path_lock);
- cpu_id = ipipe_processor_id();
- tp = &trace_paths[cpu_id][active_path[cpu_id]];
+ cpu = ipipe_processor_id();
+ tp = &per_cpu(trace_path, cpu)[per_cpu(active_path, cpu)];
tp->flags &= ~IPIPE_TFLG_NMI_LOCK;
@@ -513,15 +502,15 @@ EXPORT_SYMBOL(ipipe_trace_pid);
int ipipe_trace_max_reset(void)
{
- int cpu_id;
+ int cpu;
unsigned long flags;
struct ipipe_trace_path *path;
int ret = 0;
flags = __ipipe_global_path_lock();
- for (cpu_id = 0; cpu_id < NR_CPUS && trace_paths[cpu_id] != NULL; cpu_id++) {
- path = &trace_paths[cpu_id][max_path[cpu_id]];
+ for_each_possible_cpu(cpu) {
+ path = &per_cpu(trace_path, cpu)[per_cpu(max_path, cpu)];
if (path->dump_lock) {
ret = -EBUSY;
@@ -542,15 +531,15 @@ EXPORT_SYMBOL(ipipe_trace_max_reset);
int ipipe_trace_frozen_reset(void)
{
- int cpu_id;
+ int cpu;
unsigned long flags;
struct ipipe_trace_path *path;
int ret = 0;
flags = __ipipe_global_path_lock();
- for_each_online_cpu(cpu_id) {
- path = &trace_paths[cpu_id][frozen_path[cpu_id]];
+ for_each_online_cpu(cpu) {
+ path = &per_cpu(trace_path, cpu)[per_cpu(frozen_path, cpu)];
if (path->dump_lock) {
ret = -EBUSY;
@@ -606,7 +595,7 @@ __ipipe_get_task_info(char *task_info, s
void ipipe_trace_panic_freeze(void)
{
unsigned long flags;
- int cpu_id;
+ int cpu;
if (!ipipe_trace_enable)
return;
@@ -614,9 +603,9 @@ void ipipe_trace_panic_freeze(void)
ipipe_trace_enable = 0;
local_irq_save_hw_notrace(flags);
- cpu_id = ipipe_processor_id();
+ cpu = ipipe_processor_id();
- panic_path = &trace_paths[cpu_id][active_path[cpu_id]];
+ panic_path = &per_cpu(trace_path, cpu)[per_cpu(active_path, cpu)];
local_irq_restore_hw(flags);
}
@@ -889,7 +878,7 @@ static void *__ipipe_max_prtrace_start(s
mutex_lock(&out_mutex);
if (!n) {
- struct ipipe_trace_path *path;
+ struct ipipe_trace_path *tp;
unsigned long length_usecs;
int points, cpu;
unsigned long flags;
@@ -902,10 +891,10 @@ static void *__ipipe_max_prtrace_start(s
/* find the longest of all per-cpu paths */
print_path = NULL;
for_each_online_cpu(cpu) {
- path = &trace_paths[cpu][max_path[cpu]];
+ tp = &per_cpu(trace_path, cpu)[per_cpu(max_path, cpu)];
if ((print_path == NULL) ||
- (path->length > print_path->length)) {
- print_path = path;
+ (tp->length > print_path->length)) {
+ print_path = tp;
break;
}
}
@@ -1052,7 +1041,7 @@ static void *__ipipe_frozen_prtrace_star
mutex_lock(&out_mutex);
if (!n) {
- struct ipipe_trace_path *path;
+ struct ipipe_trace_path *tp;
int cpu;
unsigned long flags;
@@ -1064,9 +1053,9 @@ static void *__ipipe_frozen_prtrace_star
/* find the first of all per-cpu frozen paths */
print_path = NULL;
for_each_online_cpu(cpu) {
- path = &trace_paths[cpu][frozen_path[cpu]];
- if (path->end >= 0) {
- print_path = path;
+ tp = &per_cpu(trace_path, cpu)[per_cpu(frozen_path, cpu)];
+ if (tp->end >= 0) {
+ print_path = tp;
break;
}
}
@@ -1282,19 +1271,22 @@ void __init __ipipe_init_tracer(void)
int cpu, path;
for_each_possible_cpu(cpu) {
- trace_paths[cpu] = vmalloc(
- sizeof(struct ipipe_trace_path) * IPIPE_TRACE_PATHS);
- if (trace_paths[cpu] == NULL) {
+ struct ipipe_trace_path *tp_buf;
+
+ tp_buf = vmalloc_node(sizeof(struct ipipe_trace_path) *
+ IPIPE_TRACE_PATHS, cpu_to_node(cpu));
+ if (!tp_buf) {
printk(KERN_ERR "I-pipe: "
"insufficient memory for trace buffer.\n");
return;
}
- memset(trace_paths[cpu], 0,
- sizeof(struct ipipe_trace_path) * IPIPE_TRACE_PATHS);
+ memset(tp_buf, 0,
+ sizeof(struct ipipe_trace_path) * IPIPE_TRACE_PATHS);
for (path = 0; path < IPIPE_TRACE_PATHS; path++) {
- trace_paths[cpu][path].begin = -1;
- trace_paths[cpu][path].end = -1;
+ tp_buf[path].begin = -1;
+ tp_buf[path].end = -1;
}
+ per_cpu(trace_path, cpu) = tp_buf;
}
#endif /* CONFIG_IPIPE_TRACE_VMALLOC */
ipipe_trace_enable = CONFIG_IPIPE_TRACE_ENABLE_VALUE;
_______________________________________________
Adeos-main mailing list
[email protected]
https://mail.gna.org/listinfo/adeos-main