Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / rpcMgr-thr.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 #include "common/h/headers.h"
33 #include "dyninstAPI/src/dyn_lwp.h"
34 #include "dyninstAPI/src/dyn_thread.h"
35 #include "dyninstAPI/src/process.h"
36 #include "dyninstAPI/src/rpcMgr.h"
37 #include "dyninstAPI/src/mailbox.h"
38 #include "dyninstAPI/src/callbacks.h"
39
40 rpcThr::rpcThr(rpcThr *parT, rpcMgr *cM, dyn_thread *cT) :
41     mgr_(cM),
42     thr_(cT),
43     pendingRPC_(NULL),
44     runningRPC_(NULL)
45 {
46     for (unsigned i = 0; i < parT->postedRPCs_.size(); i++) {
47         inferiorRPCtoDo *newRPC = new inferiorRPCtoDo;
48         inferiorRPCtoDo *oldRPC = parT->postedRPCs_[i];
49
50         newRPC->action = oldRPC->action;
51         newRPC->noCost = oldRPC->noCost;
52         newRPC->callbackFunc = oldRPC->callbackFunc;
53         newRPC->userData = oldRPC->userData;
54         newRPC->lowmem = oldRPC->lowmem;
55         newRPC->id = oldRPC->id;
56         assert(oldRPC->thr);
57         newRPC->thr = cT;
58         assert(!oldRPC->lwp);
59         postedRPCs_.push_back(newRPC);
60     }
61     
62     if (parT->pendingRPC_) {
63         inferiorRPCinProgress *newProg = new inferiorRPCinProgress;
64         inferiorRPCinProgress *oldProg = parT->pendingRPC_;
65         
66         inferiorRPCtoDo *newRPC = new inferiorRPCtoDo;
67         inferiorRPCtoDo *oldRPC = oldProg->rpc;
68
69         newRPC->action = oldRPC->action;
70         newRPC->noCost = oldRPC->noCost;
71         newRPC->callbackFunc = oldRPC->callbackFunc;
72         newRPC->userData = oldRPC->userData;
73         newRPC->lowmem = oldRPC->lowmem;
74         newRPC->id = oldRPC->id;
75         assert(oldRPC->thr);
76         newRPC->thr = cT;
77         assert(!oldRPC->lwp);
78         
79         newProg->rpc = newRPC;
80         if (oldProg->savedRegs) {
81             newProg->savedRegs = new dyn_saved_regs;
82             memcpy(newProg->savedRegs, oldProg->savedRegs, sizeof(dyn_saved_regs));
83         }
84         else newProg->savedRegs = NULL;
85         newProg->origPC = oldProg->origPC;
86         newProg->runProcWhenDone = oldProg->runProcWhenDone;
87         newProg->rpcBaseAddr = oldProg->rpcBaseAddr;
88         newProg->rpcStartAddr = oldProg->rpcStartAddr;
89         newProg->rpcResultAddr = oldProg->rpcResultAddr;
90         newProg->rpcContPostResultAddr = oldProg->rpcContPostResultAddr;
91         newProg->rpcCompletionAddr = oldProg->rpcCompletionAddr;
92         newProg->resultRegister = oldProg->resultRegister;
93         newProg->resultValue = oldProg->resultValue;
94         
95         newProg->rpcthr = this;
96         newProg->rpclwp = NULL;
97         newProg->isProcessRPC = oldProg->isProcessRPC;
98         newProg->state = oldProg->state;
99         
100         pendingRPC_ =  newProg;
101     }
102         
103
104     if (parT->runningRPC_) {
105         inferiorRPCinProgress *newProg = new inferiorRPCinProgress;
106         inferiorRPCinProgress *oldProg = parT->runningRPC_;
107         
108         inferiorRPCtoDo *newRPC = new inferiorRPCtoDo;
109         inferiorRPCtoDo *oldRPC = oldProg->rpc;
110
111         newRPC->action = oldRPC->action;
112         newRPC->noCost = oldRPC->noCost;
113         newRPC->callbackFunc = oldRPC->callbackFunc;
114         newRPC->userData = oldRPC->userData;
115         newRPC->lowmem = oldRPC->lowmem;
116         newRPC->id = oldRPC->id;
117         assert(oldRPC->thr);
118         newRPC->thr = cT;
119         assert(!oldRPC->lwp);
120         
121         newProg->rpc = newRPC;
122         if (oldProg->savedRegs) {
123             newProg->savedRegs = new dyn_saved_regs;
124             memcpy(newProg->savedRegs, oldProg->savedRegs, sizeof(dyn_saved_regs));
125         }
126         else newProg->savedRegs = NULL;
127         newProg->origPC = oldProg->origPC;
128         newProg->runProcWhenDone = oldProg->runProcWhenDone;
129         newProg->rpcBaseAddr = oldProg->rpcBaseAddr;
130         newProg->rpcStartAddr = oldProg->rpcStartAddr;
131         newProg->rpcResultAddr = oldProg->rpcResultAddr;
132         newProg->rpcContPostResultAddr = oldProg->rpcContPostResultAddr;
133         newProg->rpcCompletionAddr = oldProg->rpcCompletionAddr;
134         newProg->resultRegister = oldProg->resultRegister;
135         newProg->resultValue = oldProg->resultValue;
136         
137         newProg->rpcthr = this;
138         newProg->rpclwp = NULL;
139         newProg->isProcessRPC = oldProg->isProcessRPC;
140         newProg->state = oldProg->state;
141         
142         runningRPC_ =  newProg;
143     }
144 }
145
146 int rpcThr::postIRPC(inferiorRPCtoDo *todo) {
147     postedRPCs_.push_back(todo);
148     return todo->id;
149 }
150
151 bool rpcThr::isProcessingIRPC() const {
152     inferiorrpc_printf("%s[%d]: call to isProcessing: isRunning %d, isWaiting %d\n",
153                        FILE__, __LINE__, isRunningIRPC(), isWaitingForBreakpoint());
154     return isRunningIRPC() || isWaitingForBreakpoint();
155 }
156
157 bool rpcThr::isRunningIRPC() const {
158     return runningRPC_ != NULL;
159 }
160
161 bool rpcThr::isWaitingForBreakpoint() const {
162     return pendingRPC_ != NULL;
163 }
164
165 bool rpcThr::isReadyForIRPC() const {
166     if (isProcessingIRPC()) {
167       inferiorrpc_printf("... thr %lu currently processing, sorry\n",
168                          get_thr()->get_tid());
169         return false;
170     }
171     if (postedRPCs_.size() > 0) {
172       inferiorrpc_printf("... thr %lu with a thread RPC\n",
173                          get_thr()->get_tid());
174         return true;
175     }
176     if (mgr_->postedProcessRPCs_.size() > 0) {
177       inferiorrpc_printf("... thr %lu picking up a process RPC\n",
178                          get_thr()->get_tid());
179         return true;
180     }
181     inferiorrpc_printf("... thr %lu with nothing to do\n",
182                        get_thr()->get_tid());
183     return false;
184 }
185
186 // Launch an inferior RPC
187 // Two cases: 
188 // 1) We have a pending RPC (in pendingRPC_) that we already prepped
189 //    and we want to run it (and a system call breakpoint was set)
190 // 2) We don't have a pending IRPC but there is one on the queue.
191 irpcLaunchState_t rpcThr::launchThrIRPC(bool runProcWhenDone) 
192 {
193
194     if (runningRPC_ || pendingRPC_) {
195         return irpcError;
196     }
197
198     if(postedRPCs_.size() == 0 && mgr_->postedProcessRPCs_.size() == 0)
199         return irpcNoIRPC;
200
201     // We can run the RPC if we're not currently in a system call.
202     // This is defined as "any time we can't modify the state of the
203     // process". In this case we try and set a breakpoint when we leave
204     // the system call. If we can't set the breakpoint we poll.
205     dyn_lwp *lwp = thr_->get_lwp();
206     
207     if (mgr_->proc()->IndependentLwpControl()) {
208         if (lwp->status() == running) runProcWhenDone = true;
209         lwp->pauseLWP();
210     }
211
212     // That call can handle process signals (I'm not kidding) at which point
213     // someone else picked up our iRPC... seen with Paradyn
214
215     if(postedRPCs_.size() == 0 && mgr_->postedProcessRPCs_.size() == 0) {
216         if (mgr_->proc()->IndependentLwpControl() && runProcWhenDone)
217             lwp->continueLWP(NoSignal, false);
218         return irpcNoIRPC;
219     }
220
221 #if defined(cap_syscall_trap)
222     // Check if we're in a system call
223     if (lwp->executingSystemCall()) {
224         // We can't do any work. If there is a pending RPC try
225         // to set a breakpoint at the exit of the call
226
227         // See if we have a thread-specific iRPC. If not, we're talking process...
228         // and that means that we just went into a system call. 
229
230         if (postedRPCs_.size() == 0) 
231             return irpcNoIRPC;
232         
233         if (lwp->setSyscallExitTrap(launchThrIRPCCallbackDispatch,
234                                     (void *)this)) {
235             // If there is an RPC queued we set it up as pending
236             // and record it
237             if (!pendingRPC_) {
238                 pendingRPC_ = new inferiorRPCinProgress;
239                 assert(postedRPCs_.size());
240                 pendingRPC_->rpc = postedRPCs_[0];
241                 pendingRPC_->runProcWhenDone = runProcWhenDone;
242                 // Delete that iRPC (clunky)
243                 pdvector<inferiorRPCtoDo *> newRPCs;
244                 VECTOR_ERASE(postedRPCs_,0,0);
245                 mgr_->addPendingRPC(pendingRPC_);
246             }
247             if (mgr_->proc()->IndependentLwpControl() && runProcWhenDone)
248                 lwp->continueLWP();
249             return irpcBreakpointSet;
250         }
251         else {
252             // Weren't able to set the breakpoint, so all we can
253             // do is try later
254             // Don't set pending if we're polling.
255             assert(!pendingRPC_);
256             if (mgr_->proc()->IndependentLwpControl() && runProcWhenDone)
257                 lwp->continueLWP();
258             return irpcAgain;
259         }
260     }
261 #endif // cap_syscall_trap
262
263     // Get the RPC and slap it in the pendingRPC_ pointer
264     if (!pendingRPC_) {
265         inferiorrpc_printf("%s[%d]: ready to run, creating pending RPC structure\n",
266                            FILE__, __LINE__);
267         pendingRPC_ = new inferiorRPCinProgress;
268         if (postedRPCs_.size() > 0) {       
269             pendingRPC_->rpc = postedRPCs_[0];
270             // Delete that iRPC (clunky)
271             pdvector<inferiorRPCtoDo *> newRPCs;
272             for (unsigned k = 1; k < postedRPCs_.size(); k++)
273                 newRPCs.push_back(postedRPCs_[k]);
274             postedRPCs_ = newRPCs;
275             pendingRPC_->isProcessRPC = false;
276         }
277         else {
278             // Take a process-wide RPC
279             pendingRPC_->rpc = mgr_->getProcessRPC();
280             // And it's running on this thread
281             pendingRPC_->rpc->thr = thr_;
282             pendingRPC_->isProcessRPC = true;
283         }
284         pendingRPC_->runProcWhenDone = runProcWhenDone;
285         mgr_->addPendingRPC(pendingRPC_);
286     }
287     assert(pendingRPC_);
288     return runPendingIRPC();
289 }
290
291 irpcLaunchState_t rpcThr::runPendingIRPC() 
292 {
293     if (!pendingRPC_) {
294         return irpcNoIRPC;
295     }
296
297     inferiorrpc_printf("%s[%d]: running a pending IRPC on thread %lu\n",
298                        FILE__, __LINE__, thr_->get_tid());
299     
300     dyn_lwp *lwp = thr_->get_lwp();
301
302     // We passed the system call check, so the thread is in a state
303     // where it is possible to run iRPCs.
304     struct dyn_saved_regs *theSavedRegs = new dyn_saved_regs;
305     // Some platforms save daemon-side, some save process-side (on the stack)
306     // Should unify this.
307     bool saveFP = pendingRPC_->rpc->saveFPState;
308     bool status = lwp->getRegisters(theSavedRegs, saveFP);
309     inferiorrpc_printf("RPC saved registers: %d\n", status);
310
311     if (status == false) {
312         // Can happen if we're in a syscall, which is caught above
313         return irpcError;
314     }
315     assert(theSavedRegs);
316     
317     // RPC is actually going to be running
318     runningRPC_ = pendingRPC_;
319     pendingRPC_ = NULL;
320     mgr_->addRunningRPC(runningRPC_);
321     
322     // Build the in progress struct
323     runningRPC_->savedRegs = theSavedRegs;
324     runningRPC_->rpcthr = this;
325     runningRPC_->rpclwp = NULL;
326     
327     runningRPC_->rpcBaseAddr =
328     mgr_->createRPCImage(runningRPC_->rpc->action, // AST tree
329                          runningRPC_->rpc->noCost,
330                          (runningRPC_->rpc->callbackFunc != NULL), // Callback?
331                          runningRPC_->rpcStartAddr, // Fills in
332                          runningRPC_->rpcCompletionAddr, 
333                          runningRPC_->rpcResultAddr,
334                          runningRPC_->rpcContPostResultAddr,
335                          runningRPC_->resultRegister,
336                          runningRPC_->rpc->lowmem, 
337                          thr_,
338                          lwp ); // Where to allocate
339
340     if (!runningRPC_->rpcBaseAddr) {
341         cerr << "launchRPC failed, couldn't create image" << endl;
342         return irpcError;
343     }
344     
345     /* Why we don't just pass runningRPC_ into createRPCImage()... */
346     mgr_->proc()->addOrigRange( runningRPC_ );
347
348 #if !defined(i386_unknown_nt4_0) \
349  && !defined(mips_unknown_ce2_11)
350     // Actually, only need this if a restoreRegisters won't reset
351     // the PC back to the original value
352     Frame curFrame = lwp->getActiveFrame();
353     runningRPC_->origPC = curFrame.getPC();
354     inferiorrpc_printf("%s[%d]: thread %lu at PC 0x%lx, saving and setting to 0x%lx\n",
355                        FILE__, __LINE__, thr_->get_tid(), runningRPC_->origPC, runningRPC_->rpcStartAddr);
356 #endif    
357
358     // Launch this sucker. Change the PC, and the caller will set running
359 #if !defined(ia64_unknown_linux2_4)
360     if (!lwp->changePC(runningRPC_->rpcStartAddr, NULL)) {
361 #else
362         /* Syscalls can actually rewind the PC by 0x10, so we need
363            a bundle _before_ the new PC to check for this. */
364     if (!lwp->changePC(runningRPC_->rpcStartAddr + 0x10, NULL)) {
365 #endif
366         cerr << "launchRPC failed: couldn't set PC" << endl;
367         return irpcError;
368     }
369     inferiorrpc_printf("Changed PC to addr 0x%lx\n", runningRPC_->rpcStartAddr);
370 #if defined(i386_unknown_linux2_0) \
371  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
372       // handle system call interruption:
373       // if we interupted a system call, this clears the state that
374       // would cause the OS to restart the call when we run the rpc.
375       // if we did not, this is a no-op.
376       // after the rpc, an interrupted system call will
377       // be restarted when we restore the original
378       // registers (restore undoes clearOPC)
379       // note that executingSystemCall is always false on this platform.
380       if (!lwp->clearOPC())
381       {
382          cerr << "launchRPC failed because clearOPC() failed"
383               << endl;
384          return irpcError;
385       }
386 #endif
387
388       if (mgr_->proc()->IndependentLwpControl())
389           lwp->continueLWP(NoSignal, false);
390
391       return irpcStarted;
392
393 }
394
395 bool rpcThr::deleteThrIRPC(unsigned id) {
396     // Can remove a queued or pending thr IRPC
397     bool removed = false;
398
399     if (pendingRPC_ && pendingRPC_->rpc->id == id) {
400        // we don't want to do as we normally do when a exit trap occurs,
401        // that is to run the rpc, which gets triggered by this callback
402 #if defined(cap_syscall_trap)
403        get_thr()->get_lwp()->clearSyscallExitTrap();
404 #endif
405        
406         delete pendingRPC_->rpc;
407         delete pendingRPC_;
408         
409         pendingRPC_ = NULL;
410
411         // Should probably also remove a system call trap
412         // if one exists
413
414         return true;
415     }
416     
417     pdvector<inferiorRPCtoDo *> newPostedRPCs;
418     for (unsigned i = 0; i < postedRPCs_.size(); i++) {
419         if (postedRPCs_[i]->id == id) {
420             removed = true;
421         }
422         else {
423             newPostedRPCs.push_back(postedRPCs_[i]);
424         }
425     }
426     postedRPCs_ = newPostedRPCs;
427     return removed;
428 }
429
430 bool rpcThr::cancelThrIRPC(unsigned id) {
431   // It better be running...
432   assert (runningRPC_->rpc->id == id);
433
434   // We handle it as a completed, no-callback IRPC
435   runningRPC_->rpc->callbackFunc = NULL; /* Void the callback */
436
437   // I don't want to deal with "it finished" races...
438   assert(mgr_->proc()->isStopped());
439
440   return handleCompletedIRPC();
441 }
442
443 bool rpcThr::handleCompletedIRPC() 
444 {
445     // The LWP can be a different one than the lwp the RPC was originally
446     // started on if the thread was migrated.
447     dyn_lwp *lwp = thr_->get_lwp();
448     assert(lwp);
449
450 #if 0
451 #if defined(sparc_sun_solaris2_4)    
452     if(mgr_->proc()->multithread_capable() && runningRPC_->isProcessRPC) {
453         mgr_->processingProcessRPC = false;
454     }
455 #endif
456 #endif
457
458     inferiorrpc_printf("Completed thread RPC %d on thread %lu\n", runningRPC_->rpc->id, thr_->get_tid());
459
460     // step 1) restore registers:
461     if (runningRPC_->savedRegs) {
462         bool savedFP = runningRPC_->rpc->saveFPState;
463         if (!lwp->restoreRegisters(*runningRPC_->savedRegs, savedFP)) {
464
465             cerr << "handleCompletedIRPC failed because restoreRegisters failed"
466                  << endl;
467             assert(false);
468         }
469         delete runningRPC_->savedRegs;
470         runningRPC_->savedRegs = NULL;
471         // The above implicitly must restore the PC.
472     }
473     else
474         if (!lwp->changePC(runningRPC_->origPC, NULL)) 
475             assert(0 && "Failed to reset PC");
476     
477     // step 2) delete temp tramp
478     process *proc = lwp->proc();
479     proc->removeOrigRange(runningRPC_);
480     proc->inferiorFree(runningRPC_->rpcBaseAddr);
481
482     // save enough information to call the callback function, if needed
483     inferiorRPCcallbackFunc cb = runningRPC_->rpc->callbackFunc;
484     void* userData = runningRPC_->rpc->userData;
485     void* resultValue = runningRPC_->resultValue;
486     unsigned id = runningRPC_->rpc->id;
487
488     // Save whether we were running or not
489     bool runProcess = runningRPC_->runProcWhenDone;
490     
491     // And blow away the data structures
492     mgr_->removeRunningRPC(runningRPC_);
493     delete runningRPC_->rpc;
494     delete runningRPC_;
495     runningRPC_ = NULL;
496
497     int retstate = 0;
498
499     // step 3) invoke user callback, if any
500     // call the callback function if needed
501     if( cb != NULL ) {
502         inferiorrpc_printf("%s[%d][%s]:  about to exec/register rpc done callback\n", 
503                            FILE__, __LINE__, getThreadStr(getExecThreadID()));
504         retstate = cb(proc, id, userData, resultValue);
505     }
506
507     // Before we continue the process: if there is another RPC,
508     // start it immediately (instead of waiting for an event loop
509     // to do the job)
510     if (isReadyForIRPC()) {
511         irpcLaunchState_t launchState =
512         launchThrIRPC(runProcess);
513         if (launchState == irpcStarted) {
514             // Run the process
515             return true;
516         }
517     }
518     
519     if (retstate == RPC_RUN_WHEN_DONE)
520         return true;
521     
522     return runProcess;
523 }
524
525 // Get the return value (preperatory for a callback)
526 bool rpcThr::getReturnValueIRPC() 
527 {
528     if (!runningRPC_ || !runningRPC_->rpc->callbackFunc)
529         return false;
530
531     Address returnValue = 0;
532
533     dyn_lwp *thr_lwp = thr_->get_lwp();
534
535     // make sure lwp is stopped
536     if(thr_lwp->status() != stopped) {
537        return false;
538     }
539     
540     inferiorrpc_printf("%s[%d]: Getting return value for irpc %d, thr %lu\n",
541                        FILE__, __LINE__, runningRPC_->rpc->id, thr_->get_tid());
542
543     if (runningRPC_->resultRegister != Null_Register) {
544         // We have a result that we care about
545         returnValue = thr_lwp->readRegister(runningRPC_->resultRegister);
546     }
547
548     inferiorrpc_printf("%s[%d]: return value is %p\n", FILE__, __LINE__, returnValue);
549
550     runningRPC_->resultValue = (void *)returnValue;
551     // we continue the process...but not quite at the PC where we left off,
552     // since that will just re-do the trap!  Instead, we need to continue at
553     // the location of the next instruction.
554     inferiorrpc_printf("%s[%d]: changing RPC PC to continue address 0x%lx\n",
555                        FILE__, __LINE__, runningRPC_->rpcContPostResultAddr);
556     if (! thr_lwp->changePC(runningRPC_->rpcContPostResultAddr, NULL)) {
557         // What if we're exited?
558         inferiorrpc_printf("%s[%d]: FAILED TO SET continue PC\n",
559                            FILE__, __LINE__);
560         return false;
561     }
562
563     return true;
564 }
565
566 bool rpcThr::launchThrIRPCCallbackDispatch(dyn_lwp * /*lwp*/,
567                                            void *data)
568 {
569     rpcThr *thr = (rpcThr *)data;
570     // the runProcess code here is ignored if a pending RPC
571     // is already set (which must be true for this callback to
572     // happen)
573     irpcLaunchState_t launchState = thr->runPendingIRPC();
574     if (launchState == irpcStarted)
575       return true;
576     return false;
577 }
578
579
580 // Launch an inferior RPC
581 // Two cases: 
582 // 1) We have a pending RPC (in pendingRPC_) that we already prepped
583 //    and we want to run it (and a system call breakpoint was set)
584 // 2) We don't have a pending IRPC but there is one on the queue.
585 irpcLaunchState_t rpcThr::launchProcIRPC(bool runProcWhenDone) {
586
587     // Most important thing: find a LWP that's not blocked in a system call
588
589     if (runningRPC_ || pendingRPC_) {
590         return irpcError;
591     }
592     
593     if (mgr_->postedProcessRPCs_.size() == 0)
594         return irpcNoIRPC;
595
596     // We can run the RPC if we're not currently in a system call.
597     // This is defined as "any time we can't modify the state of the
598     // process". In this case we try and set a breakpoint when we leave
599     // the system call. If we can't set the breakpoint we poll.
600     dyn_lwp *lwp = thr_->get_lwp();
601     
602     inferiorrpc_printf("Thread %lu, lwp %u, checking status...\n", thr_->get_tid(), lwp->get_lwp_id());
603
604 #if defined(cap_syscall_trap)    
605     // Check if we're in a system call
606     if (lwp->executingSystemCall()) {
607         // No RPCs anyway
608         return irpcError;
609     }
610 #endif
611
612     inferiorrpc_printf("Status is go, grabbing process RPC and running\n");
613     // Get the RPC and slap it in the pendingRPC_ pointer
614     pendingRPC_ = new inferiorRPCinProgress;
615     // Take a process-wide RPC
616     pendingRPC_->rpc = mgr_->getProcessRPC();
617     // And it's running on this thread
618     pendingRPC_->rpc->thr = thr_;
619     pendingRPC_->isProcessRPC = true;
620     
621     pendingRPC_->runProcWhenDone = runProcWhenDone;
622     mgr_->addPendingRPC(pendingRPC_);
623
624     return runPendingIRPC();
625 }
626