⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fasttrap.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 5 页
字号:
		sprunlock(p);	} else {		/*		 * If the process is dead, we're just waiting for the		 * last probe to be disabled to be able to free it.		 */		if (provider->ftp_rcount == 0 && !provider->ftp_marked)			whack = provider->ftp_marked = 1;		mutex_exit(&provider->ftp_mtx);	}	if (whack)		fasttrap_pid_cleanup();	probe->ftp_enabled = 0;	ASSERT(MUTEX_HELD(&cpu_lock));	fasttrap_disable_common(&fasttrap_pid_count, &dtrace_pid_probe_ptr,	    &dtrace_return_probe_ptr);}/*ARGSUSED*/static voidfasttrap_pid_getargdesc(void *arg, dtrace_id_t id, void *parg,    dtrace_argdesc_t *desc){	fasttrap_probe_t *probe = parg;	char *str;	int i;	desc->dtargd_native[0] = '\0';	desc->dtargd_xlate[0] = '\0';	if (probe->ftp_prov->ftp_defunct != 0 ||	    desc->dtargd_ndx >= probe->ftp_nargs) {		desc->dtargd_ndx = DTRACE_ARGNONE;		return;	}	/*	 * We only need to set this member if the argument is remapped.	 */	if (probe->ftp_argmap != NULL)		desc->dtargd_mapping = probe->ftp_argmap[desc->dtargd_ndx];	str = probe->ftp_ntypes;	for (i = 0; i < desc->dtargd_mapping; i++) {		str += strlen(str) + 1;	}	ASSERT(strlen(str + 1) < sizeof (desc->dtargd_native));	(void) strcpy(desc->dtargd_native, str);	if (probe->ftp_xtypes == NULL)		return;	str = probe->ftp_xtypes;	for (i = 0; i < desc->dtargd_ndx; i++) {		str += strlen(str) + 1;	}	ASSERT(strlen(str + 1) < sizeof (desc->dtargd_xlate));	(void) strcpy(desc->dtargd_xlate, str);}/*ARGSUSED*/static voidfasttrap_destroy(void *arg, dtrace_id_t id, void *parg){	ASSERT(arg == NULL);	ASSERT(id == fasttrap_probe_id);}/*ARGSUSED*/static voidfasttrap_pid_destroy(void *arg, dtrace_id_t id, void *parg){	fasttrap_probe_t *probe = parg;	int i;	size_t size;	ASSERT(probe != NULL);	ASSERT(!probe->ftp_enabled);	ASSERT(fasttrap_total >= probe->ftp_ntps);	atomic_add_32(&fasttrap_total, -probe->ftp_ntps);	size = sizeof (fasttrap_probe_t) +	    sizeof (probe->ftp_tps[0]) * (probe->ftp_ntps - 1);	if (probe->ftp_gen + 1 >= fasttrap_mod_gen)		fasttrap_mod_barrier(probe->ftp_gen);	for (i = 0; i < probe->ftp_ntps; i++) {		kmem_free(probe->ftp_tps[i].fit_tp,		    sizeof (fasttrap_tracepoint_t));	}	kmem_free(probe, size);}static const dtrace_pattr_t fasttrap_attr = {{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },};static dtrace_pops_t fasttrap_pops = {	fasttrap_provide,	NULL,	fasttrap_enable,	fasttrap_disable,	NULL,	NULL,	NULL,	fasttrap_getarg,	NULL,	fasttrap_destroy};static const dtrace_pattr_t pid_attr = {{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },};static dtrace_pops_t pid_pops = {	fasttrap_pid_provide,	NULL,	fasttrap_pid_enable,	fasttrap_pid_disable,	NULL,	NULL,	fasttrap_pid_getargdesc,	fasttrap_getarg,	NULL,	fasttrap_pid_destroy};static dtrace_pops_t usdt_pops = {	fasttrap_pid_provide,	NULL,	fasttrap_pid_enable,	fasttrap_pid_disable,	NULL,	NULL,	fasttrap_pid_getargdesc,	fasttrap_usdt_getarg,	NULL,	fasttrap_pid_destroy};/* * Lookup a fasttrap-managed provider based on its name and associated pid. * If the pattr argument is non-NULL, this function instantiates the provider * if it doesn't exist otherwise it returns NULL. The provider is returned * with its lock held. */static fasttrap_provider_t *fasttrap_provider_lookup(pid_t pid, const char *name,    const dtrace_pattr_t *pattr){	fasttrap_provider_t *fp, *new_fp = NULL;	fasttrap_bucket_t *bucket;	char provname[DTRACE_PROVNAMELEN];	proc_t *p;	uid_t uid = (uid_t)-1;	ASSERT(strlen(name) < sizeof (fp->ftp_name));	bucket = &fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)];	mutex_enter(&bucket->ftb_mtx);	/*	 * Take a lap through the list and return the match if we find it.	 */	for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {		if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&		    !fp->ftp_defunct) {			mutex_enter(&fp->ftp_mtx);			mutex_exit(&bucket->ftb_mtx);			return (fp);		}	}	/*	 * Drop the bucket lock so we don't try to perform a sleeping	 * allocation under it.	 */	mutex_exit(&bucket->ftb_mtx);	if (pattr == NULL)		return (NULL);	/*	 * Make sure the process exists, isn't a child created as the result	 * of a vfork(2), and isn't a zombie (but may be in fork). Record the	 * process's uid to pass to dtrace_register().	 */	mutex_enter(&pidlock);	if ((p = prfind(pid)) == NULL ||	    (p->p_flag & (SVFORK | SEXITLWPS)) ||	    (p->p_lwpcnt == 0 && p->p_lwpdir != NULL)) {		mutex_exit(&pidlock);		return (NULL);	}	mutex_enter(&p->p_lock);	mutex_exit(&pidlock);	/*	 * Increment p_dtrace_probes so that the process knows to inform us	 * when it exits or execs. fasttrap_provider_free() decrements this	 * when we're done with this provider.	 */	p->p_dtrace_probes++;	mutex_enter(&p->p_crlock);	uid = crgetruid(p->p_cred);	mutex_exit(&p->p_crlock);	mutex_exit(&p->p_lock);	new_fp = kmem_zalloc(sizeof (fasttrap_provider_t), KM_SLEEP);	mutex_enter(&bucket->ftb_mtx);	/*	 * Take another lap through the list to make sure a provider hasn't	 * been created for this pid while we weren't under the bucket lock.	 */	for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {		if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&		    !fp->ftp_defunct) {			mutex_enter(&fp->ftp_mtx);			mutex_exit(&bucket->ftb_mtx);			fasttrap_provider_free(new_fp);			return (fp);		}	}	new_fp->ftp_pid = pid;	(void) strcpy(new_fp->ftp_name, name);	/*	 * Fail and return NULL if either the provider name is too long	 * or we fail to register this new provider with the DTrace	 * framework. Note that this is the only place we ever construct	 * the full provider name -- we keep it in pieces in the provider	 * structure.	 */	if (snprintf(provname, sizeof (provname), "%s%u", name, (uint_t)pid) >=	    sizeof (provname) ||	    dtrace_register(provname, pattr,	    DTRACE_PRIV_PROC | DTRACE_PRIV_OWNER, uid,	    pattr == &pid_attr ? &pid_pops : &usdt_pops, new_fp,	    &new_fp->ftp_provid) != 0) {		mutex_exit(&bucket->ftb_mtx);		fasttrap_provider_free(new_fp);		return (NULL);	}	new_fp->ftp_next = bucket->ftb_data;	bucket->ftb_data = new_fp;	mutex_enter(&new_fp->ftp_mtx);	mutex_exit(&bucket->ftb_mtx);	return (new_fp);}static voidfasttrap_provider_free(fasttrap_provider_t *provider){	pid_t pid = provider->ftp_pid;	proc_t *p;	/*	 * There need to be no consumers using this provider and no	 * associated enabled probes.	 */	ASSERT(provider->ftp_ccount == 0);	ASSERT(provider->ftp_rcount == 0);	kmem_free(provider, sizeof (fasttrap_provider_t));	/*	 * Decrement p_dtrace_probes on the process whose provider we're	 * freeing. We don't have to worry about clobbering somone else's	 * modifications to it because we have locked the bucket that	 * corresponds to this process's hash chain in the provider hash	 * table. Don't sweat it if we can't find the process.	 */	mutex_enter(&pidlock);	if ((p = prfind(pid)) == NULL) {		mutex_exit(&pidlock);		return;	}	mutex_enter(&p->p_lock);	mutex_exit(&pidlock);	p->p_dtrace_probes--;	mutex_exit(&p->p_lock);}static voidfasttrap_provider_retire(fasttrap_provider_t *provider){	dtrace_provider_id_t provid = provider->ftp_provid;	/*	 * Mark the provider to be removed in our post-processing step	 * and mark it as defunct. The former indicates that we should try	 * to remove it, the latter indicates that even if we were unable	 * to remove it, this provider shouldn't be used to create probes	 * in the future.	 */	provider->ftp_defunct = 1;	provider->ftp_marked = 1;	mutex_exit(&provider->ftp_mtx);	/*	 * We don't have to worry about invalidating the same provider twice	 * since fasttrap_provider_lookup() will ignore provider that have	 * been marked as defunct.	 */	dtrace_invalidate(provid);	fasttrap_pid_cleanup();}static intfasttrap_add_probe(fasttrap_probe_spec_t *pdata){	fasttrap_provider_t *provider;	fasttrap_probe_t *pp;	fasttrap_tracepoint_t *tp;	char *name;	size_t size;	int i, aframes, whack;	switch (pdata->ftps_type) {	case DTFTP_ENTRY:		name = "entry";		aframes = FASTTRAP_ENTRY_AFRAMES;		break;	case DTFTP_RETURN:		name = "return";		aframes = FASTTRAP_RETURN_AFRAMES;		break;	case DTFTP_OFFSETS:		name = NULL;		break;	default:		return (EINVAL);	}	if ((provider = fasttrap_provider_lookup(pdata->ftps_pid,	    FASTTRAP_PID_NAME, &pid_attr)) == NULL)		return (ESRCH);	/*	 * Increment this reference count to indicate that a consumer is	 * actively adding a new probe associated with this provider.	 */	provider->ftp_ccount++;	mutex_exit(&provider->ftp_mtx);	if (name != NULL) {		if (dtrace_probe_lookup(provider->ftp_provid,		    pdata->ftps_mod, pdata->ftps_func, name) != 0)			goto done;		atomic_add_32(&fasttrap_total, pdata->ftps_noffs);		if (fasttrap_total > fasttrap_max) {			atomic_add_32(&fasttrap_total, -pdata->ftps_noffs);			goto no_mem;		}		ASSERT(pdata->ftps_noffs > 0);		size = sizeof (fasttrap_probe_t) +		    sizeof (pp->ftp_tps[0]) * (pdata->ftps_noffs - 1);		pp = kmem_zalloc(size, KM_SLEEP);		pp->ftp_prov = provider;		pp->ftp_faddr = pdata->ftps_pc;		pp->ftp_fsize = pdata->ftps_size;		pp->ftp_pid = pdata->ftps_pid;		pp->ftp_ntps = pdata->ftps_noffs;		pp->ftp_type = pdata->ftps_type;		for (i = 0; i < pdata->ftps_noffs; i++) {			tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t),			    KM_SLEEP);			tp->ftt_prov = provider;			tp->ftt_pc = pdata->ftps_offs[i] + pdata->ftps_pc;			tp->ftt_pid = pdata->ftps_pid;			pp->ftp_tps[i].fit_tp = tp;			pp->ftp_tps[i].fit_id.fti_probe = pp;		}		pp->ftp_id = dtrace_probe_create(provider->ftp_provid,		    pdata->ftps_mod, pdata->ftps_func, name, aframes, pp);	} else {		for (i = 0; i < pdata->ftps_noffs; i++) {			char name_str[17];			(void) sprintf(name_str, "%llx",			    (unsigned long long)pdata->ftps_offs[i]);			if (dtrace_probe_lookup(provider->ftp_provid,			    pdata->ftps_mod, pdata->ftps_func, name_str) != 0)				continue;			atomic_add_32(&fasttrap_total, 1);			if (fasttrap_total > fasttrap_max) {				atomic_add_32(&fasttrap_total, -1);				goto no_mem;			}			pp = kmem_zalloc(sizeof (fasttrap_probe_t), KM_SLEEP);			pp->ftp_prov = provider;			pp->ftp_faddr = pdata->ftps_pc;			pp->ftp_fsize = pdata->ftps_size;			pp->ftp_pid = pdata->ftps_pid;			pp->ftp_ntps = 1;			pp->ftp_type = pdata->ftps_type;			tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t),			    KM_SLEEP);			tp->ftt_prov = provider;			tp->ftt_pc = pdata->ftps_offs[i] + pdata->ftps_pc;			tp->ftt_pid = pdata->ftps_pid;			pp->ftp_tps[0].fit_tp = tp;			pp->ftp_tps[0].fit_id.fti_probe = pp;			pp->ftp_id = dtrace_probe_create(provider->ftp_provid,			    pdata->ftps_mod, pdata->ftps_func, name_str,			    FASTTRAP_OFFSET_AFRAMES, pp);		}	}done:	/*	 * We know that the provider is still valid since we incremented the	 * reference count. If someone tried to free this provider while we	 * were using it (e.g. because the process called exec(2) or exit(2)),	 * take note of that and try to free it now.	 */	mutex_enter(&provider->ftp_mtx);	provider->ftp_ccount--;	whack = provider->ftp_defunct;	mutex_exit(&provider->ftp_mtx);	if (whack)		fasttrap_pid_cleanup();	return (0);no_mem:	/*	 * If we've exhausted the allowable resources, we'll try to remove	 * this provider to free some up. This is to cover the case where	 * the user has accidentally created many more probes than was	 * intended (e.g. pid123:::).	 */	mutex_enter(&provider->ftp_mtx);	provider->ftp_ccount--;	provider->ftp_marked = 1;	mutex_exit(&provider->ftp_mtx);	fasttrap_pid_cleanup();	return (ENOMEM);}/*ARGSUSED*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -