dt_proc.c
来自「Sun Solaris 10 中的 DTrace 组件的源代码。请参看: htt」· C语言 代码 · 共 1,011 行 · 第 1/3 页
C
1,011 行
for (npr = *npp; npr != NULL; npr = npr->dpr_notify) { if (npr != dpr) npp = &npr->dpr_notify; else break; } if (npr != NULL) { *npp = npr->dpr_notify; npr->dpr_notify = NULL; } (void) pthread_mutex_unlock(&dph->dph_lock); /* * Remove the dt_proc_list from the LRU list, release the underlying * libproc handle, and free our dt_proc_t data structure. */ if (dpr->dpr_cacheable) { assert(dph->dph_lrucnt != 0); dph->dph_lrucnt--; } dt_list_delete(&dph->dph_lrulist, dpr); Prelease(dpr->dpr_proc, rflag); dt_free(dtp, dpr);}static intdt_proc_create_thread(dt_proc_t *dpr, uint_t stop){ sigset_t nset, oset; pthread_attr_t a; int err; (void) pthread_mutex_lock(&dpr->dpr_lock); dpr->dpr_stop |= stop; /* set bit for initial rendezvous */ (void) pthread_attr_init(&a); (void) pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); (void) sigfillset(&nset); (void) sigdelset(&nset, SIGABRT); /* unblocked for assert() */ (void) sigdelset(&nset, SIGCANCEL); /* see dt_proc_destroy() */ (void) pthread_sigmask(SIG_SETMASK, &nset, &oset); err = pthread_create(&dpr->dpr_tid, &a, dt_proc_control, dpr); (void) pthread_sigmask(SIG_SETMASK, &oset, NULL); /* * If the control thread was created, then wait on dpr_cv for either * dpr_done to be set (the victim died or the control thread failed) * or DT_PROC_STOP_IDLE to be set, indicating that the victim is now * stopped by /proc and the control thread is at the rendezvous event. * On success, we return with the process and control thread stopped: * the caller can then apply dt_proc_continue() to resume both. */ if (err == 0) { while (!dpr->dpr_done && !(dpr->dpr_stop & DT_PROC_STOP_IDLE)) (void) pthread_cond_wait(&dpr->dpr_cv, &dpr->dpr_lock); /* * If dpr_done is set, the control thread aborted before it * reached the rendezvous event. This is either due to PS_LOST * or PS_UNDEAD (i.e. the process died). We try to provide a * small amount of useful information to help figure it out. */ if (dpr->dpr_done) { const psinfo_t *prp = Ppsinfo(dpr->dpr_proc); int stat = prp ? prp->pr_wstat : 0; int pid = dpr->dpr_pid; if (Pstate(dpr->dpr_proc) == PS_LOST) { (void) dt_proc_error(dpr->dpr_hdl, dpr, "failed to control pid %d: process exec'd " "set-id or unobservable program\n", pid); } else if (WIFSIGNALED(stat)) { (void) dt_proc_error(dpr->dpr_hdl, dpr, "failed to control pid %d: process died " "from signal %d\n", pid, WTERMSIG(stat)); } else { (void) dt_proc_error(dpr->dpr_hdl, dpr, "failed to control pid %d: process exited " "with status %d\n", pid, WEXITSTATUS(stat)); } err = ESRCH; /* cause grab() or create() to fail */ } else { /* * Disable breakpoints while the process is stopped so * the pid provider can correctly disassemble all * functions. */ dt_proc_bpdisable(dpr); } } else { (void) dt_proc_error(dpr->dpr_hdl, dpr, "failed to create control thread for process-id %d: %s\n", (int)dpr->dpr_pid, strerror(err)); } (void) pthread_mutex_unlock(&dpr->dpr_lock); (void) pthread_attr_destroy(&a); return (err);}struct ps_prochandle *dt_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv){ dt_proc_hash_t *dph = dtp->dt_procs; dt_proc_t *dpr; int err; if ((dpr = dt_zalloc(dtp, sizeof (dt_proc_t))) == NULL) return (NULL); /* errno is set for us */ (void) pthread_mutex_init(&dpr->dpr_lock, NULL); (void) pthread_cond_init(&dpr->dpr_cv, NULL); if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) { return (dt_proc_error(dtp, dpr, "failed to execute %s: %s\n", file, Pcreate_error(err))); } dpr->dpr_hdl = dtp; dpr->dpr_pid = Pstatus(dpr->dpr_proc)->pr_pid; (void) Punsetflags(dpr->dpr_proc, PR_RLC); (void) Psetflags(dpr->dpr_proc, PR_KLC); if (dt_proc_create_thread(dpr, dtp->dt_prcmode) != 0) return (NULL); /* dt_proc_error() has been called for us */ dpr->dpr_hash = dph->dph_hash[dpr->dpr_pid & (dph->dph_hashlen - 1)]; dph->dph_hash[dpr->dpr_pid & (dph->dph_hashlen - 1)] = dpr; dt_list_prepend(&dph->dph_lrulist, dpr); dt_dprintf("created pid %d\n", (int)dpr->dpr_pid); dpr->dpr_refs++; return (dpr->dpr_proc);}struct ps_prochandle *dt_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags, int nomonitor){ dt_proc_hash_t *dph = dtp->dt_procs; uint_t h = pid & (dph->dph_hashlen - 1); dt_proc_t *dpr, *opr; int err; /* * Search the hash table for the pid. If it is already grabbed or * created, move the handle to the front of the lrulist, increment * the reference count, and return the existing ps_prochandle. */ for (dpr = dph->dph_hash[h]; dpr != NULL; dpr = dpr->dpr_hash) { if (dpr->dpr_pid == pid) { dt_dprintf("grabbed pid %d (cached)\n", (int)pid); dt_list_delete(&dph->dph_lrulist, dpr); dt_list_prepend(&dph->dph_lrulist, dpr); dpr->dpr_refs++; return (dpr->dpr_proc); } } if ((dpr = dt_zalloc(dtp, sizeof (dt_proc_t))) == NULL) return (NULL); /* errno is set for us */ (void) pthread_mutex_init(&dpr->dpr_lock, NULL); (void) pthread_cond_init(&dpr->dpr_cv, NULL); if ((dpr->dpr_proc = Pgrab(pid, flags, &err)) == NULL) { return (dt_proc_error(dtp, dpr, "failed to grab pid %d: %s\n", (int)pid, Pgrab_error(err))); } dpr->dpr_hdl = dtp; dpr->dpr_pid = pid; (void) Punsetflags(dpr->dpr_proc, PR_KLC); (void) Psetflags(dpr->dpr_proc, PR_RLC); /* * If we are attempting to grab the process without a monitor * thread, then mark the process as cacheable. If we're currently * caching more process handles than dph_lrulim permits, attempt to * find the least-recently-used handle that is currently * unreferenced and release it from the cache. Otherwise we are * grabbing the process for control: create a control thread for * this process and store its ID in dpr->dpr_tid. */ if (nomonitor || (flags & PGRAB_RDONLY)) { if (dph->dph_lrucnt >= dph->dph_lrulim) { for (opr = dt_list_prev(&dph->dph_lrulist); opr != NULL; opr = dt_list_prev(opr)) { if (opr->dpr_cacheable && opr->dpr_refs == 0) { dt_proc_destroy(dtp, opr->dpr_proc); break; } } } if (flags & PGRAB_RDONLY) { dpr->dpr_cacheable = B_TRUE; dph->dph_lrucnt++; } } else if (dt_proc_create_thread(dpr, DT_PROC_STOP_GRAB) != 0) return (NULL); /* dt_proc_error() has been called for us */ dpr->dpr_hash = dph->dph_hash[h]; dph->dph_hash[h] = dpr; dt_list_prepend(&dph->dph_lrulist, dpr); dt_dprintf("grabbed pid %d\n", (int)pid); dpr->dpr_refs++; return (dpr->dpr_proc);}voiddt_proc_release(dtrace_hdl_t *dtp, struct ps_prochandle *P){ dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); dt_proc_hash_t *dph = dtp->dt_procs; assert(dpr != NULL); assert(dpr->dpr_refs != 0); if (--dpr->dpr_refs == 0 && (!dpr->dpr_cacheable || dph->dph_lrucnt > dph->dph_lrulim)) dt_proc_destroy(dtp, P);}voiddt_proc_continue(dtrace_hdl_t *dtp, struct ps_prochandle *P){ dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); (void) pthread_mutex_lock(&dpr->dpr_lock); if (dpr->dpr_stop & DT_PROC_STOP_IDLE) { /* * Breakpoints are disabled while the process is stopped so * the pid provider can correctly disassemble all functions. */ dt_proc_bpenable(dpr); dpr->dpr_stop &= ~DT_PROC_STOP_IDLE; (void) pthread_cond_broadcast(&dpr->dpr_cv); } (void) pthread_mutex_unlock(&dpr->dpr_lock);}voiddt_proc_lock(dtrace_hdl_t *dtp, struct ps_prochandle *P){ dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); int err = pthread_mutex_lock(&dpr->dpr_lock); assert(err == 0); /* check for recursion */}voiddt_proc_unlock(dtrace_hdl_t *dtp, struct ps_prochandle *P){ dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); int err = pthread_mutex_unlock(&dpr->dpr_lock); assert(err == 0); /* check for unheld lock */}voiddt_proc_hash_create(dtrace_hdl_t *dtp){ if ((dtp->dt_procs = dt_zalloc(dtp, sizeof (dt_proc_hash_t) + sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) != NULL) { (void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL); (void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL); dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets; dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim; }}voiddt_proc_hash_destroy(dtrace_hdl_t *dtp){ dt_proc_hash_t *dph = dtp->dt_procs; dt_proc_t *dpr; while ((dpr = dt_list_next(&dph->dph_lrulist)) != NULL) dt_proc_destroy(dtp, dpr->dpr_proc); dtp->dt_procs = NULL; dt_free(dtp, dph);}struct ps_prochandle *dtrace_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv){ dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); struct ps_prochandle *P = dt_proc_create(dtp, file, argv); if (P != NULL && idp != NULL && idp->di_id == 0) idp->di_id = Pstatus(P)->pr_pid; /* $target = created pid */ return (P);}struct ps_prochandle *dtrace_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags){ dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); struct ps_prochandle *P = dt_proc_grab(dtp, pid, flags, 0); if (P != NULL && idp != NULL && idp->di_id == 0) idp->di_id = pid; /* $target = grabbed pid */ return (P);}voiddtrace_proc_release(dtrace_hdl_t *dtp, struct ps_prochandle *P){ dt_proc_release(dtp, P);}voiddtrace_proc_continue(dtrace_hdl_t *dtp, struct ps_prochandle *P){ dt_proc_continue(dtp, P);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?