summaryrefslogtreecommitdiffstats
path: root/tapsets.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'tapsets.cxx')
-rw-r--r--tapsets.cxx14
1 files changed, 14 insertions, 0 deletions
diff --git a/tapsets.cxx b/tapsets.cxx
index 12982259..5390ee2d 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -3506,8 +3506,15 @@ mark_derived_probe::emit_registrations (translator_output * o, unsigned i)
o->newline(1) << "void (**fn) (" << probe_sig_expanded << ") = (void *)"
<< address << "UL;";
+ o->newline() << "#if __HAVE_ARCH_CMPXCHG";
+ o->newline() << "unsigned long *fnpp = (unsigned long *) (void *) fn;";
+ o->newline() << "unsigned long fnp = (unsigned long) (void *) & enter_" << i << ";";
+ o->newline() << "unsigned long oldval = cmpxchg (fnpp, 0, fnp);";
+ o->newline() << "if (oldval != 0) rc = 1;"; // XXX: could retry a few times
+ o->newline() << "#else";
// XXX: need proper synchronization for concurrent registration attempts
o->newline() << "if (*fn == 0) *fn = & enter_" << i << ";";
+ o->newline() << "#endif";
o->newline() << "mb ();";
o->newline() << "if (*fn != & enter_" << i << ") rc = 1;";
@@ -3523,7 +3530,14 @@ mark_derived_probe::emit_deregistrations (translator_output * o, unsigned i)
o->newline() << "{";
o->newline(1) << "void (**fn) (" << probe_sig_expanded << ") = (void *)"
<< address << "UL;";
+ o->newline() << "#if __HAVE_ARCH_CMPXCHG";
+ o->newline() << "unsigned long *fnpp = (unsigned long *) (void *) fn;";
+ o->newline() << "unsigned long fnp = (unsigned long) (void *) & enter_" << i << ";";
+ o->newline() << "unsigned long oldval = cmpxchg (fnpp, fnp, 0);";
+ o->newline() << "if (oldval != fnp) ;"; // XXX: should not happen
+ o->newline() << "#else";
o->newline(0) << "*fn = 0;";
+ o->newline() << "#endif";
o->newline(-1) << "}";
}