Messages in this thread Patch in this message | | | From | Frederic Weisbecker <> | Subject | [RFC PATCH 07/10] ftrace: Make the function hashlist concurrently usable | Date | Fri, 22 Jan 2010 02:16:19 +0100 |
| |
Allow the function hashlist to be usable by simultaneous users. The function tracers can then plug in for their own needs.
This introduces a get/put_function_hlist() that keeps track of the hashlist users for allocation and release.
We also introduce function_hlist_reset_profile() that resets the function profiling statistics on a function hashlist already in use.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> --- kernel/trace/ftrace.c | 5 ++- kernel/trace/functions_hlist.c | 56 ++++++++++++++++++++++++++++++++++++++- kernel/trace/functions_hlist.h | 5 ++- 3 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 0ded01c..027743c 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -490,11 +490,12 @@ ftrace_profile_write(struct file *filp, const char __user *ubuf, mutex_lock(&ftrace_profile_lock); if (ftrace_profile_enabled ^ val) { if (val) { - ret = function_hlist_init(); + ret = get_function_hlist(); if (ret < 0) { cnt = ret; goto out; } + function_hlist_reset_profile(); ret = register_ftrace_profiler(); if (ret < 0) { @@ -509,7 +510,7 @@ ftrace_profile_write(struct file *filp, const char __user *ubuf, * so this acts like an synchronize_sched. */ unregister_ftrace_profiler(); - function_hlist_release(); + put_function_hlist(); } } out: diff --git a/kernel/trace/functions_hlist.c b/kernel/trace/functions_hlist.c index c79c4c5..d682213 100644 --- a/kernel/trace/functions_hlist.c +++ b/kernel/trace/functions_hlist.c @@ -20,6 +20,39 @@ DEFINE_PER_CPU(struct func_hlist, func_hlist_cpu); int functions_hash_bits __read_mostly; +static atomic_t hlist_refcount; + + +static void function_hlist_reset_profile_cpu(int cpu) +{ + struct func_hlist *hlist = &per_cpu(func_hlist_cpu, cpu); + struct hlist_head *head; + struct hlist_node *node; + struct func_node *rec; + int i; + + for (i = 0; i < FUNCTIONS_HLIST_SIZE; i++) { + head = &hlist->hash[i]; + + if (hlist_empty(head)) + continue; + + hlist_for_each_entry(rec, node, head, node) { + rec->counter = 0; +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + rec->time = 0; +#endif + } + } +} + +void function_hlist_reset_profile(void) +{ + int cpu; + + for_each_online_cpu(cpu) + function_hlist_reset_profile_cpu(cpu); +} static void __function_hlist_release(struct func_hlist *hlist) { @@ -115,7 +148,7 @@ static int function_hlist_init_cpu(int cpu) return 0; } -void function_hlist_release(void) +static void function_hlist_release(void) { int cpu; struct func_hlist *hlist; @@ -126,7 +159,7 @@ void function_hlist_release(void) } } -int function_hlist_init(void) +static int function_hlist_init(void) { int cpu; int ret = 0; @@ -140,6 +173,25 @@ int function_hlist_init(void) return ret; } +int get_function_hlist(void) +{ + int ret = 0; + + if (atomic_inc_return(&hlist_refcount) == 1) { + ret = function_hlist_init(); + if (ret < 0) + atomic_dec(&hlist_refcount); + } + + return ret; +} + +void put_function_hlist(void) +{ + if (!atomic_dec_return(&hlist_refcount)) + function_hlist_release(); +} + struct func_node * function_find_hlist_node(struct func_hlist *hlist, unsigned long ip) { diff --git a/kernel/trace/functions_hlist.h b/kernel/trace/functions_hlist.h index 8001f95..a4655c7 100644 --- a/kernel/trace/functions_hlist.h +++ b/kernel/trace/functions_hlist.h @@ -35,5 +35,6 @@ function_find_hlist_node(struct func_hlist *hlist, unsigned long ip); struct func_node * function_hlist_record_alloc(struct func_hlist *hlist, unsigned long ip); -int function_hlist_init(void); -void function_hlist_release(void); +int get_function_hlist(void); +void put_function_hlist(void); +void function_hlist_reset_profile(void); -- 1.6.2.3
| |