aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2012-09-14 12:52:10 -0400
committerOleg Nesterov <oleg@redhat.com>2012-09-29 15:21:53 -0400
commit1b08e907211cdc744f54871736005d9f3e7f182c (patch)
treedf62046438501ecd89e0bac1fb9b73edaf622e15
parent0578a97098dab967ece4b025fe5eb4984c4c86c0 (diff)
uprobes: Kill UTASK_BP_HIT state
Kill UTASK_BP_HIT state, it buys nothing but complicates the code. It is only used in uprobe_notify_resume() to decide who should be called, we can check utask->active_uprobe != NULL instead. And this allows us to simplify handle_swbp(), no need to clear utask->state. Likewise we could kill UTASK_SSTEP, but UTASK_BP_HIT is worse and imho should die. The problem is, it creates the special case when task->utask is NULL, we can't distinguish RUNNING and BP_HIT. With this patch utask == NULL always means RUNNING. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
-rw-r--r--include/linux/uprobes.h1
-rw-r--r--kernel/events/uprobes.c29
2 files changed, 9 insertions, 21 deletions
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index e6f0331e3d45..18d839da6517 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -59,7 +59,6 @@ struct uprobe_consumer {
59#ifdef CONFIG_UPROBES 59#ifdef CONFIG_UPROBES
60enum uprobe_task_state { 60enum uprobe_task_state {
61 UTASK_RUNNING, 61 UTASK_RUNNING,
62 UTASK_BP_HIT,
63 UTASK_SSTEP, 62 UTASK_SSTEP,
64 UTASK_SSTEP_ACK, 63 UTASK_SSTEP_ACK,
65 UTASK_SSTEP_TRAPPED, 64 UTASK_SSTEP_TRAPPED,
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index d2392968d4e6..d3f5381e7482 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1469,10 +1469,6 @@ static void handle_swbp(struct pt_regs *regs)
1469 bp_vaddr = uprobe_get_swbp_addr(regs); 1469 bp_vaddr = uprobe_get_swbp_addr(regs);
1470 uprobe = find_active_uprobe(bp_vaddr, &is_swbp); 1470 uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
1471 1471
1472 utask = current->utask;
1473 if (utask)
1474 utask->state = UTASK_RUNNING;
1475
1476 if (!uprobe) { 1472 if (!uprobe) {
1477 if (is_swbp > 0) { 1473 if (is_swbp > 0) {
1478 /* No matching uprobe; signal SIGTRAP. */ 1474 /* No matching uprobe; signal SIGTRAP. */
@@ -1491,6 +1487,7 @@ static void handle_swbp(struct pt_regs *regs)
1491 return; 1487 return;
1492 } 1488 }
1493 1489
1490 utask = current->utask;
1494 if (!utask) { 1491 if (!utask) {
1495 utask = add_utask(); 1492 utask = add_utask();
1496 /* Cannot allocate; re-execute the instruction. */ 1493 /* Cannot allocate; re-execute the instruction. */
@@ -1547,13 +1544,12 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs)
1547} 1544}
1548 1545
1549/* 1546/*
1550 * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag. (and on 1547 * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag and
1551 * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and 1548 * allows the thread to return from interrupt. After that handle_swbp()
1552 * allows the thread to return from interrupt. 1549 * sets utask->active_uprobe.
1553 * 1550 *
1554 * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and 1551 * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag
1555 * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from 1552 * and allows the thread to return from interrupt.
1556 * interrupt.
1557 * 1553 *
1558 * While returning to userspace, thread notices the TIF_UPROBE flag and calls 1554 * While returning to userspace, thread notices the TIF_UPROBE flag and calls
1559 * uprobe_notify_resume(). 1555 * uprobe_notify_resume().
@@ -1563,10 +1559,10 @@ void uprobe_notify_resume(struct pt_regs *regs)
1563 struct uprobe_task *utask; 1559 struct uprobe_task *utask;
1564 1560
1565 utask = current->utask; 1561 utask = current->utask;
1566 if (!utask || utask->state == UTASK_BP_HIT) 1562 if (utask && utask->active_uprobe)
1567 handle_swbp(regs);
1568 else
1569 handle_singlestep(utask, regs); 1563 handle_singlestep(utask, regs);
1564 else
1565 handle_swbp(regs);
1570} 1566}
1571 1567
1572/* 1568/*
@@ -1575,17 +1571,10 @@ void uprobe_notify_resume(struct pt_regs *regs)
1575 */ 1571 */
1576int uprobe_pre_sstep_notifier(struct pt_regs *regs) 1572int uprobe_pre_sstep_notifier(struct pt_regs *regs)
1577{ 1573{
1578 struct uprobe_task *utask;
1579
1580 if (!current->mm || !test_bit(MMF_HAS_UPROBES, &current->mm->flags)) 1574 if (!current->mm || !test_bit(MMF_HAS_UPROBES, &current->mm->flags))
1581 return 0; 1575 return 0;
1582 1576
1583 utask = current->utask;
1584 if (utask)
1585 utask->state = UTASK_BP_HIT;
1586
1587 set_thread_flag(TIF_UPROBE); 1577 set_thread_flag(TIF_UPROBE);
1588
1589 return 1; 1578 return 1;
1590} 1579}
1591 1580