static void* thread_start_mark(void *arg){ tar_threadstart threadstart=(tar_threadstart)arg; #if (!NO_SNAPSHOT) bound_thread_to_cpu(MARK_CPU); #else bound_thread_to_cpu(NONSNAPSHOT_MARK_CPU); #endif threadstart(); return NULL; }
static void* thread_start_free(void *arg){ tar_threadstart threadstart=(tar_threadstart)arg; bound_thread_to_cpu(FREE_CPU); threadstart(); return NULL; }
static void* thread_start_snapshot(void *arg){ tar_threadstart threadstart=(tar_threadstart)arg; threadstart(); return NULL; }
int ctlproc(int id, char *msg) { Thread *t; int status; // Hang/attached dance is for debugging newly exec'ed programs. // After fork, the child does ctlproc("hang") before exec, // and the parent does ctlproc("attached") and then waitstop. // Using these requires the BSD ptrace interface, unlike everything // else we do, which uses only the Mach interface. Our goal here // is to do as little as possible using ptrace and then flip over to Mach. if(strcmp(msg, "hang") == 0) return ptrace(PT_TRACE_ME, 0, 0, 0); if(strcmp(msg, "attached") == 0){ // The pid "id" has done a ctlproc "hang" and then // exec, so we should find it stoppped just before exec // of the new program. #undef waitpid if(waitpid(id, &status, WUNTRACED) < 0){ fprint(2, "ctlproc attached waitpid: %r\n"); return -1; } if(WIFEXITED(status) || !WIFSTOPPED(status)){ fprint(2, "ctlproc attached: bad process state\n"); return -1; } // Find Mach thread for pid and suspend it. t = addpid(id, 1); if(t == nil) return -1; if(me(thread_suspend(t->thread)) < 0){ fprint(2, "ctlproc attached: thread_suspend: %r\n"); return -1; } // Let ptrace tell the process to keep going: // then ptrace is out of the way and we're back in Mach land. return ptrace(PT_CONTINUE, id, (caddr_t)1, 0); } // All the other control messages require a Thread structure. if((t = idtotable(id)) == nil){ werrstr("no such thread"); return -1; } if(strcmp(msg, "kill") == 0) return ptrace(PT_KILL, t->pid, 0, 0); if(strcmp(msg, "start") == 0) return threadstart(t, 0); if(strcmp(msg, "stop") == 0) return threadstop(t); if(strcmp(msg, "startstop") == 0){ if(threadstart(t, 0) < 0) return -1; return waitstop(t); } if(strcmp(msg, "step") == 0){ if(threadstart(t, 1) < 0) return -1; return waitstop(t); } if(strcmp(msg, "waitstop") == 0) return waitstop(t); // sysstop not available on OS X werrstr("unknown control message"); return -1; }