FreeBSD/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c
/*
 * 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.
 */
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.
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;
	cred_t *cred;
	ASSERT(strlen(name) < sizeof (fp->ftp_name));
	ASSERT(pattr != NULL);
	bucket = &fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)];
	mutex_enter(&bucket->ftb_mtx);
	for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
		if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
		    !fp->ftp_retired) {
			mutex_enter(&fp->ftp_mtx);
			mutex_exit(&bucket->ftb_mtx);
			return (fp);
		}
	}
	mutex_exit(&bucket->ftb_mtx);
	if ((p = pfind(pid)) == NULL)
		return (NULL);
	p->p_dtrace_probes++;
	PROC_LOCK_ASSERT(p, MA_OWNED);
	crhold(p->p_ucred);
	cred = p->p_ucred;
	PROC_UNLOCK(p);
	new_fp = kmem_zalloc(sizeof (fasttrap_provider_t), KM_SLEEP);
	new_fp->ftp_pid = pid;
	new_fp->ftp_proc = fasttrap_proc_lookup(pid);
#ifndef illumos
	mutex_init(&new_fp->ftp_mtx, "provider mtx", MUTEX_DEFAULT, NULL);
	mutex_init(&new_fp->ftp_cmtx, "lock on creating", MUTEX_DEFAULT, NULL);
#endif
	ASSERT(new_fp->ftp_proc != NULL);
	mutex_enter(&bucket->ftb_mtx);
	for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
		if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
		    !fp->ftp_retired) {
			mutex_enter(&fp->ftp_mtx);
			mutex_exit(&bucket->ftb_mtx);
			fasttrap_provider_free(new_fp);
			crfree(cred);
			return (fp);
		}
	}
	(void) strcpy(new_fp->ftp_name, name);
	if (snprintf(provname, sizeof (provname), "%s%u", name, (uint_t)pid) >=
	    sizeof (provname) ||
	    dtrace_register(provname, pattr,
	    DTRACE_PRIV_PROC | DTRACE_PRIV_OWNER | DTRACE_PRIV_ZONEOWNER, cred,
	    pattr == &pid_attr ? &pid_pops : &usdt_pops, new_fp,
	    &new_fp->ftp_provid) != 0) {
		mutex_exit(&bucket->ftb_mtx);
		fasttrap_provider_free(new_fp);
		crfree(cred);
		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);
	crfree(cred);
	return (new_fp);
}
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 ; cred_t * cred ; ASSERT ( strlen ( name ) < sizeof ( fp -> ftp_name ) ) ; ASSERT ( pattr != NULL ) ; bucket = & fasttrap_provs . fth_table [ FASTTRAP_PROVS_INDEX ( pid , name ) ] ; mutex_enter ( & bucket -> ftb_mtx ) ; for ( fp = bucket -> ftb_data ; fp != NULL ; fp = fp -> ftp_next ) { if ( fp -> ftp_pid == pid && strcmp ( fp -> ftp_name , name ) == 0 && ! fp -> ftp_retired ) { mutex_enter ( & fp -> ftp_mtx ) ; mutex_exit ( & bucket -> ftb_mtx ) ; return ( fp ) ; } } mutex_exit ( & bucket -> ftb_mtx ) ; if ( ( p = pfind ( pid ) ) == NULL ) return ( NULL ) ; p -> p_dtrace_probes ++ ; PROC_LOCK_ASSERT ( p , MA_OWNED ) ; crhold ( p -> p_ucred ) ; cred = p -> p_ucred ; PROC_UNLOCK ( p ) ; new_fp = kmem_zalloc ( sizeof ( fasttrap_provider_t ) , KM_SLEEP ) ; new_fp -> ftp_pid = pid ; new_fp -> ftp_proc = fasttrap_proc_lookup ( pid ) ; #ifndef illumos mutex_init ( & new_fp -> ftp_mtx , " " , MUTEX_DEFAULT , NULL ) ; mutex_init ( & new_fp -> ftp_cmtx , " " , MUTEX_DEFAULT , NULL ) ; #endif ASSERT ( new_fp -> ftp_proc != NULL ) ; mutex_enter ( & bucket -> ftb_mtx ) ; for ( fp = bucket -> ftb_data ; fp != NULL ; fp = fp -> ftp_next ) { if ( fp -> ftp_pid == pid && strcmp ( fp -> ftp_name , name ) == 0 && ! fp -> ftp_retired ) { mutex_enter ( & fp -> ftp_mtx ) ; mutex_exit ( & bucket -> ftb_mtx ) ; fasttrap_provider_free ( new_fp ) ; crfree ( cred ) ; return ( fp ) ; } } ( void ) strcpy ( new_fp -> ftp_name , name ) ; if ( snprintf ( provname , sizeof ( provname ) , " " , name , ( uint_t ) pid ) >= sizeof ( provname ) || dtrace_register ( provname , pattr , DTRACE_PRIV_PROC | DTRACE_PRIV_OWNER | DTRACE_PRIV_ZONEOWNER , cred , pattr == & pid_attr ? & pid_pops : & usdt_pops , new_fp , & new_fp -> ftp_provid ) != 0 ) { mutex_exit ( & bucket -> ftb_mtx ) ; fasttrap_provider_free ( new_fp ) ; crfree ( cred ) ; 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 ) ; crfree ( cred ) ; return ( new_fp ) ; }
Lookup a fasttrap-managed provider based on its name and associated pid.
Lookup a fasttrap - managed provider based on its name and associated pid .
/*
	 * Take a lap through the list and return the match if we find it.
	 */ /*
	 * Drop the bucket lock so we don't try to perform a sleeping
	 * allocation under it.
	 */ /*
	 * 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).
	 */ /*
	 * 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.
	 */ /*
	 * Grab the credentials for this process so we have
	 * something to pass to dtrace_register().
	 */ /*
	 * 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.
	 */ /*
	 * 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.
	 */