Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 100569
b: refs/heads/master
c: 0eb9670
h: refs/heads/master
i:
  100567: 522d644
v: v3
  • Loading branch information
Abhishek Sagar authored and Ingo Molnar committed Jun 10, 2008
1 parent 82828cd commit b7c9923
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e0773410247f1e5fc6f7c52a4c5f3c6c9873d527
refs/heads/master: 0eb967012ea15e6e8cfab483d9fa37bc602d400c
1 change: 1 addition & 0 deletions trunk/include/linux/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ enum {
FTRACE_FL_FILTER = (1 << 2),
FTRACE_FL_ENABLED = (1 << 3),
FTRACE_FL_NOTRACE = (1 << 4),
FTRACE_FL_CONVERTED = (1 << 5),
};

struct dyn_ftrace {
Expand Down
76 changes: 46 additions & 30 deletions trunk/kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ ftrace_add_hash(struct dyn_ftrace *node, unsigned long key)
hlist_add_head_rcu(&node->node, &ftrace_hash[key]);
}

/* called from kstop_machine */
static inline void ftrace_del_hash(struct dyn_ftrace *node)
{
hlist_del(&node->node);
}

static void ftrace_free_rec(struct dyn_ftrace *rec)
{
/* no locking, only called from kstop_machine */
Expand Down Expand Up @@ -332,12 +338,11 @@ ftrace_record_ip(unsigned long ip)
#define FTRACE_ADDR ((long)(ftrace_caller))
#define MCOUNT_ADDR ((long)(mcount))

static void
static int
__ftrace_replace_code(struct dyn_ftrace *rec,
unsigned char *old, unsigned char *new, int enable)
{
unsigned long ip, fl;
int failed;

ip = rec->ip;

Expand All @@ -364,7 +369,7 @@ __ftrace_replace_code(struct dyn_ftrace *rec,

if ((fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) ||
(fl == 0) || (rec->flags & FTRACE_FL_NOTRACE))
return;
return 0;

/*
* If it is enabled disable it,
Expand All @@ -388,42 +393,32 @@ __ftrace_replace_code(struct dyn_ftrace *rec,
*/
fl = rec->flags & (FTRACE_FL_NOTRACE | FTRACE_FL_ENABLED);
if (fl == FTRACE_FL_NOTRACE)
return;
return 0;

new = ftrace_call_replace(ip, FTRACE_ADDR);
} else
old = ftrace_call_replace(ip, FTRACE_ADDR);

if (enable) {
if (rec->flags & FTRACE_FL_ENABLED)
return;
return 0;
rec->flags |= FTRACE_FL_ENABLED;
} else {
if (!(rec->flags & FTRACE_FL_ENABLED))
return;
return 0;
rec->flags &= ~FTRACE_FL_ENABLED;
}
}

failed = ftrace_modify_code(ip, old, new);
if (failed) {
unsigned long key;
/* It is possible that the function hasn't been converted yet */
key = hash_long(ip, FTRACE_HASHBITS);
if (!ftrace_ip_in_hash(ip, key)) {
rec->flags |= FTRACE_FL_FAILED;
ftrace_free_rec(rec);
}

}
return ftrace_modify_code(ip, old, new);
}

static void ftrace_replace_code(int enable)
{
int i, failed;
unsigned char *new = NULL, *old = NULL;
struct dyn_ftrace *rec;
struct ftrace_page *pg;
int i;

if (enable)
old = ftrace_nop_replace();
Expand All @@ -438,7 +433,15 @@ static void ftrace_replace_code(int enable)
if (rec->flags & FTRACE_FL_FAILED)
continue;

__ftrace_replace_code(rec, old, new, enable);
failed = __ftrace_replace_code(rec, old, new, enable);
if (failed && (rec->flags & FTRACE_FL_CONVERTED)) {
rec->flags |= FTRACE_FL_FAILED;
if ((system_state == SYSTEM_BOOTING) ||
!kernel_text_address(rec->ip)) {
ftrace_del_hash(rec);
ftrace_free_rec(rec);
}
}
}
}
}
Expand Down Expand Up @@ -467,7 +470,6 @@ ftrace_code_disable(struct dyn_ftrace *rec)
failed = ftrace_modify_code(ip, call, nop);
if (failed) {
rec->flags |= FTRACE_FL_FAILED;
ftrace_free_rec(rec);
return 0;
}
return 1;
Expand Down Expand Up @@ -621,8 +623,7 @@ unsigned long ftrace_update_tot_cnt;
static int __ftrace_update_code(void *ignore)
{
struct dyn_ftrace *p;
struct hlist_head head;
struct hlist_node *t;
struct hlist_node *t, *n;
int save_ftrace_enabled;
cycle_t start, stop;
int i;
Expand All @@ -637,18 +638,33 @@ static int __ftrace_update_code(void *ignore)

/* No locks needed, the machine is stopped! */
for (i = 0; i < FTRACE_HASHSIZE; i++) {
if (hlist_empty(&ftrace_hash[i]))
continue;
/* all CPUS are stopped, we are safe to modify code */
hlist_for_each_entry_safe(p, t, n, &ftrace_hash[i], node) {
/* Skip over failed records which have not been
* freed. */
if (p->flags & FTRACE_FL_FAILED)
continue;

head = ftrace_hash[i];
INIT_HLIST_HEAD(&ftrace_hash[i]);
/* Unconverted records are always at the head of the
* hash bucket. Once we encounter a converted record,
* simply skip over to the next bucket. Saves ftraced
* some processor cycles (ftrace does its bid for
* global warming :-p ). */
if (p->flags & (FTRACE_FL_CONVERTED))
break;

/* all CPUS are stopped, we are safe to modify code */
hlist_for_each_entry(p, t, &head, node) {
if (ftrace_code_disable(p))
if (ftrace_code_disable(p)) {
p->flags |= FTRACE_FL_CONVERTED;
ftrace_update_cnt++;
}
} else {
if ((system_state == SYSTEM_BOOTING) ||
!kernel_text_address(p->ip)) {
ftrace_del_hash(p);
ftrace_free_rec(p);

}
}
}
}

stop = ftrace_now(raw_smp_processor_id());
Expand Down

0 comments on commit b7c9923

Please sign in to comment.