This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] uprobes: fix SMP multithreading race


The enclosed patch fixes a problem seen on SMP systems when multiple
threads of a multithreaded app are pounding the probed instruction
when the uprobe is registered.  This patch applies atop the most recent
uprobes patch set, which I posted May 25 (May 26 UTC):
http://sources.redhat.com/ml/systemtap/2007-q2/msg00399.html

The problem was intermittent, but I was able to tickle it pretty
reliably using the enclosed script.  In the test suite, run
$ probe7-thread 1000000000		# 1 billion
and after that's started, run the script
# ./poundt
The bug causes probe7-thread to die with a SIGSEGV.  The fix allows
probe7-thread to run to completion.

Jim Keniston
----- poundt -----
#!/bin/bash
vaddr=`objdump -d probe7-thread | awk '$2=="<add>:" {print $1}'`
pid=`ps -e -o fname,pid | awk '$1=="probe7-t" {print $2}'`

kill -cont $pid

# While probed process runs...
while (ps -p $pid > /dev/null)
do
	sleep 0.2
	insmod probe5.ko verbose=0 vaddr=0x$vaddr pid=$pid
	if [ $? -ne 0 ]
	then
		exit 1
	fi
	sleep 0.2
	rmmod probe5
done
exit 0
-----

Fixes a problem seen on SMP systems when multiple threads of a multithreaded
app are pounding the probed instruction when the uprobe is registered.
uprobe_verify_ssol() was releasing the second thread through before SSOL
setup was complete.

---

 include/linux/uprobes.h |    3 +++
 kernel/uprobes.c        |    8 +++++---
 2 files changed, 8 insertions(+), 3 deletions(-)

diff -puN include/linux/uprobes.h~uprobes-smp-pounder-fix include/linux/uprobes.h
--- linux-2.6.21-rc6/include/linux/uprobes.h~uprobes-smp-pounder-fix	2007-06-09 11:21:05.000000000 -0700
+++ linux-2.6.21-rc6-jimk/include/linux/uprobes.h	2007-06-09 11:23:33.000000000 -0700
@@ -169,6 +169,9 @@ struct uprobe_ssol_area {
 
 	/* Ensures 2 threads don't try to set up the vma simultaneously. */
 	struct mutex setup_mutex;
+
+	/* 1 = we've at least tried.  IS_ERR(insn_area) if we failed. */
+	int initialized;
 };
 
 /*
diff -puN kernel/uprobes.c~uprobes-smp-pounder-fix kernel/uprobes.c
--- linux-2.6.21-rc6/kernel/uprobes.c~uprobes-smp-pounder-fix	2007-06-09 11:21:05.000000000 -0700
+++ linux-2.6.21-rc6-jimk/kernel/uprobes.c	2007-06-09 11:23:51.000000000 -0700
@@ -285,9 +285,9 @@ static void rouse_all_threads(struct upr
 		if (utask->quiescing) {
 			utask->quiescing = 0;
 			if (utask->state == UPTASK_QUIESCENT) {
-				clear_utrace_quiesce(utask);
 				utask->state = UPTASK_RUNNING;
 				uproc->n_quiescent_threads--;
+				clear_utrace_quiesce(utask);
 			}
 		}
 	}
@@ -533,6 +533,7 @@ static struct uprobe_process *uprobe_mk_
 	uproc->uretprobe_trampoline_addr = NULL;
 
 	uproc->ssol_area.insn_area = NULL;
+	uproc->ssol_area.initialized = 0;
 	mutex_init(&uproc->ssol_area.setup_mutex);
 #ifdef CONFIG_UPROBES_SSOL
 	uproc->sstep_out_of_line = 1;
@@ -1020,13 +1021,14 @@ static __user uprobe_opcode_t
 {
 	struct uprobe_ssol_area *area = &uproc->ssol_area;
 
-	if (unlikely(!area->insn_area)) {
+	if (unlikely(!area->initialized)) {
 		/* First time through for this probed process */
 		static DEFINE_MUTEX(ssol_setup_mutex);
 		mutex_lock(&ssol_setup_mutex);
-		if (likely(!area->insn_area))
+		if (likely(!area->initialized))
 			/* Nobody snuck in and set things up ahead of us. */
 			uprobe_init_ssol(uproc);
+			area->initialized = 1;
 		mutex_unlock(&ssol_setup_mutex);
 	}
 	return area->insn_area;
_

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]