proccontrol: Fix Coverity UNINIT_CTOR errors
[dyninst.git] / proccontrol / src / response.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "proccontrol/h/Event.h"
32
33 #include "proccontrol/src/response.h"
34 #include "proccontrol/src/int_process.h"
35 #include "proccontrol/src/int_handler.h"
36 #include "proccontrol/src/procpool.h"
37
38 #include <cstring>
39
40 using namespace Dyninst;
41 using namespace ProcControlAPI;
42 using namespace std;
43
44 unsigned int response::next_id = 1;
45
46 static Mutex id_lock;
47
48 unsigned newResponseID()
49 {
50   unsigned id;
51   id_lock.lock();
52   id = response::next_id++;
53   id_lock.unlock();
54   return id;
55 }
56
57 unsigned newResponseID(unsigned size)
58 {
59   unsigned id;
60   id_lock.lock();
61   id = response::next_id;
62   response::next_id += size;
63   id_lock.unlock();
64   return id;
65 }
66
67 response::response() :
68    event(Event::ptr()),
69    state(unset),
70    checked_ready(false),
71    isSyncHandled(false),
72    error(false),
73    errorcode(0),
74    proc(NULL),
75    aio(NULL),
76    resp_type((resp_type_t)-1),
77    decoder_event(NULL),
78    multi_resp_size(0),
79    multi_resp_recvd(0)
80 {
81    id = newResponseID();
82 }
83
84 response::~response()
85 {
86    assert(error || state != ready || checked_ready);
87 }
88
89 bool response::isReady() const
90 {
91    checked_ready = true;
92    return (state == ready);
93 }
94
95 bool response::testReady() const
96 {
97    return (state == ready);
98 }
99
100 Event::ptr response::getEvent() const
101 {
102    return event;
103 }
104
105 bool response::hasError() const
106 {
107    return error;
108 }
109
110 int response::errorCode() const
111 {
112    assert(error);
113    return errorcode;
114 }
115
116 bool response::isPosted() const 
117 {
118    return state != unset;
119 }
120
121 void response::markReady()
122 {
123    if (multi_resp_size && multi_resp_size < multi_resp_recvd)
124       return;
125
126    assert(state != ready);
127    state = ready;
128 }
129
130 void response::markPosted()
131 {
132    assert(state == unset);
133    state = posted;
134 }
135
136 void response::markError(int code)
137 {
138    assert(!error);
139    error = true;
140    errorcode = code;
141 }
142
143 void response::setEvent(Event::ptr ev)
144 {
145    assert(!event || !ev || event == ev);
146    event = ev;
147 }
148
149 void response::markSyncHandled()
150 {
151    isSyncHandled = true;
152 }
153
154 unsigned int response::getID() const 
155 {
156    return id;
157 }
158
159 int_eventAsyncIO *response::getAsyncIOEvent()
160 {
161    return aio;
162 }
163
164 void response::setAsyncIOEvent(int_eventAsyncIO *aio_)
165 {
166    aio = aio_;
167 }
168
169 string response::name() const
170 {
171    switch (resp_type) {
172       case rt_result:
173          return "Result Response";
174       case rt_reg:
175          return "Reg Response";
176       case rt_allreg:
177          return "AllReg Response";
178       case rt_mem:
179          return "Mem Response";
180       case rt_set:
181          return "Set Response";
182       case rt_stack:
183          return "Stack Response";
184       case rt_data:
185          return "Data Response";
186    }
187    assert(0);
188    return "";
189 }
190
191 unsigned int response::markAsMultiResponse(int num_resps)
192 {
193    assert(num_resps);
194    assert(state == unset);
195    id_lock.lock();
196    id = next_id;
197    next_id += num_resps;
198    id_lock.unlock();
199
200    multi_resp_size = num_resps;
201
202    return id;
203 }
204
205 bool response::isMultiResponse()
206 {
207    return multi_resp_size != 0;
208 }
209
210 unsigned int response::multiResponseSize()
211 {
212    return multi_resp_size;
213 }
214
215 bool response::isMultiResponseComplete()
216 {
217    return (multi_resp_size == multi_resp_recvd);
218 }
219
220 void response::setDecoderEvent(ArchEvent *ae)
221 {
222    decoder_event = ae;
223 }
224
225 ArchEvent *response::getDecoderEvent()
226 {
227    return decoder_event;
228 }
229
230 int_process *response::getProcess() const
231 {
232   return proc;
233 }
234
235 void response::setProcess(int_process *p)
236 {
237   proc = p;
238 }
239
240 result_response::ptr response::getResultResponse()
241 {
242    return resp_type == rt_result ? 
243       boost::static_pointer_cast<result_response>(shared_from_this()) :
244       result_response::ptr();
245 }
246
247 mem_response::ptr response::getMemResponse()
248 {
249    return resp_type == rt_mem ? 
250       boost::static_pointer_cast<mem_response>(shared_from_this()) :
251       mem_response::ptr();
252 }
253
254 reg_response::ptr response::getRegResponse()
255 {
256    return resp_type == rt_reg ? 
257       boost::static_pointer_cast<reg_response>(shared_from_this()) :
258       reg_response::ptr();
259 }
260
261 allreg_response::ptr response::getAllRegResponse()
262 {
263    return resp_type == rt_allreg ? 
264       boost::static_pointer_cast<allreg_response>(shared_from_this()) :
265       allreg_response::ptr();
266 }
267
268 stack_response::ptr response::getStackResponse()
269 {
270    return resp_type == rt_stack ?
271       boost::static_pointer_cast<stack_response>(shared_from_this()) :
272       stack_response::ptr();
273 }
274
275 data_response::ptr response::getDataResponse()
276 {
277    return resp_type == rt_data ?
278       boost::static_pointer_cast<data_response>(shared_from_this()) :
279       data_response::ptr();
280 }
281
282 response::ptr responses_pending::rmResponse(unsigned int id)
283 {
284    //cvar lock should already be held.
285    std::map<unsigned int, response::ptr>::iterator i = pending.find(id);
286    if (i == pending.end()) {
287       //I've seen this happen on BlueGene/P, it sometimes throws duplicate ACKs
288       pthrd_printf("Unknown response.  Recieved duplicate ACK message on BlueGene?\n");
289       return response::ptr();
290    }
291    response::ptr result = (*i).second;
292
293    pending.erase(i);
294
295    return result;
296 }
297  
298 bool responses_pending::waitFor(response::ptr resp)
299 {
300    cvar.lock();
301
302    if (resp->isReady()) {
303       cvar.unlock();
304       pthrd_printf("Waiting for async event %d, complete\n", resp->getID());
305       return true;
306    }
307
308    unsigned int iter = 0;
309    map<unsigned int, response::ptr>::iterator i = pending.find(resp->getID());
310    assert(i != pending.end());
311
312    while (!resp->isReady()) {
313       pthrd_printf("Waiting for async event %d, iter = %d\n", resp->getID(), iter);
314       cvar.wait();
315       iter++;
316    }
317    cvar.unlock();
318
319    pthrd_printf("Waiting for async event %d, complete\n", resp->getID());
320
321    return true;
322 }
323
324 bool responses_pending::hasAsyncPending(bool ev_only)
325 {
326    bool ret = false;
327    cvar.lock();
328    if (!ev_only) {
329       ret = !pending.empty();
330    }
331    else {
332       map<unsigned, response::ptr>::const_iterator i;
333       for (i = pending.begin(); i != pending.end(); i++) {
334          if (i->second->getEvent()) {
335             ret = true;
336             break;
337          }
338       }
339    }
340    cvar.unlock();
341    return ret;
342 }
343
344 response::ptr responses_pending::getResponse(unsigned int id)
345 {
346    cvar.lock();
347    map<unsigned int, response::ptr>::iterator i = pending.find(id);
348    cvar.unlock();
349    assert(i != pending.end());
350    return (*i).second;
351 }
352
353 void responses_pending::lock()
354 {
355    cvar.lock();
356 }
357
358 void responses_pending::unlock()
359 {
360    cvar.unlock();
361 }
362
363 void responses_pending::signal()
364 {
365    cvar.broadcast();
366 }
367
368 CondVar &responses_pending::condvar()
369 {
370    return cvar;
371 }
372
373 void responses_pending::addResponse(response::ptr r, int_process *proc)
374 {
375    pthrd_printf("Adding response %d of type %s to list of pending responses\n", r->getID(), r->name().c_str());
376    Event::ptr ev = proc->handlerPool()->curEvent();
377    if (r->isSyncHandled)
378       ev = Event::ptr();
379
380    r->setProcess(proc);
381
382    r->setEvent(ev);
383    r->markPosted();
384
385    if (!r->isMultiResponse()) {
386       pending[r->getID()] = r;
387    }
388    else {
389       unsigned int id = r->getID();
390       unsigned int end = r->getID() + r->multiResponseSize();
391       for (unsigned int i = id; i < end; i++) {
392          pending[i] = r;
393       }
394    }
395 }
396
397 void responses_pending::noteResponse()
398 {
399    if (isGeneratorThread()) {
400       //Signaling the ProcPool is meant to wake the generator.  We
401       // obviously don't need to signal ourselves.  In fact,
402       // the generator may already be holding the procpool lock, 
403       // so we don't want to retake it.
404       return;
405    }
406    ProcPool()->condvar()->lock();
407    ProcPool()->condvar()->broadcast();
408    ProcPool()->condvar()->unlock();
409 }
410
411 responses_pending &getResponses()
412 {
413    static responses_pending rp;
414    return rp;
415 }
416
417 result_response::ptr result_response::createResultResponse()
418 {
419    return result_response::ptr(new result_response());
420 }
421
422 result_response::result_response() :
423    b(false)
424 {
425    resp_type = rt_result;
426 }
427
428 result_response::~result_response()
429 {
430 }
431
432 void result_response::setResponse(bool b_)
433 {
434    postResponse(b_);
435    markReady();
436 }
437
438 void result_response::postResponse(bool b_)
439 {
440    if (!isMultiResponse()) {
441       b = b_;
442       return;
443    }
444
445    multi_resp_recvd++;
446    if (multi_resp_recvd == 1) {
447       b = b_;
448       return;
449    }
450    // The 'b = b & b_' logic is so that a multi-response result will 
451    // be true iff all RESULT_ACKs returned success
452    b = b & b_;
453 }
454
455 bool result_response::getResult() const
456 {
457    return b;
458 }
459
460 reg_response::ptr reg_response::createRegResponse()
461 {
462    return reg_response::ptr(new reg_response());
463 }
464
465
466 reg_response::reg_response() :
467    val(0),
468    thr(NULL)
469 {
470    resp_type = rt_reg;
471 }
472
473 reg_response::~reg_response()
474 {
475 }
476
477 void reg_response::setRegThread(Dyninst::MachRegister r, int_thread *t)
478 {
479    reg = r;
480    thr = t;
481 }
482
483 void reg_response::setResponse(Dyninst::MachRegisterVal v)
484 {
485    postResponse(v);
486    markReady();
487 }
488
489 void reg_response::postResponse(Dyninst::MachRegisterVal v)
490 {
491    assert(reg && thr);
492    thr->updateRegCache(reg, v);
493    val = v;
494 }
495
496 Dyninst::MachRegisterVal reg_response::getResult() const { 
497    return val;
498 }
499
500 allreg_response::ptr allreg_response::createAllRegResponse()
501 {
502    return allreg_response::ptr(new allreg_response());
503 }
504
505 allreg_response::ptr allreg_response::createAllRegResponse(int_registerPool *regpool)
506 {
507    allreg_response::ptr r = allreg_response::ptr(new allreg_response());
508    r->regpool = regpool;
509    return r;
510 }
511
512 allreg_response::allreg_response() :
513    regpool(NULL),
514    thr(NULL)
515 {
516    resp_type = rt_allreg;
517 }
518
519 allreg_response::~allreg_response()
520 {
521 }
522
523 void allreg_response::setThread(int_thread *t)
524 {
525    thr = t;
526 }
527
528 void allreg_response::setRegPool(int_registerPool *p)
529 {
530    regpool = p;
531 }
532
533 void allreg_response::setResponse()
534 {
535    postResponse();
536    markReady();
537 }
538
539 void allreg_response::postResponse()
540 {
541    assert(thr);
542    if (isMultiResponse()) {
543       multi_resp_recvd++;
544    }
545    if (isMultiResponseComplete()) {
546       thr->updateRegCache(*regpool);
547    }
548 }
549
550 void allreg_response::setIndividualRegAccess(reg_response::ptr iacc, Dyninst::MachRegister ireg)
551 {
552    assert(!indiv_access);
553    indiv_access = iacc;
554    indiv_reg = ireg;
555 }
556
557 Dyninst::MachRegister allreg_response::getIndividualReg()
558 {
559    return indiv_reg;
560 }
561
562 reg_response::ptr allreg_response::getIndividualAcc()
563 {
564    return indiv_access;
565 }
566
567 int_registerPool *allreg_response::getRegPool() const
568 {
569    return regpool;
570 }
571
572 mem_response::ptr mem_response::createMemResponse()
573 {
574    return mem_response::ptr(new mem_response());
575 }
576
577 mem_response::ptr mem_response::createMemResponse(char *targ, unsigned targ_size)
578 {
579    return mem_response::ptr(new mem_response(targ, targ_size));
580 }
581
582 mem_response::mem_response() :
583    buffer(NULL),
584    size(0),
585    buffer_set(false),
586    last_base(0)
587 {
588    resp_type = rt_mem;
589 }
590
591 mem_response::mem_response(char *targ, unsigned targ_size) :
592    buffer(targ),
593    size(targ_size),
594    buffer_set(true),
595    last_base(0)
596 {
597    resp_type = rt_mem;
598 }
599
600 mem_response::~mem_response()
601 {
602 }
603
604 void mem_response::setBuffer(char *targ, unsigned targ_size)
605 {
606    assert(!buffer_set);
607    buffer = targ;
608    size = targ_size;
609    buffer_set = true;
610 }
611
612 void mem_response::setResponse(char *src, unsigned src_size)
613 {
614    postResponse(src, src_size);
615    markReady();
616 }
617
618 void mem_response::setResponse()
619 {
620    postResponse();
621    markReady();
622 }
623
624 void mem_response::postResponse(char *src, unsigned src_size, Address src_addr)
625 {
626    assert(buffer_set);
627
628    if (!isMultiResponse()) {
629       assert(src_size >= size);
630       memcpy(buffer, src, size);
631       return;
632    }
633
634    multi_resp_recvd++;
635    unsigned long offset = src_addr - last_base;
636    memcpy(buffer + offset, src, src_size);
637 }
638
639 void mem_response::setLastBase(Address a) 
640 {
641    last_base = a;
642 }
643
644 Address mem_response::lastBase()
645 {
646    return last_base;
647 }
648
649 void mem_response::postResponse()
650 {
651 }
652
653 char *mem_response::getBuffer() const
654 {
655    return buffer;
656 }
657
658 unsigned mem_response::getSize() const
659 {
660    return size;
661 }
662
663 stack_response::ptr stack_response::createStackResponse(int_thread *t)
664 {
665    return stack_response::ptr(new stack_response(t));
666 }
667
668 stack_response::stack_response(int_thread *t) :
669    data(NULL),
670    thr(t)
671 {
672    resp_type = rt_stack;
673 }
674  
675 stack_response::~stack_response()
676 {
677 }
678
679 void *stack_response::getData()
680 {
681    return data;
682 }
683
684 int_thread *stack_response::getThread()
685 {
686    return thr;
687 }
688
689 void stack_response::postResponse(void *d)
690 {
691    data = d;
692 }
693
694 data_response::data_response() :
695    data(NULL)
696 {
697    resp_type = rt_data;
698 }
699
700 data_response::~data_response()
701 {
702    if (data) {
703       free(data);
704       data = NULL;
705    }
706 }
707
708 data_response::ptr data_response::createDataResponse()
709 {
710    return data_response::ptr(new data_response());
711 }
712
713 void *data_response::getData()
714 {
715    return data;
716 }
717
718 void data_response::postResponse(void *d)
719 {
720    data = d;
721    markReady();
722 }
723
724 unsigned int ResponseSet::next_id = 1;
725 Mutex ResponseSet::id_lock;
726 std::map<unsigned int, ResponseSet *> ResponseSet::all_respsets;
727
728 ResponseSet::ResponseSet()
729 {
730   id_lock.lock();
731   myid = next_id++;
732   if (!myid)
733     myid = next_id++;
734   all_respsets.insert(make_pair(myid, this));
735   id_lock.unlock();
736 }
737
738 void ResponseSet::addID(unsigned id, unsigned index)
739 {
740   ids.insert(make_pair(index, id));
741 }
742
743 unsigned ResponseSet::getIDByIndex(unsigned int index, bool &found) const
744 {
745   map<unsigned, unsigned>::const_iterator i = ids.find(index);
746   if (i == ids.end()) {
747     found = false;
748     return 0;
749   }
750   found = true;
751   return i->second;
752 }
753
754 unsigned int ResponseSet::getID() const {
755   return myid;
756 }
757
758 ResponseSet *ResponseSet::getResponseSetByID(unsigned int id) {
759   map<unsigned int, ResponseSet *>::iterator i;
760   ResponseSet *respset = NULL;
761   id_lock.lock();
762   i = all_respsets.find(id);
763   if (i != all_respsets.end()) {
764     respset = i->second;
765     all_respsets.erase(i);
766   }
767   id_lock.unlock();
768   return respset;
769 }
770