[DTrace-devel] [PATCH] Refactor the versioning handling system

Eugene Loh eugene.loh at oracle.com
Fri Feb 28 20:55:03 UTC 2025


How about eliminating DT_VERS_LATEST?  It seems cumbersome and 
unnecessary to maintain manually.

Do tests pass with this patch?  How about:
         test/unittest/options/tst.version.sh
         test/unittest/dtrace-util/tst.APIVersion.d
Is the plan to update such tests with each new version of DTrace?

Ideally (well, in my opinion), it'd be nice if the patch were factored 
into multiple patches.  The big code movement that merely moves stuff 
from one file to another would come first.  Then, the smaller changes 
that actually change how things are done can be in a smaller patch.  
(Yeah, I know:  subjective and a question of whether to make things more 
tedious for the submitter or the reviewer of the changes.)

Did it use to be the case that when you ran DTrace you would want to 
know both what version of the tool is this and what version of the API?  
But now there is only one version number?  We've been going that way 
anyhow, but maybe if we're committing to that simpler versioning, we 
should say so?  (The whole topic confused me, in any case.)

Also...

On 2/27/25 22:09, Kris Van Hees via DTrace-devel wrote:

> DTrace was handlings versioning data in multiple locations, causing
> common mistakes in not consistently updating versions in allplaces.

s/allplaces/all places/

> By consolidating all versioning data in dt_version.h a single file

For me, a comma after dt_version.h would help with readability.

> need to be updated (as far as the source tree is concerned) when a

s/need/needs/?

> new version is introduced.
>
> For building, the GNUmakefile and dtrace.spec files will also need
> to be updated with the new version number.

Maybe this comment about GNUmakefile and dtrace.spec should be in 
dt_version.h?  Also, what about libdtrace/Build (and libdtrace_VERSION)?

> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> ---
>   libdtrace/Build        |   1 +
>   libdtrace/dt_impl.h    |  48 ++++++++-----------
>   libdtrace/dt_open.c    |  19 --------
>   libdtrace/dt_subr.c    |  80 --------------------------------
>   libdtrace/dt_version.c |  93 +++++++++++++++++++++++++++++++++++++
>   libdtrace/dt_version.h | 102 ++++++++++++++++++++++++++++-------------
>   6 files changed, 181 insertions(+), 162 deletions(-)
>   create mode 100644 libdtrace/dt_version.c
>
> diff --git a/libdtrace/Build b/libdtrace/Build
> index 51e0f078..57804f55 100644
> --- a/libdtrace/Build
> +++ b/libdtrace/Build
> @@ -70,6 +70,7 @@ libdtrace-build_SOURCES = dt_aggregate.c \
>   			  dt_strtab.c \
>   			  dt_subr.c \
>   			  dt_symtab.c \
> +			  dt_version.c \
>   			  dt_work.c \
>   			  dt_xlator.c
>   
> diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
> index 68fb8ec5..60e9b0c9 100644
> --- a/libdtrace/dt_impl.h
> +++ b/libdtrace/dt_impl.h
> @@ -256,8 +256,6 @@ typedef struct dt_percpu_drops {
>    */
>   #define DT_MAX_NSPECS 16		/* sanity upper bound on speculations */
>   
> -typedef uint32_t dt_version_t;		/* encoded version (see below) */
> -
>   struct dtrace_hdl {
>   	const dtrace_vector_t *dt_vector; /* library vector, if vectored open */
>   	void *dt_varg;	/* vector argument, if vectored open */
> @@ -645,6 +643,24 @@ enum {
>   	EDT_PRINT,		/* missing or corrupt print() record */
>   };
>   
> +/*
> + * Stability definitions
> + *
> + * These #defines are used in the tables of identifiers below to fill in the
> + * attribute fields associated with each identifier.  The DT_ATTR_* macros are
> + * a convenience to permit more concise declarations of common attributes such
> + * as Stable/Stable/Common.
> + *
> + * Refer to the Solaris Dynamic Tracing Guide Stability chapter respectively
> + * for an explanation of these DTrace features and their values.
> + */
> +#define DT_ATTR_STABCMN { DTRACE_STABILITY_STABLE, \
> +	DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }
> +
> +#define DT_ATTR_EVOLCMN { DTRACE_STABILITY_EVOLVING, \
> +	DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON \
> +}
> +
>   /*
>    * Interfaces for parsing and comparing DTrace attribute tuples, which describe
>    * stability and architectural binding information.
> @@ -654,31 +670,6 @@ extern dtrace_attribute_t dt_attr_max(dtrace_attribute_t, dtrace_attribute_t);
>   extern char *dt_attr_str(dtrace_attribute_t, char *, size_t);
>   extern int dt_attr_cmp(dtrace_attribute_t, dtrace_attribute_t);
>   
> -/*
> - * Interfaces for parsing and handling DTrace version strings.  Version binding
> - * is a feature of the D compiler that is handled completely independently of
> - * the DTrace kernel infrastructure, so the definitions are here in libdtrace.
> - * Version strings are compiled into an encoded uint32_t which can be compared
> - * using C comparison operators.  Version definitions are found in dt_open.c.
> - */
> -#define	DT_VERSION_STRMAX	16	/* enough for "255.4095.4095\0" */
> -#define	DT_VERSION_MAJMAX	0xFF	/* maximum major version number */
> -#define	DT_VERSION_MINMAX	0xFFF	/* maximum minor version number */
> -#define	DT_VERSION_MICMAX	0xFFF	/* maximum micro version number */
> -
> -#define	DT_VERSION_NUMBER(M, m, u) \
> -	((((M) & 0xFF) << 24) | (((m) & 0xFFF) << 12) | ((u) & 0xFFF))
> -
> -#define	DT_VERSION_MAJOR(v)	(((v) & 0xFF000000) >> 24)
> -#define	DT_VERSION_MINOR(v)	(((v) & 0x00FFF000) >> 12)
> -#define	DT_VERSION_MICRO(v)	((v) & 0x00000FFF)
> -
> -extern char *dt_version_num2str(dt_version_t, char *, size_t);
> -extern int dt_version_str2num(const char *, dt_version_t *);
> -extern int dt_version_defined(dt_version_t);
> -
> -extern int dt_str2kver(const char *, dt_version_t *);
> -
>   extern uint32_t dt_gen_hval(const char *, uint32_t, size_t);
>   
>   /*
> @@ -816,9 +807,6 @@ extern const dtrace_attribute_t _dtrace_typattr; /* type ref attributes */
>   extern const dtrace_attribute_t _dtrace_prvattr; /* provider attributes */
>   extern const dtrace_pattr_t _dtrace_prvdesc;	 /* provider attribute bundle */
>   
> -extern const dt_version_t _dtrace_versions[];	 /* array of valid versions */
> -extern const char *const _dtrace_version;	 /* current version string */
> -
>   extern int _dtrace_strbuckets;		/* number of hash buckets for strings */
>   extern uint_t _dtrace_stkindent;	/* default indent for stack/ustack */
>   extern uint_t _dtrace_pidbuckets;	/* number of hash buckets for pids */
> diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
> index 51c056b2..72c138ce 100644
> --- a/libdtrace/dt_open.c
> +++ b/libdtrace/dt_open.c
> @@ -42,25 +42,6 @@
>   #include <dt_peb.h>
>   #include <dt_pid.h>
>   
> -const dt_version_t _dtrace_versions[] = {
> -	DT_VERS_1_0,	/* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
> -	DT_VERS_1_1,	/* D API 1.1.0 Solaris Express 6/05 */
> -	DT_VERS_1_2,	/* D API 1.2.0 Solaris 10 Update 1 */
> -	DT_VERS_1_2_1,	/* D API 1.2.1 Solaris Express 4/06 */
> -	DT_VERS_1_2_2,	/* D API 1.2.2 Solaris Express 6/06 */
> -	DT_VERS_1_3,	/* D API 1.3 Solaris Express 10/06 */
> -	DT_VERS_1_4,	/* D API 1.4 Solaris Express 2/07 */
> -	DT_VERS_1_4_1,	/* D API 1.4.1 Solaris Express 4/07 */
> -	DT_VERS_1_5,	/* D API 1.5 Solaris Express 7/07 */
> -	DT_VERS_1_6,	/* D API 1.6 */
> -	DT_VERS_1_6_1,	/* D API 1.6.1 */
> -	DT_VERS_1_6_2,	/* D API 1.6.2 */
> -	DT_VERS_1_6_3,	/* D API 1.6.3 */
> -	DT_VERS_1_6_4,	/* D API 1.6.4 */
> -	DT_VERS_2_0,	/* D API 2.0 */
> -	0
> -};
> -
>   /*
>    * Table of global identifiers.  This is used to populate the global identifier
>    * hash when a new dtrace client open occurs.  For more info see dt_ident.h.
> diff --git a/libdtrace/dt_subr.c b/libdtrace/dt_subr.c
> index d5dca164..40b66c7d 100644
> --- a/libdtrace/dt_subr.c
> +++ b/libdtrace/dt_subr.c
> @@ -369,58 +369,6 @@ dt_attr_str(dtrace_attribute_t a, char *buf, size_t len)
>   	return buf;
>   }
>   
> -char *
> -dt_version_num2str(dt_version_t v, char *buf, size_t len)
> -{
> -	uint_t M = DT_VERSION_MAJOR(v);
> -	uint_t m = DT_VERSION_MINOR(v);
> -	uint_t u = DT_VERSION_MICRO(v);
> -
> -	if (u == 0)
> -		snprintf(buf, len, "%u.%u", M, m);
> -	else
> -		snprintf(buf, len, "%u.%u.%u", M, m, u);
> -
> -	return buf;
> -}
> -
> -int
> -dt_version_str2num(const char *s, dt_version_t *vp)
> -{
> -	int i = 0, n[3] = { 0, 0, 0 };
> -	char c;
> -
> -	while ((c = *s++) != '\0') {
> -		if (isdigit(c))
> -			n[i] = n[i] * 10 + c - '0';
> -		else if (c != '.' || i++ >= sizeof(n) / sizeof(n[0]) - 1)
> -			return -1;
> -	}
> -
> -	if (n[0] > DT_VERSION_MAJMAX ||
> -	    n[1] > DT_VERSION_MINMAX ||
> -	    n[2] > DT_VERSION_MICMAX)
> -		return -1;
> -
> -	if (vp != NULL)
> -		*vp = DT_VERSION_NUMBER(n[0], n[1], n[2]);
> -
> -	return 0;
> -}
> -
> -int
> -dt_version_defined(dt_version_t v)
> -{
> -	int i;
> -
> -	for (i = 0; _dtrace_versions[i] != 0; i++) {
> -		if (_dtrace_versions[i] == v)
> -			return 1;
> -	}
> -
> -	return 0;
> -}
> -
>   char *
>   dt_cpp_add_arg(dtrace_hdl_t *dtp, const char *str)
>   {
> @@ -949,34 +897,6 @@ dtrace_uaddr2str(dtrace_hdl_t *dtp, pid_t pid, uint64_t addr, char *str,
>   	return dt_string2str(c, str, nbytes);
>   }
>   
> -/*
> - * The function converts string representation of kernel version
> - * into the dt_version_t type.
> - */
> -int
> -dt_str2kver(const char *kverstr, dt_version_t *vp)
> -{
> -	int		kv1, kv2, kv3;
> -	int		rval;
> -
> -	rval = sscanf(kverstr, "%d.%d.%d", &kv1, &kv2, &kv3);
> -
> -	switch (rval) {
> -	case 2:
> -		kv3 = 0;
> -		break;
> -	case 3:
> -		break;
> -	default:
> -		return -1;
> -	}
> -
> -	if (vp)
> -		*vp = DT_VERSION_NUMBER(kv1, kv2, kv3);
> -
> -	return 0;
> -}
> -
>   /*
>    * Compute a 32-bit hash value for a memory block of given size.
>    */
> diff --git a/libdtrace/dt_version.c b/libdtrace/dt_version.c
> new file mode 100644
> index 00000000..e9ac88be
> --- /dev/null
> +++ b/libdtrace/dt_version.c
> @@ -0,0 +1,93 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +#include <stdio.h>
> +#include <ctype.h>
> +
> +#include <dt_impl.h>
> +
> +const dt_version_t _dtrace_versions[] = DTRACE_VERSIONS;
> +
> +char *
> +dt_version_num2str(dt_version_t v, char *buf, size_t len)
> +{
> +	uint_t	M = DT_VERSION_MAJOR(v);
> +	uint_t	m = DT_VERSION_MINOR(v);
> +	uint_t	u = DT_VERSION_MICRO(v);
> +
> +	if (u == 0)
> +		snprintf(buf, len, "%u.%u", M, m);
> +	else
> +		snprintf(buf, len, "%u.%u.%u", M, m, u);
> +
> +	return buf;
> +}
> +
> +int
> +dt_version_str2num(const char *s, dt_version_t *vp)
> +{
> +	int	i = 0, n[3] = { 0, 0, 0 };
> +	char	c;
> +
> +	while ((c = *s++) != '\0') {
> +		if (isdigit(c))
> +			n[i] = n[i] * 10 + c - '0';
> +		else if (c != '.' || i++ >= ARRAY_SIZE(n) - 1)
> +			return -1;
> +	}
> +
> +	if (n[0] > DT_VERSION_MAJMAX ||
> +	    n[1] > DT_VERSION_MINMAX ||
> +	    n[2] > DT_VERSION_MICMAX)
> +		return -1;
> +
> +	if (vp != NULL)
> +		*vp = DT_VERSION_NUMBER(n[0], n[1], n[2]);
> +
> +	return 0;
> +}
> +
> +int
> +dt_version_defined(dt_version_t v)
> +{
> +	int	i;
> +
> +	for (i = 0; i < ARRAY_SIZE(_dtrace_versions); i++) {
> +		if (_dtrace_versions[i] == v)
> +			return 1;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Convert a string representation of a kernel version string into the
> + * a dt_version_t value.
> + */
> +int
> +dt_str2kver(const char *kverstr, dt_version_t *vp)
> +{
> +	int	kv1, kv2, kv3;
> +	int	rval;
> +
> +	rval = sscanf(kverstr, "%d.%d.%d", &kv1, &kv2, &kv3);
> +
> +	switch (rval) {
> +	case 2:
> +		kv3 = 0;
> +		break;
> +	case 3:
> +		break;
> +	default:
> +		return -1;
> +	}
> +
> +	if (vp)
> +		*vp = DT_VERSION_NUMBER(kv1, kv2, kv3);
> +
> +	return 0;
> +}
> diff --git a/libdtrace/dt_version.h b/libdtrace/dt_version.h
> index 3fd1b3d1..967e22cc 100644
> --- a/libdtrace/dt_version.h
> +++ b/libdtrace/dt_version.h
> @@ -15,24 +15,6 @@ extern "C" {
>   #include <dt_ident.h>
>   #include <dt_git_version.h>
>   
> -/*
> - * Stability definitions
> - *
> - * These #defines are used in the tables of identifiers below to fill in the
> - * attribute fields associated with each identifier.  The DT_ATTR_* macros are
> - * a convenience to permit more concise declarations of common attributes such
> - * as Stable/Stable/Common.
> - *
> - * Refer to the Solaris Dynamic Tracing Guide Stability chapter respectively
> - * for an explanation of these DTrace features and their values.
> - */
> -#define DT_ATTR_STABCMN { DTRACE_STABILITY_STABLE, \
> -	DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }
> -
> -#define DT_ATTR_EVOLCMN { DTRACE_STABILITY_EVOLVING, \
> -	DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON \
> -}
> -
>   /*
>    * Versioning definitions
>    *
> @@ -46,9 +28,11 @@ extern "C" {
>    * Refer to the Solaris Dynamic Tracing Guide Versioning chapter for an
>    * explanation of these DTrace features and their values.
>    *
> - * You must update DT_VERS_LATEST and DT_VERS_STRING when adding a new version,
> - * and then add the new version to the _dtrace_versions[] array declared in
> - * dt_open.c..
> + * When adding a new version:
> + *  - Add a new DT_VERS_* macro
> + *  - Add the new DT_VERS_* macro at the end of the DTRACE_VERSIONS macro
> + *  - Set DT_VERS_LATEST to the new DT_VERS_*
> + *  - Update DT_VERS_STRING to reflect the new version
>    *
>    * NOTE: Although the DTrace versioning scheme supports the labeling and
>    *       introduction of incompatible changes (e.g. dropping an interface in a
> @@ -57,16 +41,18 @@ extern "C" {
>    *       we ever need to provide divergent interfaces, this will need work.
>    *
>    * The version number should be increased for every customer visible release
> - * of Solaris. The major number should be incremented when a fundamental
> - * change has been made that would affect all consumers, and would reflect
> - * sweeping changes to DTrace or the D language. The minor number should be
> - * incremented when a change is introduced that could break scripts that had
> - * previously worked; for example, adding a new built-in variable could break
> - * a script which was already using that identifier. The micro number should
> - * be changed when introducing functionality changes or major bug fixes that
> - * do not affect backward compatibility -- this is merely to make capabilities
> - * easily determined from the version number. Minor bugs do not require any
> - * modification to the version number.
> + * of Linux.

of Linux?  But we do not release with Linux versions.

> + *  - The major number should be incremented when a fundamental change has been
> + *    made that would affect all consumers, and would reflect sweeping changes
> + *    to DTrace or the D language.
> + *  - The minor number should be incremented when a change is introduced that
> + *    could break scripts that had previously worked; for example, adding a new
> + *    built-in variable could break a script which was already using that
> + *    identifier.
> + *  - The micro number should be changed when introducing functionality changes
> + *    or major bug fixes that do not affect backward compatibility -- this is
> + *    merely to make capabilities easily determined from the version number.
> + *    Minor bugs do not require any modification to the version number.
>    */
>   #define	DT_VERS_1_0	DT_VERSION_NUMBER(1, 0, 0)
>   #define	DT_VERS_1_1	DT_VERSION_NUMBER(1, 1, 0)
> @@ -84,9 +70,59 @@ extern "C" {
>   #define	DT_VERS_1_6_4	DT_VERSION_NUMBER(1, 6, 4)
>   #define	DT_VERS_2_0	DT_VERSION_NUMBER(2, 0, 0)
>   #define	DT_VERS_2_0_1	DT_VERSION_NUMBER(2, 0, 1)
> +#define	DT_VERS_2_0_2	DT_VERSION_NUMBER(2, 0, 2)
> +
> +#define DTRACE_VERSIONS	{ \

Why was DT_VERS_1_0 dropped from this list?

> +	DT_VERS_1_1,	/* D API 1.1.0 Solaris Express 6/05 */ \
> +	DT_VERS_1_2,	/* D API 1.2.0 Solaris 10 Update 1 */ \
> +	DT_VERS_1_2_1,	/* D API 1.2.1 Solaris Express 4/06 */ \
> +	DT_VERS_1_2_2,	/* D API 1.2.2 Solaris Express 6/06 */ \
> +	DT_VERS_1_3,	/* D API 1.3 Solaris Express 10/06 */ \
> +	DT_VERS_1_4,	/* D API 1.4 Solaris Express 2/07 */ \
> +	DT_VERS_1_4_1,	/* D API 1.4.1 Solaris Express 4/07 */ \
> +	DT_VERS_1_5,	/* D API 1.5 Solaris Express 7/07 */ \
> +	DT_VERS_1_6,	/* D API 1.6 */ \
> +	DT_VERS_1_6_1,	/* D API 1.6.1 */ \
> +	DT_VERS_1_6_2,	/* D API 1.6.2 */ \
> +	DT_VERS_1_6_3,	/* D API 1.6.3 */ \
> +	DT_VERS_1_6_4,	/* D API 1.6.4 */ \
> +	DT_VERS_2_0,	/* D API 2.0 */ \
> +	DT_VERS_2_0_1,	/* D API 2.0.1 */ \
> +	DT_VERS_2_0_2,	/* D API 2.0.2 */ \
> +}
> +
> +#define	DT_VERS_LATEST	DT_VERS_2_0_2
> +#define	DT_VERS_STRING	"Oracle D 2.0.2"
> +
> +/*
> + * Interfaces for parsing and handling DTrace version strings.  Version binding
> + * is a feature of the D compiler that is handled completely independently of
> + * the DTrace kernel infrastructure, so the definitions are here in libdtrace.
> + * Version strings are compiled into an encoded uint32_t which can be compared
> + * using C comparison operators.
> + */
> +#define	DT_VERSION_STRMAX	16	/* enough for "255.4095.4095\0" */
> +#define	DT_VERSION_MAJMAX	0xFF	/* maximum major version number */
> +#define	DT_VERSION_MINMAX	0xFFF	/* maximum minor version number */
> +#define	DT_VERSION_MICMAX	0xFFF	/* maximum micro version number */
> +
> +#define	DT_VERSION_NUMBER(M, m, u) \
> +	((((M) & 0xFF) << 24) | (((m) & 0xFFF) << 12) | ((u) & 0xFFF))
> +
> +#define	DT_VERSION_MAJOR(v)	(((v) & 0xFF000000) >> 24)
> +#define	DT_VERSION_MINOR(v)	(((v) & 0x00FFF000) >> 12)
> +#define	DT_VERSION_MICRO(v)	((v) & 0x00000FFF)
> +
> +typedef uint32_t dt_version_t;
> +
> +extern const dt_version_t _dtrace_versions[];
> +extern const char *const _dtrace_version;
> +
> +extern char *dt_version_num2str(dt_version_t, char *, size_t);
> +extern int dt_version_str2num(const char *, dt_version_t *);
> +extern int dt_version_defined(dt_version_t);
>   
> -#define	DT_VERS_LATEST	DT_VERS_2_0_1
> -#define	DT_VERS_STRING	"Oracle D 2.0"
> +extern int dt_str2kver(const char *, dt_version_t *);
>   
>   #ifdef  __cplusplus
>   }



More information about the DTrace-devel mailing list