Problem 1:
[dyninst.git] / dyninstAPI / src / callbacks.C
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include "callbacks.h"
5 #include "mailbox.h"
6 #include "EventHandler.h"
7 #include "util.h"
8 #include "showerror.h"
9 #include "process.h"
10
11 CallbackManager *callback_manager = NULL;
12 CallbackManager *getCBManager()
13 {
14   if (callback_manager == NULL)
15     callback_manager = new CallbackManager();
16   return callback_manager;
17 }
18
19 bool CallbackManager::registerCallback(eventType evt, CallbackBase *cb)
20 {
21   pdvector<CallbackBase *> &cbs_for_type = cbs[evt];
22   cbs_for_type.push_back(cb);
23   return true;
24 }
25
26 bool CallbackManager::removeCallbacks(eventType evt, pdvector<CallbackBase *> &cbs_out)
27 {
28   if (cbs.defines(evt)) {
29     pdvector<CallbackBase *> cbs_for_type = cbs.get_and_remove(evt);
30     for (unsigned int i = 0; i < cbs_for_type.size(); ++i) {
31       cbs_out.push_back(cbs_for_type[i]); 
32     }
33   }
34   else  {
35     mailbox_printf("%s[%d]:  no callbacks matching %s\n", 
36                    FILE__, __LINE__, eventType2str(evt));
37     return false;
38   }
39   return true;
40 }
41
42 bool CallbackManager::dispenseCallbacksMatching(eventType evt, pdvector<CallbackBase *> &cbs_out)
43 {
44   if (cbs_out.size()) {
45     fprintf(stderr, "%s[%d]:  WARN, dispenseCallbacksMatching (%s) appending to existing callbacks\n", FILE__, __LINE__, eventType2str(evt));
46   }
47
48   if (cbs.defines(evt)) {
49     pdvector<CallbackBase *> &cbs_for_type = cbs[evt];
50     for (unsigned int i = 0; i < cbs_for_type.size(); ++i) {
51       CallbackBase *newcb = cbs_for_type[i]->copy(); 
52       cbs_out.push_back(newcb); 
53     }
54   }
55   else  {
56     mailbox_printf("%s[%d]:  no callbacks matching %s\n", 
57                    FILE__, __LINE__, eventType2str(evt));
58     return false;
59   }
60   return true;
61
62 }
63
64 void SyncCallback::signalCompletion(CallbackBase *cb) 
65 {
66      //fprintf(stderr, "%s[%d]:  welcome to singal completion\n", FILE__, __LINE__);
67      SyncCallback *scb = (SyncCallback *) cb;
68      scb->lock->_Lock(FILE__, __LINE__);
69      scb->completion_signalled = true;
70      if (scb->sh)
71        scb->sh->wait_cb = NULL;
72      signal_printf("%s[%d]: SyncCallback, signalling completion, sh = %s\n", FILE__, __LINE__, scb->sh ? scb->sh->getName() : "null");
73      mailbox_printf("%s[%d][%s]:  signalling completion of callback\n",
74              FILE__, __LINE__, getThreadStr(getExecThreadID()));
75      scb->lock->_Broadcast(FILE__, __LINE__);
76      scb->lock->_Unlock(FILE__, __LINE__);
77 }
78
79 bool SyncCallback::waitForCompletion() 
80 {
81     //  Assume that we are already locked upon entry
82     assert(lock);
83     assert(lock->depth());
84     assert(lock == global_mutex);
85     //  we need to find the signal
86     //  handler that has this thread id -- ie, find out if we are running on a 
87     //  signal handler thread.  Since we do not have an easy way of getting 
88     //  this object, we need to search for it:
89
90     extern pdvector<process *> processVec;
91     for (unsigned int i = 0; i < processVec.size(); ++i) {
92         if (processVec[i]) {
93             if (processVec[i]->status() != deleted && processVec[i]->sh)
94                 if (NULL != (sh = processVec[i]->sh->findSHWithThreadID(getExecThreadID())))
95                     break;
96         }
97     }
98     signal_printf("%s[%d]: SyncCallback, waiting for completion, sh = %p\n", FILE__, __LINE__, sh ? sh->getName() : "null");
99     if (sh)
100       sh->wait_cb = (CallbackBase *) this;
101
102     while (!completion_signalled) {
103       if (!lock) {
104         fprintf(stderr, "%s[%d]:  LOCK IS GONE!!\n", FILE__, __LINE__);
105         return false;
106       }
107       mailbox_printf("%s[%d][%s]:  waiting for completion of callback\n",
108              FILE__, __LINE__, getThreadStr(getExecThreadID()));
109       if (0 != lock->_Broadcast(FILE__, __LINE__)) assert(0);
110       if (0 != lock->_WaitForSignal(FILE__, __LINE__)) assert(0);
111     }
112     return true;
113 }
114
115 bool SyncCallback::execute() 
116 {
117   unsigned int need_to_relock = 0;
118   lock->_Lock(FILE__, __LINE__);
119   while (lock->depth()-1) {
120     lock->_Unlock(FILE__, __LINE__);
121     need_to_relock++;
122   }
123   lock->_Unlock(FILE__, __LINE__);
124
125   execute_real();
126
127   while (need_to_relock--) 
128     lock->_Lock(FILE__, __LINE__);
129   return true;
130 }
131
132 bool SyncCallback::do_it()
133 {
134   bool reset_delete_enabled = false;
135   if (synchronous) {
136     if (deleteEnabled()) {
137        enableDelete(false);
138        reset_delete_enabled = true;
139     }
140   }
141
142   getMailbox()->executeOrRegisterCallback(this);
143   if (synchronous) {
144     signal_printf("%s[%d]:  waiting for completion of callback\n", FILE__, __LINE__);
145     waitForCompletion();
146     if (reset_delete_enabled)
147        enableDelete();
148   }
149   return true;
150 }
151
152 ErrorCallback::~ErrorCallback()
153 {
154   //  need to free memory allocated for the arguments 
155   if (str) free(str);
156 }
157
158 bool ErrorCallback::execute_real(void) 
159 {
160   cb(sev, num, (const char **)&str);
161   return true;
162 }
163
164 bool ErrorCallback::operator()(BPatchErrorLevel severity, int number,
165                           const char *error_string)
166 {
167   //  Assume that we are already locked upon entry
168   assert(lock->depth());
169
170   str = strdup(error_string);
171   num = number;
172   sev = severity;    
173
174   return do_it();
175 }
176
177 bool ForkCallback::execute_real(void) 
178 {
179   cb(par, chld);
180   return true;
181 }
182
183 bool ForkCallback::operator()(BPatch_thread *parent, BPatch_thread *child)
184 {
185   assert(lock->depth());
186   par = parent;
187   chld = child;
188
189   return do_it();
190 }
191
192 bool ExecCallback::execute_real(void) 
193 {
194   cb(thread);
195   return true;
196 }
197
198 bool ExecCallback::operator()(BPatch_thread *thr)
199 {
200   assert(lock->depth());
201   thread = thr;
202
203   return do_it();
204 }
205
206 bool ExitCallback::execute_real(void) 
207 {
208   cb(thread, type);
209   return true;
210 }
211
212 bool ExitCallback::operator()(BPatch_thread *thr, BPatch_exitType exit_type)
213 {
214   assert(lock->depth());
215   thread = thr;;
216   type = exit_type;
217
218   return do_it();
219 }
220
221 bool SignalCallback::execute_real(void) 
222 {
223     cb(thread, num);
224     return true;
225 }
226
227 bool SignalCallback::operator()(BPatch_thread *thr, int sigNum)
228 {
229   assert(lock->depth());
230   thread = thr;
231   num = sigNum;
232
233   return do_it();
234 }
235
236 bool OneTimeCodeCallback::execute_real(void) 
237 {
238   cb(thread, user_data, return_value);
239   return true;
240 }
241
242 bool OneTimeCodeCallback::operator()(BPatch_thread *thr, void *userData, void *returnValue)
243 {
244   assert(lock->depth());
245   thread = thr;
246   user_data = userData;
247   return_value = returnValue;
248
249   return do_it();
250 }
251
252 bool DynLibraryCallback::execute_real(void) 
253 {
254   cb(thread, mod, load_param);
255   return true;
256 }
257
258 bool DynLibraryCallback::operator()(BPatch_thread *thr, BPatch_module *module, bool load)
259 {
260   assert(lock->depth());
261   thread = thr;
262   mod = module;
263   load_param = load;
264
265   return do_it();
266 }
267
268 bool DynamicCallsiteCallback::execute_real(void) 
269 {
270   cb(pt, func);
271   return true;
272 }
273
274 bool DynamicCallsiteCallback::operator()(BPatch_point *at_point, 
275                                          BPatch_function *called_function)
276 {
277   assert(lock->depth());
278   pt = at_point;
279   func = called_function;
280
281   return do_it();
282 }
283
284 UserEventCallback::~UserEventCallback()
285 {
286   if (buf) delete [] (int *)buf;
287 }
288
289 bool UserEventCallback::execute_real(void) 
290 {
291   cb(proc, buf, bufsize);
292   return true;
293 }
294
295 bool UserEventCallback::operator()(BPatch_process *process, void *buffer, int buffersize)
296 {
297   assert(lock->depth());
298   proc = process;
299   bufsize = buffersize;
300   buf = new int [buffersize];
301   memcpy(buf, buffer, buffersize); 
302
303   return do_it();
304 }
305
306 bool AsyncThreadEventCallback::execute_real(void) 
307 {
308   async_printf("%s[%d][%s]:  welcome to AsyncThreadEventCallback: execute\n", 
309           FILE__, __LINE__, getThreadStr(getExecThreadID()));
310   cb(proc, thr);
311   return true;
312 }
313
314 bool AsyncThreadEventCallback::operator()(BPatch_process *process, BPatch_thread *thread)
315 {
316   assert(lock->depth());
317   assert(process);
318   assert(thread);
319
320   proc = process;
321   thr = thread;
322
323   return do_it();
324 }
325
326 InternalThreadExitCallback::~InternalThreadExitCallback()
327 {
328   if (cbs) delete cbs;
329 }
330
331 bool InternalThreadExitCallback::execute_real(void) 
332 {
333   cb(proc, thr, cbs);
334   return true;
335 }
336
337 bool InternalThreadExitCallback::operator()(BPatch_process *p, BPatch_thread *t, 
338                                             pdvector<AsyncThreadEventCallback *> *callbacks)
339 {
340   assert(lock->depth());
341   proc = p;
342   thr = t;
343   cbs = callbacks;
344
345   return do_it();
346 }
347
348 #ifdef IBM_BPATCH_COMPAT
349 bool ThreadEventCallback::execute_real(void) 
350 {
351   cb(thr, a1, a2);
352   return true;
353 }
354
355 bool ThreadEventCallback::operator()(BPatch_thread *thread, void *arg1, void *arg2)
356 {
357   assert(lock->depth());
358   thr = thread;
359   a1 = arg1;
360   a2 = arg2;
361
362   return do_it();
363 }
364 #endif