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
|