Update copyright to LGPL on all files
[dyninst.git] / testsuite / src / dyninst / test_thread_2.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: test_thread_2.C,v 1.1 2008/10/30 19:22:28 legendre Exp $
33 /*
34  * #Name: test12_3
35  * #Desc: thread create callback
36  * #Dep: 
37  * #Arch: all
38  * #Notes:
39  */
40
41 #include <vector>
42 using std::vector;
43 #include "BPatch.h"
44 #include "BPatch_Vector.h"
45 #include "BPatch_thread.h"
46 #include "BPatch_snippet.h"
47
48 #include "test_lib.h"
49 #include "test12.h"
50
51 #include "dyninst_comp.h"
52 class test_thread_2_Mutator : public DyninstMutator {
53 private:
54   BPatch *bpatch;
55
56   void dumpVars();
57   bool setVar(const char *vname, void *addr, int testno, const char *testname);
58   bool getVar(const char *vname, void *addr, int len, int testno,
59               const char *testname);
60
61 public:
62   virtual bool hasCustomExecutionPath() { return true; }
63   virtual test_results_t setup(ParameterDict &param);
64   virtual test_results_t executeTest();
65 };
66 extern "C" DLLEXPORT TestMutator *test_thread_2_factory() {
67   return new test_thread_2_Mutator();
68 }
69
70 #define TESTNO 3
71 #define TESTNAME "test_thread_2"
72 #define TESTDESC "thread create callback"
73
74 static int debugPrint;
75
76 void test_thread_2_Mutator::dumpVars() {
77   BPatch_Vector<BPatch_variableExpr *> vars;
78   appImage->getVariables(vars);
79   for (unsigned int i = 0; i < vars.size(); ++i) {
80     logerror("\t%s\n", vars[i]->getName());
81   }
82 }
83
84
85 // Returns true on error, false on success
86 bool test_thread_2_Mutator::setVar(const char *vname, void *addr, int testno,
87                                    const char *testname) {
88   BPatch_variableExpr *v;
89    void *buf = addr;
90    if (NULL == (v = appImage->findVariable(vname))) {
91       logerror("**Failed test #%d (%s)\n", testno, testname);
92       logerror("  cannot find variable %s, avail vars:\n", vname);
93       dumpVars();
94       return true;
95    }
96
97    if (! v->writeValue(buf, sizeof(int),true)) {
98       logerror("**Failed test #%d (%s)\n", testno, testname);
99       logerror("  failed to write call site var to mutatee\n");
100       return true;
101    }
102    return false; // No error
103 }
104
105
106 // Returns true on error, false on success
107 bool test_thread_2_Mutator::getVar(const char *vname, void *addr, int len,
108                                    int testno, const char *testname) {
109    BPatch_variableExpr *v;
110    if (NULL == (v = appImage->findVariable(vname))) {
111       logerror("**Failed test #%d (%s)\n", testno, testname);
112       logerror("  cannot find variable %s: avail vars:\n", vname);
113       dumpVars();
114       return true;
115    }
116
117    if (! v->readValue(addr, len)) {
118       logerror("**Failed test #%d (%s)\n", testno, testname);
119       logerror("  failed to read var in mutatee\n");
120       return true;
121    }
122    return false; // No error
123 }
124
125
126 static vector<unsigned long> callback_tids;
127 static int test3_threadCreateCounter = 0;
128 static void threadCreateCB(BPatch_process * proc, BPatch_thread *thr)
129 {
130   assert(thr);  
131   if (debugPrint)
132      dprintf("%s[%d]:  thread %lu start event for pid %d\n", __FILE__, __LINE__,
133                thr->getTid(), thr->getPid());
134   test3_threadCreateCounter++;
135   callback_tids.push_back(thr->getTid());
136   if (thr->isDeadOnArrival()) {
137      dprintf("%s[%d]:  thread %lu is doa \n", __FILE__, __LINE__, thr->getTid());
138   }
139 }
140
141 // static bool mutatorTest3and4(int testno, const char *testname)
142 test_results_t test_thread_2_Mutator::executeTest() {
143   test3_threadCreateCounter = 0;
144   callback_tids.clear();
145
146   unsigned int timeout = 0; // in ms
147   int err = 0;
148
149   BPatchAsyncThreadEventCallback createcb = threadCreateCB;
150   if (!bpatch->registerThreadEventCallback(BPatch_threadCreateEvent, createcb))
151   {
152     FAIL_MES(TESTNAME, TESTDESC);
153     logerror("%s[%d]:  failed to register thread callback\n",
154              __FILE__, __LINE__);
155     appThread->getProcess()->terminateExecution();
156     return FAILED;
157   }
158
159 #if 0
160   //  unset mutateeIde to trigger thread (10) spawn.
161   int zero = 0;
162   // FIXME Check the return code for setVar
163   setVar("mutateeIdle", (void *) &zero, TESTNO, TESTDESC);
164   dprintf("%s[%d]:  continue execution for test %d\n", __FILE__, __LINE__, TESTNO);
165   appThread->continueExecution();
166 #endif
167
168   //  wait until we have received the desired number of events
169   //  (or timeout happens)
170
171   BPatch_Vector<BPatch_thread *> threads;
172   BPatch_process *appProc = appThread->getProcess();
173   assert(appProc);
174   appProc->getThreads(threads);
175   int active_threads = 11; // FIXME Magic number
176   threads.clear();
177   while (((test3_threadCreateCounter < TEST3_THREADS)
178          || (active_threads > 1))
179          && (timeout < TIMEOUT)) {
180     dprintf("%s[%d]: waiting for completion for test %d, num active threads = %d\n",
181             __FILE__, __LINE__, TESTNO, active_threads);
182     sleep_ms(SLEEP_INTERVAL/*ms*/);
183     timeout += SLEEP_INTERVAL;
184     if (appThread->isTerminated()) {
185        logerror("%s[%d]:  BAD NEWS:  somehow the process died\n", __FILE__, __LINE__);
186        err = 1;
187        break;
188     }
189     bpatch->pollForStatusChange();
190     if (appThread->isStopped()) {
191        appThread->continueExecution();
192     }
193     appProc->getThreads(threads);
194     active_threads = threads.size();
195     threads.clear();
196   }
197
198   if (timeout >= TIMEOUT) {
199     FAIL_MES(TESTNAME, TESTDESC);
200     logerror("%s[%d]:  test timed out. got %d/10 events\n",
201            __FILE__, __LINE__, test3_threadCreateCounter);
202     err = 1;
203   }
204
205   dprintf("%s[%d]: ending test %d, num active threads = %d\n",
206             __FILE__, __LINE__, TESTNO, active_threads);
207   dprintf("%s[%d]:  stop execution for test %d\n", __FILE__, __LINE__, TESTNO);
208   appThread->stopExecution();
209
210   //   read all tids from the mutatee and verify that we got them all
211   unsigned long mutatee_tids[TEST3_THREADS];
212   const char *threads_varname = "test3_threads";
213   if (getVar(threads_varname, (void *) mutatee_tids,
214              (sizeof(unsigned long) * TEST3_THREADS),
215              TESTNO, TESTDESC)) {
216     appThread->getProcess()->terminateExecution();
217     return FAILED;
218   }
219
220   if (debugPrint) {
221     dprintf("%s[%d]:  read following tids for test%d from mutatee\n", __FILE__, __LINE__, TESTNO);
222
223     for (unsigned int i = 0; i < TEST3_THREADS; ++i) {
224        dprintf("\t%lu\n", mutatee_tids[i]);
225     }
226   }
227
228   for (unsigned int i = 0; i < TEST3_THREADS; ++i) {
229      bool found = false;
230      for (unsigned int j = 0; j < callback_tids.size(); ++j) {
231        if (callback_tids[j] == mutatee_tids[i]) {
232          found = true;
233          break;
234        }
235      }
236
237     if (!found) {
238       FAIL_MES(TESTNAME, TESTDESC);
239       logerror("%s[%d]:  could not find record for tid %lu: have these:\n",
240              __FILE__, __LINE__, mutatee_tids[i]);
241        for (unsigned int j = 0; j < callback_tids.size(); ++j) {
242           logerror("%lu\n", callback_tids[j]);
243        }
244       err = 1;
245       break;
246     }
247   }
248
249   dprintf("%s[%d]: removing thread callback\n", __FILE__, __LINE__);
250   if (!bpatch->removeThreadEventCallback(BPatch_threadCreateEvent, createcb)) {
251     FAIL_MES(TESTNAME, TESTDESC);
252     logerror("%s[%d]:  failed to remove thread callback\n",
253            __FILE__, __LINE__);
254     err = 1;
255   }
256
257   if (!err)  {
258     PASS_MES(TESTNAME, TESTDESC);
259     appThread->getProcess()->terminateExecution();
260     return PASSED;
261   }
262   appThread->getProcess()->terminateExecution();
263   return FAILED;
264 }
265 // extern "C" int test12_3_mutatorMAIN(ParameterDict &param)
266 test_results_t test_thread_2_Mutator::setup(ParameterDict &param) {
267   DyninstMutator::setup(param);
268   bpatch = (BPatch *)(param["bpatch"]->getPtr());
269   debugPrint = param["debugPrint"]->getInt();
270
271   return PASSED;
272 }