summaryrefslogtreecommitdiffstats
path: root/runtime/uprobes/uprobes.c
diff options
context:
space:
mode:
authorkenistoj <kenistoj>2008-01-25 23:55:04 +0000
committerkenistoj <kenistoj>2008-01-25 23:55:04 +0000
commitfb10329303b55f4b7af98237e65d72c030df13b0 (patch)
tree326cc0efa5719a742f95b7580b605fbc91273de0 /runtime/uprobes/uprobes.c
parent1939ea3217ce8b8fae35e4a70f4cd5c1c431e438 (diff)
downloadsystemtap-steved-fb10329303b55f4b7af98237e65d72c030df13b0.tar.gz
systemtap-steved-fb10329303b55f4b7af98237e65d72c030df13b0.tar.xz
systemtap-steved-fb10329303b55f4b7af98237e65d72c030df13b0.zip
* runtime/uprobes/uprobes.c: Within a probed process, serialize
calls to access_process_vm() when populating instructions slots. Fixes an SMP bug on multithreaded apps with many active probepoints. * runtime/uprobes/uprobes.h: Ditto
Diffstat (limited to 'runtime/uprobes/uprobes.c')
-rw-r--r--runtime/uprobes/uprobes.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c
index 501c4298..f0b72c46 100644
--- a/runtime/uprobes/uprobes.c
+++ b/runtime/uprobes/uprobes.c
@@ -649,6 +649,7 @@ static struct uprobe_process *uprobe_mk_process(struct task_struct *p)
uproc->ssol_area.insn_area = NULL;
uproc->ssol_area.initialized = 0;
mutex_init(&uproc->ssol_area.setup_mutex);
+ /* Initialize rest of area in uprobe_init_ssol(). */
#ifdef CONFIG_UPROBES_SSOL
uproc->sstep_out_of_line = 1;
#else
@@ -1257,6 +1258,7 @@ static noinline void uprobe_init_ssol(struct uprobe_process *uproc)
area->insn_area = ERR_PTR(-ENOMEM);
return;
}
+ mutex_init(&area->populate_mutex);
spin_lock_init(&area->lock);
area->next_slot = 0;
slot_addr = (char*) area->insn_area;
@@ -1405,8 +1407,10 @@ found_slot:
s->last_used = jiffies;
s->state = SSOL_ASSIGNED;
/* Copy the original instruction to the chosen slot. */
+ mutex_lock(&area->populate_mutex);
len = access_process_vm(current, (unsigned long)s->insn,
ppt->insn, MAX_UINSN_BYTES, 1);
+ mutex_unlock(&area->populate_mutex);
if (unlikely(len < MAX_UINSN_BYTES)) {
up_write(&s->rwsem);
printk(KERN_ERR "Failed to copy instruction at %#lx"
@@ -1450,12 +1454,18 @@ static struct uprobe_ssol_slot
static
struct uprobe_ssol_slot *uprobe_get_insn_slot(struct uprobe_probept *ppt)
{
- struct uprobe_ssol_slot *slot = ppt->slot;
+ struct uprobe_ssol_slot *slot;
+retry:
+ slot = ppt->slot;
if (unlikely(!slot))
return uprobe_find_insn_slot(ppt);
down_read(&slot->rwsem);
+ if (unlikely(slot != ppt->slot)) {
+ up_read(&slot->rwsem);
+ goto retry;
+ }
if (unlikely(slot->owner != ppt)) {
up_read(&slot->rwsem);
return uprobe_find_insn_slot(ppt);