Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / callbacks.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 #include <stdio.h>
32 #include <stdlib.h>
33
34 #include "dyninstAPI/src/callbacks.h"
35 #include "dyninstAPI/src/mailbox.h"
36 #include "dyninstAPI/src/EventHandler.h"
37 #include "dyninstAPI/src/util.h"
38 #include "dyninstAPI/src/debug.h"
39 #include "dyninstAPI/src/process.h"
40 #include "dyninstAPI/src/dyn_thread.h"
41 #include "dyninstAPI/src/signalgenerator.h"
42 #include "dyninstAPI/h/BPatch_thread.h"
43
44 CallbackManager *callback_manager = NULL;
45 CallbackManager *getCBManager()
46 {
47    if (callback_manager == NULL)
48       callback_manager = new CallbackManager();
49
50    return callback_manager;
51 }
52
53 bool CallbackManager::registerCallback(eventType evt, CallbackBase *cb)
54 {
55    pdvector<CallbackBase *> &cbs_for_type = cbs[evt];
56    cbs_for_type.push_back(cb);
57
58    return true;
59 }
60
61 bool CallbackManager::removeCallbacks(eventType evt, pdvector<CallbackBase *> &cbs_out)
62 {
63    if (cbs.defines(evt)) {
64       pdvector<CallbackBase *> cbs_for_type = cbs.get_and_remove(evt);
65       for (unsigned int i = 0; i < cbs_for_type.size(); ++i) {
66          cbs_out.push_back(cbs_for_type[i]); 
67       }
68       assert(!cbs.defines(evt));
69    }
70    else  {
71       mailbox_printf("%s[%d]:  no callbacks matching %s\n", 
72             FILE__, __LINE__, eventType2str(evt));
73       return false;
74    }
75
76    return true;
77 }
78
79 bool CallbackManager::dispenseCallbacksMatching(eventType evt, pdvector<CallbackBase *> &cbs_out)
80 {
81    if (cbs_out.size()) {
82       fprintf(stderr, "%s[%d]:  WARN, dispenseCallbacksMatching (%s) appending to existing callbacks\n", FILE__, __LINE__, eventType2str(evt));
83    }
84
85    if (cbs.defines(evt)) {
86       pdvector<CallbackBase *> &cbs_for_type = cbs[evt];
87       for (unsigned int i = 0; i < cbs_for_type.size(); ++i) {
88          CallbackBase *newcb = cbs_for_type[i]->copy(); 
89          cbs_out.push_back(newcb); 
90       }
91    }
92    else  {
93       mailbox_printf("%s[%d]:  no callbacks matching %s\n", 
94             FILE__, __LINE__, eventType2str(evt));
95       return false;
96    }
97    return true;
98
99 }
100
101 void SyncCallback::signalCompletion(CallbackBase *cb) 
102 {
103    //fprintf(stderr, "%s[%d]:  welcome to singal completion\n", FILE__, __LINE__);
104    SyncCallback *scb = (SyncCallback *) cb;
105    scb->lock->_Lock(FILE__, __LINE__);
106    scb->completion_signalled = true;
107    if (scb->sh)
108       scb->sh->wait_cb = NULL;
109    signal_printf("%s[%d]: SyncCallback, signalling completion, sh = %s\n", FILE__, __LINE__, scb->sh ? scb->sh->getName() : "null");
110    mailbox_printf("%s[%d][%s]:  signalling completion of callback\n",
111          FILE__, __LINE__, getThreadStr(getExecThreadID()));
112    scb->lock->_Broadcast(FILE__, __LINE__);
113    scb->lock->_Unlock(FILE__, __LINE__);
114 }
115
116 bool SyncCallback::waitForCompletion() 
117 {
118    //  Assume that we are already locked upon entry
119    assert(lock);
120    assert(lock->depth());
121    assert(lock == global_mutex);
122    //  we need to find the signal
123    //  handler that has this thread id -- ie, find out if we are running on a 
124    //  signal handler thread.  Since we do not have an easy way of getting 
125    //  this object, we need to search for it:
126
127    extern pdvector<process *> processVec;
128    for (unsigned int i = 0; i < processVec.size(); ++i) {
129       if (processVec[i]) {
130          if (processVec[i]->status() != deleted && processVec[i]->sh)
131             if (NULL != (sh = processVec[i]->sh->findSHWithThreadID(getExecThreadID())))
132                break;
133       }
134    }
135    signal_printf("%s[%d]: SyncCallback, waiting for completion, sh = %p\n", FILE__, __LINE__, sh ? sh->getName() : "null");
136    if (sh) {
137       sh->wait_cb = (CallbackBase *) this;
138       sh->sg->pingIfContinueBlocked();
139    }
140
141    while (!completion_signalled) {
142       if (!lock) {
143          fprintf(stderr, "%s[%d]:  LOCK IS GONE!!\n", FILE__, __LINE__);
144          return false;
145       }
146       mailbox_printf("%s[%d][%s]:  waiting for completion of callback\n",
147             FILE__, __LINE__, getThreadStr(getExecThreadID()));
148       if (0 != lock->_Broadcast(FILE__, __LINE__)) assert(0);
149       if (0 != lock->_WaitForSignal(FILE__, __LINE__)) assert(0);
150    }
151    return true;
152 }
153
154 bool SyncCallback::execute() 
155 {
156    unsigned int need_to_relock = 0;
157    lock->_Lock(FILE__, __LINE__);
158    while (lock->depth()-1) {
159       lock->_Unlock(FILE__, __LINE__);
160       need_to_relock++;
161    }
162    lock->_Unlock(FILE__, __LINE__);
163
164    execute_real();
165
166    while (need_to_relock--) 
167       lock->_Lock(FILE__, __LINE__);
168    return true;
169 }
170
171 bool SyncCallback::do_it()
172 {
173    bool reset_delete_enabled = false;
174    if (synchronous) {
175       if (deleteEnabled()) {
176          enableDelete(false);
177          reset_delete_enabled = true;
178       }
179    }
180
181    getMailbox()->executeOrRegisterCallback(this);
182    if (synchronous) {
183       signal_printf("%s[%d]:  waiting for completion of callback\n", FILE__, __LINE__);
184       waitForCompletion();
185       if (reset_delete_enabled)
186          enableDelete();
187    }
188    return true;
189 }
190
191 ErrorCallback::~ErrorCallback()
192 {
193    //  need to free memory allocated for the arguments 
194    if (str) free(str);
195 }
196
197 bool ErrorCallback::execute_real(void) 
198 {
199    cb(sev, num, &str);
200    return true;
201 }
202
203 bool ErrorCallback::operator()(BPatchErrorLevel severity, int number,
204       const char *error_string)
205 {
206    //  Assume that we are already locked upon entry
207    assert(lock->depth());
208    assert(error_string);
209    str = P_strdup(error_string);
210    num = number;
211    sev = severity;    
212
213    return do_it();
214 }
215
216 bool ForkCallback::execute_real(void) 
217 {
218    bool is_stopped = par->isVisiblyStopped();
219    if (!is_stopped)
220    par->markVisiblyStopped(true);
221    cb(par, chld);
222    if (!is_stopped)
223    par->markVisiblyStopped(false);
224    return true;
225 }
226
227 bool ForkCallback::operator()(BPatch_thread *parent, BPatch_thread *child)
228 {
229    assert(lock->depth());
230    par = parent;
231    chld = child;
232
233    return do_it();
234 }
235
236 bool ExecCallback::execute_real(void) 
237 {
238    bool is_stopped = thread->isVisiblyStopped();
239    if (!is_stopped)
240    thread->markVisiblyStopped(true);
241    cb(thread);
242    if (!is_stopped)
243    thread->markVisiblyStopped(false);
244    return true;
245 }
246
247 bool ExecCallback::operator()(BPatch_thread *thr)
248 {
249    assert(lock->depth());
250    thread = thr;
251
252    return do_it();
253 }
254
255 bool ExitCallback::execute_real(void) 
256 {
257    bool is_stopped = thread->isVisiblyStopped();
258    if (!is_stopped)
259    thread->markVisiblyStopped(true);
260    cb(thread, type);
261    return true;
262 }
263
264 bool ExitCallback::operator()(BPatch_thread *thr, BPatch_exitType exit_type)
265 {
266    assert(lock->depth());
267    thread = thr;;
268    type = exit_type;
269
270    return do_it();
271 }
272
273 bool SignalCallback::execute_real(void) 
274 {
275    cb(thread, num);
276    return true;
277 }
278
279 bool SignalCallback::operator()(BPatch_thread *thr, int sigNum)
280 {
281    assert(lock->depth());
282    thread = thr;
283    num = sigNum;
284
285    return do_it();
286 }
287
288 bool OneTimeCodeCallback::execute_real(void) 
289 {
290    cb(thread, user_data, return_value);
291    return true;
292 }
293
294 bool OneTimeCodeCallback::operator()(BPatch_thread *thr, void *userData, void *returnValue)
295 {
296    assert(lock->depth());
297    thread = thr;
298    user_data = userData;
299    return_value = returnValue;
300
301    return do_it();
302 }
303
304 bool DynLibraryCallback::execute_real(void) 
305 {
306    bool is_stopped = thread->isVisiblyStopped();
307    if (!is_stopped)
308    thread->markVisiblyStopped(true);
309    cb(thread, mod, load_param);
310    if (!is_stopped)
311    thread->markVisiblyStopped(false);
312    return true;
313 }
314
315 bool DynLibraryCallback::operator()(BPatch_thread *thr, BPatch_module *module, bool load)
316 {
317    assert(lock->depth());
318    thread = thr;
319    mod = module;
320    load_param = load;
321
322    return do_it();
323 }
324
325 bool DynamicCallsiteCallback::execute_real(void) 
326 {
327    cb(pt, func);
328    return true;
329 }
330
331 bool DynamicCallsiteCallback::operator()(BPatch_point *at_point, 
332       BPatch_function *called_function)
333 {
334    assert(lock->depth());
335    pt = at_point;
336    func = called_function;
337
338    return do_it();
339 }
340
341 UserEventCallback::~UserEventCallback()
342 {
343    if (buf) delete [] (int *)buf;
344 }
345
346 bool UserEventCallback::execute_real(void) 
347 {
348    cb(proc, buf, bufsize);
349    return true;
350 }
351
352 bool UserEventCallback::operator()(BPatch_process *process, void *buffer, int buffersize)
353 {
354    assert(lock->depth());
355    proc = process;
356    bufsize = buffersize;
357    buf = new int [buffersize];
358    memcpy(buf, buffer, buffersize); 
359
360    return do_it();
361 }
362
363 bool StopThreadCallback::execute_real(void) 
364 {
365   cb(point, return_value);
366   return true;
367 }
368
369 bool StopThreadCallback::operator()(BPatch_point *atPoint, void *returnValue)
370 {
371   assert(lock->depth());
372   point = atPoint;
373   return_value = returnValue;
374
375   return do_it();
376 }
377
378 bool SignalHandlerCallback::execute_real(void) 
379 {
380   cb(point, signum, handlers);
381   return true;
382 }
383
384 bool SignalHandlerCallback::handlesSignal(long signum) 
385 {
386   if (NULL == signals) {
387     return true;
388   } else {
389     return signals->contains(signum);
390   }
391 }
392
393 bool SignalHandlerCallback::operator()(BPatch_point *at_point, long signal_number, 
394                                        BPatch_Vector<Dyninst::Address> *handler_vec)
395 {
396   assert(lock->depth());
397   point = at_point;
398   signum = signal_number;
399   handlers = handler_vec;
400   return do_it();
401 }
402
403 bool AsyncThreadEventCallback::execute_real(void) 
404 {
405    async_printf("%s[%d][%s]:  welcome to AsyncThreadEventCallback: execute\n", 
406          FILE__, __LINE__, getThreadStr(getExecThreadID()));
407    cb(proc, thr);
408
409    return true;
410 }
411
412 bool AsyncThreadEventCallback::operator()(BPatch_process *process, BPatch_thread *thread)
413 {
414    assert(lock->depth());
415    assert(process);
416    assert(thread);
417
418    proc = process;
419    thr = thread;
420    synchronous = override_to_sync;
421
422    return do_it();
423 }
424
425 InternalThreadExitCallback::~InternalThreadExitCallback()
426 {
427    if (cbs) delete cbs;
428 }
429
430 bool InternalThreadExitCallback::execute_real(void) 
431 {
432    cb(proc, thr, cbs);
433    return true;
434 }
435
436 bool InternalThreadExitCallback::operator()(BPatch_process *p, BPatch_thread *t, 
437       pdvector<AsyncThreadEventCallback *> *callbacks)
438 {
439    assert(lock->depth());
440    proc = p;
441    thr = t;
442    cbs = callbacks;
443
444    return do_it();
445 }