[DynInst_API:] TLS-based trampguard patch


Date: Fri, 06 Feb 2015 14:54:48 -0600
From: Bill Williams <bill@xxxxxxxxxxx>
Subject: [DynInst_API:] TLS-based trampguard patch
As per discussion earlier this week, here's an initial implementation of TLS-based trampguards. It is not yet pushed to master; I've tested it locally but it has not been through serious cross-platform validation yet. Treat as experimental.

This should (mostly) obviate our hard-coded thread limits, and should produce modestly better performance in multithreaded code. These changes will not work with an old dyninst runtime library at present; that's backwards compatibility that I can wedge back in if anyone particularly cares. As always, feedback (both good and bad) is encouraged.

--bw

Bill Williams
Paradyn Project
bill@xxxxxxxxxxx
diff --git a/dyninstAPI/src/baseTramp.C b/dyninstAPI/src/baseTramp.C
index b19574d..764a260 100644
--- a/dyninstAPI/src/baseTramp.C
+++ b/dyninstAPI/src/baseTramp.C
@@ -307,78 +307,17 @@ bool baseTramp::generateCodeInlined(codeGen &gen,
 
    AstNodePtr minis = AstNode::sequenceNode(miniTramps);
 
-   // Let's build the tramp guard addr (if we want it)
-   AstNodePtr threadIndex;
-   AstNodePtr trampGuardAddr;
-
-   if (guarded() &&
-       minis->containsFuncCall() &&
-       (proc()->trampGuardAST() != AstNodePtr())) {
-      // If we don't have a function call, then we don't
-      // need the guard....
-
-      // Now, the guard flag. 
-      // If we're multithreaded, we need to index off
-      // the base address.
-
-      if (!threaded()) {
-         // ...
-      }
-      else if (gen.thread()) {
-         // Constant override...
-         threadIndex = AstNode::operandNode(AstNode::Constant,
-                                            (void *)(long)gen.thread()->getIndex());
-      }
-      else {
-         // TODO: we can get clever with this, and have the generation of
-         // the thread index depend on whether gen has a thread defined...
-         // For that, we'd need an AST thread index node. Just something
-         // to think about. Maybe a child of funcNode?
-         threadIndex = AstNode::threadIndexNode();
-      }
-        
-      if (threadIndex) {
-         trampGuardAddr = AstNode::operandNode(AstNode::DataIndir,
-                                               AstNode::operatorNode(plusOp,
-                                                                     AstNode::operatorNode(timesOp,
-                                                                                           threadIndex,
-                                                                                           AstNode::operandNode(AstNode::Constant, 
-                                                                                                                (void *)sizeof(unsigned))),
-                                                                     proc()->trampGuardAST()));
-
-         /* At the moment, we can't directly specify the fact
-            that we're loading 4 bytes instead of a normal
-            (address-width) word. */
-         trampGuardAddr->setType( BPatch::getBPatch()->builtInTypes->findBuiltInType( "unsigned int" ) );
-      }
-      else {
-         trampGuardAddr = AstNode::operandNode(AstNode::DataIndir,
-                                               proc()->trampGuardAST());
-         trampGuardAddr->setType( BPatch::getBPatch()->builtInTypes->findBuiltInType( "unsigned int" ) );
-      }
-   }
-
-
    AstNodePtr baseTrampSequence;
    pdvector<AstNodePtr > baseTrampElements;
 
-   if (trampGuardAddr) {
-      // First, set it to 0
-      baseTrampElements.push_back(AstNode::operatorNode(storeOp, 
-                                                        trampGuardAddr,
-                                                        AstNode::operandNode(AstNode::Constant,
-                                                                             (void *)0)));
-   }
     
    // Run the minitramps
    baseTrampElements.push_back(minis);
+   vector<AstNodePtr> empty_args;
     
-   if (trampGuardAddr) {
-      // And set the tramp guard flag to 1
-      baseTrampElements.push_back(AstNode::operatorNode(storeOp,
-                                                        trampGuardAddr,
-                                                        AstNode::operandNode(AstNode::Constant,
-                                                                             (void *)1)));
+   if (guarded() &&
+       minis->containsFuncCall()) {
+     baseTrampElements.push_back(AstNode::funcCallNode("DYNINST_unlock_tramp_guard", empty_args));
    }
 
    baseTrampSequence = AstNode::sequenceNode(baseTrampElements);
@@ -387,17 +326,17 @@ bool baseTramp::generateCodeInlined(codeGen &gen,
 
    // If trampAddr is non-NULL, then we wrap this with an IF. If not, 
    // we just run the minitramps.
-   if (trampGuardAddr == NULL) {
-      baseTrampAST = baseTrampSequence;
-      baseTrampSequence.reset();
-   }
-   else {
-      // Oh, boy. 
-      // Short form of the above
+   if (guarded() &&
+       minis->containsFuncCall()) {
       baseTrampAST = AstNode::operatorNode(ifOp,
-                                           trampGuardAddr,
+                                           // trampGuardAddr,
+					   AstNode::funcCallNode("DYNINST_lock_tramp_guard", empty_args),
                                            baseTrampSequence);
    }
+   else {
+      baseTrampAST = baseTrampSequence;
+      baseTrampSequence.reset();
+   }
 
 
 
diff --git a/dyninstAPI_RT/src/RTcommon.c b/dyninstAPI_RT/src/RTcommon.c
index 85e850c..88d1462 100644
--- a/dyninstAPI_RT/src/RTcommon.c
+++ b/dyninstAPI_RT/src/RTcommon.c
@@ -119,6 +119,25 @@ unsigned *DYNINST_tramp_guards;
 
 DLLEXPORT unsigned DYNINST_default_tramp_guards[MAX_THREADS+1];
 
+#if MSC_VER
+#define TLS_VAR __declspec(thread)
+#else
+#define TLS_VAR __thread
+#endif
+
+TLS_VAR int DYNINST_tls_tramp_guard = 1;
+
+DLLEXPORT int DYNINST_lock_tramp_guard()
+{
+  if(!DYNINST_tls_tramp_guard) return 0;
+  DYNINST_tls_tramp_guard = 0;
+  return 1;
+}
+DLLEXPORT void DYNINST_unlock_tramp_guard()
+{
+  DYNINST_tls_tramp_guard = 1;
+}
+
 #if defined(os_linux)
 void DYNINSTlinuxBreakPoint();
 #endif
[← Prev in Thread] Current Thread [Next in Thread→]