Exemple #1
0
void
dt_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 */
}
Exemple #2
0
void
dt_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);
}
Exemple #3
0
void
dt_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) {
		dpr->dpr_stop &= ~DT_PROC_STOP_IDLE;
		(void) pthread_cond_broadcast(&dpr->dpr_cv);
	}

	(void) pthread_mutex_unlock(&dpr->dpr_lock);
}
Exemple #4
0
static void
dt_proc_destroy(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;
	dt_proc_notify_t *npr, **npp;
	int rflag;

	assert(dpr != NULL);

	/*
	 * If neither PR_KLC nor PR_RLC is set, then the process is stopped by
	 * an external debugger and we were waiting in dt_proc_waitrun().
	 * Leave the process in this condition using PRELEASE_HANG.
	 */
printf("dt_proc_destroy flags=%d\n", Pstatus(dpr->dpr_proc)->pr_flags);
	if (!(Pstatus(dpr->dpr_proc)->pr_flags & (PR_KLC | PR_RLC))) {
		dt_dprintf("abandoning pid %d\n", (int)dpr->dpr_pid);
		rflag = PRELEASE_HANG;
	} else {
		dt_dprintf("releasing pid %d\n", (int)dpr->dpr_pid);
		rflag = 0; /* apply kill or run-on-last-close */
	}

	if (dpr->dpr_tid) {
		/*
		 * Set the dpr_quit flag to tell the daemon thread to exit.  We
		 * send it a SIGCANCEL to poke it out of PCWSTOP or any other
		 * long-term /proc system call.  Our daemon threads have POSIX
		 * cancellation disabled, so EINTR will be the only effect.  We
		 * then wait for dpr_done to indicate the thread has exited.
		 *
		 * We can't use pthread_kill() to send SIGCANCEL because the
		 * interface forbids it and we can't use pthread_cancel()
		 * because with cancellation disabled it won't actually
		 * send SIGCANCEL to the target thread, so we use _lwp_kill()
		 * to do the job.  This is all built on evil knowledge of
		 * the details of the cancellation mechanism in libc.
		 */
		(void) pthread_mutex_lock(&dpr->dpr_lock);
		dpr->dpr_quit = B_TRUE;
#if defined(sun)
		(void) _lwp_kill(dpr->dpr_tid, SIGCANCEL);
#else
		(void) pthread_kill(dpr->dpr_tid, SIGUSR1);
#endif

		/*
		 * If the process is currently idling in dt_proc_stop(), re-
		 * enable breakpoints and poke it into running again.
		 */
		if (dpr->dpr_stop & DT_PROC_STOP_IDLE) {
			dt_proc_bpenable(dpr);
			dpr->dpr_stop &= ~DT_PROC_STOP_IDLE;
			(void) pthread_cond_broadcast(&dpr->dpr_cv);
		}

		while (!dpr->dpr_done)
			(void) pthread_cond_wait(&dpr->dpr_cv, &dpr->dpr_lock);

		(void) pthread_mutex_unlock(&dpr->dpr_lock);
	}

	/*
	 * Before we free the process structure, remove this dt_proc_t from the
	 * lookup hash, and then walk the dt_proc_hash_t's notification list
	 * and remove this dt_proc_t if it is enqueued.
	 */
	(void) pthread_mutex_lock(&dph->dph_lock);
	(void) dt_proc_lookup(dtp, P, B_TRUE);
	npp = &dph->dph_notify;

	while ((npr = *npp) != NULL) {
		if (npr->dprn_dpr == dpr) {
			*npp = npr->dprn_next;
			dt_free(dtp, npr);
		} else {
			npp = &npr->dprn_next;
		}
	}

	(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);
}
Exemple #5
0
int
dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
{
	char provname[DTRACE_PROVNAMELEN];
	struct ps_prochandle *P;
	dt_proc_t *dpr;
	pid_t pid;
	int err = 0;

	assert(pcb != NULL);

	if ((pid = dt_pid_get_pid(pdp, dtp, pcb, NULL)) == -1)
		return (-1);

	if (dtp->dt_ftfd == -1) {
		if (dtp->dt_fterr == ENOENT) {
			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV,
			    "pid provider is not installed on this system");
		} else {
			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV,
			    "pid provider is not available: %s",
			    strerror(dtp->dt_fterr));
		}

		return (-1);
	}

	(void) snprintf(provname, sizeof (provname), "pid%d", (int)pid);

	if (gmatch(provname, pdp->dtpd_provider) != 0) {
		if ((P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE,
		    0)) == NULL) {
			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,
			    "failed to grab process %d", (int)pid);
			return (-1);
		}

		dpr = dt_proc_lookup(dtp, P, 0);
		assert(dpr != NULL);
		(void) pthread_mutex_lock(&dpr->dpr_lock);

		if ((err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr)) == 0) {
			/*
			 * Alert other retained enablings which may match
			 * against the newly created probes.
			 */
			(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);
		}

		(void) pthread_mutex_unlock(&dpr->dpr_lock);
		dt_proc_release(dtp, P);
	}

	/*
	 * If it's not strictly a pid provider, we might match a USDT provider.
	 */
	if (strcmp(provname, pdp->dtpd_provider) != 0) {
		if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL) {
			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,
			    "failed to grab process %d", (int)pid);
			return (-1);
		}

		dpr = dt_proc_lookup(dtp, P, 0);
		assert(dpr != NULL);
		(void) pthread_mutex_lock(&dpr->dpr_lock);

		if (!dpr->dpr_usdt) {
			err = dt_pid_create_usdt_probes(pdp, dtp, pcb, dpr);
			dpr->dpr_usdt = B_TRUE;
		}

		(void) pthread_mutex_unlock(&dpr->dpr_lock);
		dt_proc_release(dtp, P);
	}

	return (err ? -1 : 0);
}