[DTrace-devel] [PATCH 12/12] Implement TLS variables

Kris Van Hees kris.van.hees at oracle.com
Wed Nov 24 05:20:54 UTC 2021


On Tue, Nov 23, 2021 at 08:52:45PM -0500, Eugene Loh via DTrace-devel wrote:
> On 11/23/21 2:45 AM, Kris Van Hees wrote:
> 
> > On Mon, Nov 22, 2021 at 06:08:18PM -0500, Eugene Loh via DTrace-devel wrote:
> > > On 11/20/21 12:44 AM, Kris Van Hees via DTrace-devel wrote:
> > > > diff --git a/bpf/get_tvar.c b/bpf/get_tvar.c
> > > > @@ -10,12 +10,40 @@
> > > >    # define noinline	__attribute__((noinline))
> > > >    #endif
> > > > -extern struct bpf_map_def tvars;
> > > > +extern struct bpf_map_def dvars;
> > > > +extern uint64_t NCPUS;
> > > > -noinline uint64_t dt_get_tvar(uint32_t id)
> > > > +noinline void *dt_get_tvar(uint32_t id)
> > > >    {
> > > > -	uint64_t	*val;
> > > > +	uint64_t	key;
> > > > +	uint64_t	dflt_key = 0;;
> Double semicolon.

Yup

> > > > +	void		*val;
> > > > -	val = bpf_map_lookup_elem(&tvars, &id);
> > > > -	return val ? *val : 0;
> > > > +	key = bpf_get_current_pid_tgid();
> > > > +	key &= 0x00000000ffffffffUL;
> > > > +	if (key == 0)
> > > > +		key = bpf_get_smp_processor_id();
> > > > +	else
> > > > +		key += (uint32_t)(uint64_t)&NCPUS;
> > > > +
> > > > +	key++;
> > > > +	key = (key << 32) | id;
> > > > diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
> > > > @@ -213,36 +213,21 @@ populate_probes_map(dtrace_hdl_t *dtp, int fd)
> > > >     *		use.
> > > >     * - gvars:	Global variables map.  This is a global map with a singleton
> > > >     *		element (key 0) addressed by variable offset.
> > > > + * - dvars:	Dynamic variables map.  This is a global hash map index with
> > > > + *		a unique numeric identifier for each variable.
> > > Well, variable/pid combo.
> s/index/indexed/

yes

> and again not just per variable but also per pid

No, we look at it as distict variables, and thus each numeric identifier relates
to a single variable.  So, a single variable name (identifier) maps to multiple
variables (internally).

> > > > @@ -371,10 +354,19 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
> > > >    			sizeof(uint32_t), lvarsz, 1) == -1)
> > > >    		return -1;		/* dt_errno is set for us */
> > > > -	if (tvarc > 0 &&
> > > > -	    create_gmap(dtp, "tvars", BPF_MAP_TYPE_ARRAY,
> > > > -			sizeof(uint32_t), sizeof(uint64_t), tvarc) == -1)
> > > > -		return -1;		/* dt_errno is set for us */
> > > > +	if (dvarc > 0) {
> > > Speaking of which, is there a plan to get fancier on the sizing? We're
> > > allocating string space for everyone.  In many cases, that will be 256/4 or
> > > 256/8 times too much.  Meanwhile, for some structs, I guess it'll be too
> > > small.  Doesn't need to be fixed in the first patch, but maybe worth
> > > mentioning?
> > This is the challenge of doing tracing and supporting dynamic variables.  You
> > cannot really get into implementing fancy memory management.  And yes, later on
> > we will need to make the size be based on the largest datatype a variable can
> > have rather than strsize, so indeed it can be larger than strsize.
> But this should be mentioned in the commit message or somewhere.  If there
> are major limitations, they should be acknowledged.

Sure, I will add it to the commmit message.  Calling it a major limitation is
quite a stretch though.

> > > > diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> > > > @@ -2351,23 +2377,48 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
> > > >    	/* TLS var */
> > > >    	varid = idp->di_id - DIF_VAR_OTHER_UBASE;
> > > > -	idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_set_tvar");
> > > > +	size = idp->di_size;
> > > > +
> > > > +	idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_tvar");
> > > >    	assert(idp != NULL);
> > > >    	if (dt_regset_xalloc_args(drp) == -1)
> > > >    		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> > > > -	/*
> > > > -	 * We assign the varid in the instruction preceding the call because
> > > > -	 * the disassembler expects this sequence in support for annotating
> > > > -	 * the disassembly with variables names.
> > > > -	 */
> > > > -	emit(dlp,  BPF_MOV_REG(BPF_REG_2, dnp->dn_reg));
> > > >    	emit(dlp,  BPF_MOV_IMM(BPF_REG_1, varid));
> > > >    	dt_regset_xalloc(drp, BPF_REG_0);
> > > >    	emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
> > > > -	dt_regset_free(drp, BPF_REG_0);
> > > >    	dt_regset_free_args(drp);
> > > > +
> > > > +	if ((reg = dt_regset_alloc(drp)) == -1)
> > > > +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> > > > +
> > > > +	emit(dlp, BPF_MOV_REG(reg, BPF_REG_0));
> > > > +	dt_regset_free(drp, BPF_REG_0);
> > > > +
> > > > +	dt_cg_check_notnull(dlp, drp, reg);
> > > > +
> > > > +	if (dnp->dn_flags & DT_NF_REF) {
> > > > +		size_t		srcsz;
> > > > +
> > > > +		/*
> > > > +		 * Determine the amount of data to be copied.  It is
> > > > +		 * the lesser of the size of the identifier and the
> > > > +		 * size of the data being copied in.
> > > > +		 */
> > > > +		srcsz = dt_node_type_size(dnp->dn_right);
> > > > +		if (dt_node_is_string(dnp))
> > > > +			srcsz += DT_STRLEN_BYTES;
> > > > +		size = MIN(srcsz, size);
> > > I think neither "srcsz = dt_node_type_size(dnp->dn_right)" nor "size =
> > > idp->di_size" includes the NUL terminating byte.  Same with the pre-existing
> > > gvar/lvar code.
> > This is actually an interesting situation because dt_node_type_size() does
> > include the terminating NUL byte for string constants but not for regular
> > string types.  And di_size generally will not contain it either.  And as you
> > say, this applies to gvar and lvar as well.  So, I am inclined to leave it as
> > is in this patch and simply fix it for all three cases with a single patch.
> How do these bugs get tracked?

You file a bug for it :)

> > > > +
> > > > +		dt_cg_memcpy(dlp, drp, reg, dnp->dn_reg, size);
> > > > +	} else {
> > > > +		assert(size > 0 && size <= 8 && (size & (size - 1)) == 0);
> > > > +
> > > > +		emit(dlp, BPF_STORE(ldstw[size], reg, 0, dnp->dn_reg));
> > > > +	}
> > > > +
> > > > +	dt_regset_free(drp, reg);
> > > >    }
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list