From 5455e77c6b322c1f2826f6a37e709bf8bb79e12f Mon Sep 17 00:00:00 2001 From: purplerain Date: Tue, 12 Sep 2023 03:18:43 +0000 Subject: [PATCH] sync code with last improvements from OpenBSD --- regress/usr.sbin/btrace/Makefile | 4 +- regress/usr.sbin/btrace/tuple.bt | 4 + regress/usr.sbin/btrace/tuple.ok | 1 + regress/usr.sbin/btrace/tupleeval.bt | 8 ++ regress/usr.sbin/btrace/tupleeval.ok | 1 + regress/usr.sbin/btrace/vareval.bt | 5 + regress/usr.sbin/btrace/vareval.ok | 1 + share/man/man5/ruby-module.5 | 100 +++++++-------- usr.sbin/btrace/bt_parse.y | 23 +++- usr.sbin/btrace/bt_parser.h | 7 +- usr.sbin/btrace/btrace.c | 174 +++++++++++++++++++++++---- usr.sbin/btrace/btrace.h | 9 +- usr.sbin/btrace/map.c | 123 ++++++------------- 13 files changed, 283 insertions(+), 177 deletions(-) create mode 100644 regress/usr.sbin/btrace/tuple.bt create mode 100644 regress/usr.sbin/btrace/tuple.ok create mode 100644 regress/usr.sbin/btrace/tupleeval.bt create mode 100644 regress/usr.sbin/btrace/tupleeval.ok create mode 100644 regress/usr.sbin/btrace/vareval.bt create mode 100644 regress/usr.sbin/btrace/vareval.ok diff --git a/regress/usr.sbin/btrace/Makefile b/regress/usr.sbin/btrace/Makefile index a5b37cbab..6f0bb76d3 100644 --- a/regress/usr.sbin/btrace/Makefile +++ b/regress/usr.sbin/btrace/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.29 2023/09/02 19:28:46 dv Exp $ +# $OpenBSD: Makefile,v 1.30 2023/09/11 19:03:53 mpi Exp $ BTRACE?= /usr/sbin/btrace ALLOWDT!= sysctl -n kern.allowdt 2>/dev/null @@ -9,7 +9,7 @@ BT_LANG_SCRIPTS= arithm beginend beginend-argn boolean comments delete \ map mapclear mapempty mapsyntax mapzero map-unnamed \ maxoperand min+max+sum multismts nsecs+var \ precedence print read-map-after-clear staticv-empty \ - syntaxerror + syntaxerror tuple tupleeval vareval BT_ARG_LANG_SCRIPTS= staticv str diff --git a/regress/usr.sbin/btrace/tuple.bt b/regress/usr.sbin/btrace/tuple.bt new file mode 100644 index 000000000..80124c487 --- /dev/null +++ b/regress/usr.sbin/btrace/tuple.bt @@ -0,0 +1,4 @@ +BEGIN { + $t = (1, 42, "something"); + printf("%d %s\n", $t.1, $t.2); +} diff --git a/regress/usr.sbin/btrace/tuple.ok b/regress/usr.sbin/btrace/tuple.ok new file mode 100644 index 000000000..a75bd975a --- /dev/null +++ b/regress/usr.sbin/btrace/tuple.ok @@ -0,0 +1 @@ +42 something diff --git a/regress/usr.sbin/btrace/tupleeval.bt b/regress/usr.sbin/btrace/tupleeval.bt new file mode 100644 index 000000000..aeee95c6d --- /dev/null +++ b/regress/usr.sbin/btrace/tupleeval.bt @@ -0,0 +1,8 @@ +BEGIN { + $t = (5, comm, "str", probe); + @u = $t; +} + +END { + print(@u) +} diff --git a/regress/usr.sbin/btrace/tupleeval.ok b/regress/usr.sbin/btrace/tupleeval.ok new file mode 100644 index 000000000..ea54e1e11 --- /dev/null +++ b/regress/usr.sbin/btrace/tupleeval.ok @@ -0,0 +1 @@ +(5, btrace, str, BEGIN) diff --git a/regress/usr.sbin/btrace/vareval.bt b/regress/usr.sbin/btrace/vareval.bt new file mode 100644 index 000000000..3ea83a52d --- /dev/null +++ b/regress/usr.sbin/btrace/vareval.bt @@ -0,0 +1,5 @@ +BEGIN { + $tmp = 5; + @t = $tmp; + @m[42] = @t; +} diff --git a/regress/usr.sbin/btrace/vareval.ok b/regress/usr.sbin/btrace/vareval.ok new file mode 100644 index 000000000..366a59e13 --- /dev/null +++ b/regress/usr.sbin/btrace/vareval.ok @@ -0,0 +1 @@ +@m[42]: 5 diff --git a/share/man/man5/ruby-module.5 b/share/man/man5/ruby-module.5 index 2a0fcf13f..58b3bbbd1 100644 --- a/share/man/man5/ruby-module.5 +++ b/share/man/man5/ruby-module.5 @@ -1,4 +1,5 @@ -.\" $OpenBSD: ruby-module.5,v 1.40 2023/05/31 15:27:45 jeremy Exp $ +m +.\" $OpenBSD: ruby-module.5,v 1.41 2023/09/11 20:02:38 jeremy Exp $ .\" .\" Copyright (c) 2008 Marc Espie, Jeremy Evans .\" @@ -24,7 +25,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: May 31 2023 $ +.Dd $Mdocdate: September 11 2023 $ .Dt RUBY-MODULE 5 .Os .Sh NAME @@ -38,48 +39,40 @@ in the tree. .Pp Sets -.Ev MODRUBY_REV , -.Ev RUBY , -.Ev RAKE , -.Ev RSPEC , -.Ev MODRUBY_BIN_TESTRB , -.Ev MODRUBY_BIN_RSPEC , -.Ev MODRUBY_WANTLIB , -.Ev MODRUBY_RUN_DEPENDS , -.Ev MODRUBY_LIB_DEPENDS , -.Ev MODRUBY_BUILD_DEPENDS , -.Ev MODRUBY_RSPEC_DEPENDS , -.Ev MODRUBY_RSPEC3_DEPENDS , -.Ev MODRUBY_RUBY_ADJ , +.Ev GEM , +.Ev GEM_BASE_BIN , +.Ev GEM_BASE_LIB , +.Ev GEM_BIN , +.Ev GEM_BIN_SUFFIX , +.Ev GEM_EXTENSIONS_DIR, +.Ev GEM_FLAGS , +.Ev GEM_LIB , +.Ev GEM_MAN_SUFFIX , .Ev MODRUBY_ADJ_FILES , -.Ev MODRUBY_LIBDIR , -.Ev MODRUBY_DOCDIR , +.Ev MODRUBY_ARCH , +.Ev MODRUBY_BINREV , +.Ev MODRUBY_BIN_RSPEC , +.Ev MODRUBY_BUILD_DEPENDS , +.Ev MODRUBY_BUILDDEP , +.Ev MODRUBY_FLAVOR , +.Ev MODRUBY_HANDLE_FLAVORS , +.Ev MODRUBY_LIBREV , +.Ev MODRUBY_LIB_DEPENDS , +.Ev MODRUBY_PKG_PREFIX , +.Ev MODRUBY_RELEXAMPLEDIR , +.Ev MODRUBY_REV , +.Ev MODRUBY_RUBY_ADJ , +.Ev MODRUBY_RUN_DEPENDS , +.Ev MODRUBY_RUNDEP , .Ev MODRUBY_SITEARCHDIR , .Ev MODRUBY_SITEDIR , -.Ev MODRUBY_EXAMPLEDIR , -.Ev MODRUBY_ARCH , -.Ev MODRUBY_LIBREV , -.Ev MODRUBY_BINREV , -.Ev MODRUBY_HANDLE_FLAVORS , -.Ev MODRUBY_PKG_PREFIX , -.Ev MODRUBY_FLAVOR , .Ev MODRUBY_TEST , -.Ev MODRUBY_TEST_TARGET , -.Ev MODRUBY_TEST_DIR , .Ev MODRUBY_TEST_ENV , -.Ev MODRUBY_BUILD_TARGET , -.Ev MODRUBY_INSTALL_TARGET , -.Ev MODRUBY_EXTRACT_TARGET , -.Ev GEM , -.Ev GEM_BIN , -.Ev GEM_LIB , -.Ev GEM_BASE_LIB , -.Ev GEM_ABS_PATH , -.Ev GEM_BASE_BIN , -.Ev GEM_BIN_SUFFIX , -.Ev GEM_MAN_SUFFIX , +.Ev MODRUBY_TEST_TARGET , +.Ev MODRUBY_WANTLIB , +.Ev RAKE , and -.Ev GEM_FLAGS . +.Ev RUBY . .Pp Appends to .Ev CATEGORIES @@ -98,23 +91,17 @@ unless .Ev MODRUBY_RUNDEP is set to No. .Pp -.Ev MODRUBY_RSPEC_DEPENDS -is set to the dependency line for the rspec 1 port for the version of ruby in -use. .Ev MODRUBY_RSPEC3_DEPENDS is set to the dependency line for the rspec 3 port for the version of ruby in use. .Ev RUBY , -.Ev RAKE , -and -.Ev MODRUBY_BIN_TESTRB -are the path to the ruby, rake, and -testrb binaries for the related ruby implementation. -.Ev RSPEC and +.Ev RAKE +are the path to the ruby and rake +binaries for the related ruby implementation. .Ev MODRUBY_BIN_RSPEC -are the path to the spec (rspec 1) and -rspec (rspec 3) binaries for the related ruby implementation. +is the path to the rspec (rspec 3) binaries for the related ruby +implementation. .Pp .Ev MODRUBY_RUBY_ADJ is a command that takes filename arguments and replaces @@ -129,14 +116,10 @@ Creates a do-test target if .Ev MODRUBY_TEST is used and one is not already defined. .Ev MODRUBY_TEST -can be set to ruby, rake, rspec, rspec3, or testrb to +can be set to ruby, rake, rspec3, or testrb to choose the appropriate binary to run the regress tests. .Ev MODRUBY_TEST_ENV can be used to set environment variables for the regress tests. -.Ev MODRUBY_TEST_DIR -can be used to set the directory in which to execute -the regress tests, it defaults to -.Ev WRKSRC . .Ev MODRUBY_TEST_TARGET sets the argument to the regress test program. .Pp @@ -152,7 +135,7 @@ The "ruby gem" should be used for pure ruby gems without C extensions. This adds .Ev PKG_ARCH -= * and adds ruby30, ruby31, ruby32, and jruby += * and adds ruby30, ruby31, and ruby32 .Ev FLAVOR Ns s to the port, so the same port can build packages for multiple versions of ruby. .It @@ -192,8 +175,7 @@ instead of ruby as the package prefix. Specifying .Ev MODRUBY_FLAVOR is necessary so that if a ruby x.y package is being built for the current -port, it depends on the ruby x.y package of the -dependencies. +port, it depends on the ruby x.y package of the dependencies. .Pp The ports system defaults to using ruby 3.2 if the version of ruby is not specified. @@ -202,7 +184,7 @@ If you want to specify a version for a gem port, use a specific such as ruby31 to use ruby 3.1. If you want to specify a version for a non-gem port, set .Ev MODRUBY_REV -for the version of ruby you want to use (3.0, 3.1, 3.2, jruby). +for the version of ruby you want to use (3.0, 3.1, 3.2). .Pp If you do not want the ports system to automatically set up .Ev FLAVOR Ns s @@ -218,7 +200,7 @@ When .Ev MODRUBY_HANDLE_FLAVORS is Yes, the ports system automatically adds the appropriate prefix to the .Ev FULLPKGNAME -(e.g. jruby- for jruby, ruby32- for ruby 3.2). +(e.g. ruby31- for ruby 3.1, ruby32- for ruby 3.2). Additionally, it adds .Ev GEM_BIN_SUFFIX and diff --git a/usr.sbin/btrace/bt_parse.y b/usr.sbin/btrace/bt_parse.y index b2c3e6585..0a8d9c62f 100644 --- a/usr.sbin/btrace/bt_parse.y +++ b/usr.sbin/btrace/bt_parse.y @@ -1,7 +1,7 @@ -/* $OpenBSD: bt_parse.y,v 1.52 2023/09/02 19:28:46 dv Exp $ */ +/* $OpenBSD: bt_parse.y,v 1.53 2023/09/11 19:01:26 mpi Exp $ */ /* - * Copyright (c) 2019-2021 Martin Pieuchot + * Copyright (c) 2019-2023 Martin Pieuchot * Copyright (c) 2019 Tobias Heider * Copyright (c) 2015 Ted Unangst * @@ -72,6 +72,8 @@ struct bt_stmt *bg_store(const char *, struct bt_arg *); struct bt_arg *bg_find(const char *); struct bt_var *bg_get(const char *); +struct bt_arg *bi_find(struct bt_arg *, unsigned long); + struct bt_var *bl_lookup(const char *); struct bt_stmt *bl_store(const char *, struct bt_arg *); struct bt_arg *bl_find(const char *); @@ -210,9 +212,11 @@ fterm : fterm '*' factor { $$ = ba_op(B_AT_OP_MULT, $1, $3); } variable: lvar { $$ = bl_find($1); } | gvar { $$ = bg_find($1); } + | variable '.' NUMBER { $$ = bi_find($1, $3); } ; factor : '(' expr ')' { $$ = $2; } + | '(' vargs ',' expr ')'{ $$ = ba_new(ba_append($2, $4), B_AT_TUPLE); } | NUMBER { $$ = ba_new($1, B_AT_LONG); } | BUILTIN { $$ = ba_new(NULL, $1); } | CSTRING { $$ = ba_new($1, B_AT_STR); } @@ -419,7 +423,7 @@ ba_new0(void *val, enum bt_argtype type) /* * Link two arguments together, to build an argument list used in - * function calls. + * operators, tuples and function calls. */ struct bt_arg * ba_append(struct bt_arg *da0, struct bt_arg *da1) @@ -592,6 +596,17 @@ bl_store(const char *vname, struct bt_arg *vval) return bs_new(B_AC_STORE, vval, bv); } +/* Create an argument that points to a tuple variable and a given index */ +struct bt_arg * +bi_find(struct bt_arg *ba, unsigned long index) +{ + struct bt_var *bv = ba->ba_value; + + ba = ba_new(bv, B_AT_TMEMBER); + ba->ba_key = (void *)index; + return ba; +} + struct bt_stmt * bm_op(enum bt_action mact, struct bt_arg *ba, struct bt_arg *mval) { @@ -610,7 +625,7 @@ bm_insert(const char *mname, struct bt_arg *mkey, struct bt_arg *mval) return bs_new(B_AC_INSERT, ba, (struct bt_var *)mval); } -/* Create an argument that points to a variable and attach a key to it. */ +/* Create an argument that points to a map variable and attach a key to it. */ struct bt_arg * bm_find(const char *vname, struct bt_arg *mkey) { diff --git a/usr.sbin/btrace/bt_parser.h b/usr.sbin/btrace/bt_parser.h index 6fe2eb432..9cbcace6f 100644 --- a/usr.sbin/btrace/bt_parser.h +++ b/usr.sbin/btrace/bt_parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bt_parser.h,v 1.23 2022/12/28 21:30:16 jmc Exp $ */ +/* $OpenBSD: bt_parser.h,v 1.24 2023/09/11 19:01:26 mpi Exp $ */ /* * Copyright (c) 2019-2021 Martin Pieuchot @@ -94,7 +94,7 @@ struct bt_rule { }; /* - * Global variable representation. + * Global and local variable representation. * * Variables are untyped and also include maps and histograms. */ @@ -105,6 +105,7 @@ struct bt_var { enum bt_vartype { B_VT_STR = 1, B_VT_LONG, + B_VT_TUPLE, B_VT_MAP, B_VT_HIST, } bv_type; @@ -126,6 +127,8 @@ struct bt_arg { B_AT_VAR, /* global/local variable */ B_AT_MAP, /* global map (@map[]) */ B_AT_HIST, /* histogram */ + B_AT_TUPLE, /* tuple (1, 42, "str") */ + B_AT_TMEMBER, /* tuple member $t.2 */ B_AT_NIL, /* empty value */ B_AT_BI_PID, diff --git a/usr.sbin/btrace/btrace.c b/usr.sbin/btrace/btrace.c index f57091107..6ab03222e 100644 --- a/usr.sbin/btrace/btrace.c +++ b/usr.sbin/btrace/btrace.c @@ -1,7 +1,7 @@ -/* $OpenBSD: btrace.c,v 1.75 2023/09/02 15:16:12 dv Exp $ */ +/* $OpenBSD: btrace.c,v 1.76 2023/09/11 19:01:26 mpi Exp $ */ /* - * Copyright (c) 2019 - 2021 Martin Pieuchot + * Copyright (c) 2019 - 2023 Martin Pieuchot * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -95,6 +95,7 @@ bool stmt_test(struct bt_stmt *, struct dt_evt *); void stmt_time(struct bt_stmt *, struct dt_evt *); void stmt_zero(struct bt_stmt *); struct bt_arg *ba_read(struct bt_arg *); +struct bt_arg *baeval(struct bt_arg *, struct dt_evt *); const char *ba2hash(struct bt_arg *, struct dt_evt *); long baexpr2long(struct bt_arg *, struct dt_evt *); const char *ba2bucket(struct bt_arg *, struct bt_arg *, @@ -854,6 +855,7 @@ stmt_bucketize(struct bt_stmt *bs, struct dt_evt *dtev) struct bt_arg *brange, *bhist = SLIST_FIRST(&bs->bs_args); struct bt_arg *bval = (struct bt_arg *)bs->bs_var; struct bt_var *bv = bhist->ba_value; + struct hist *hist; const char *bucket; long step = 0; @@ -870,8 +872,17 @@ stmt_bucketize(struct bt_stmt *bs, struct dt_evt *dtev) debug("hist=%p '%s' increment bucket '%s'\n", bv->bv_value, bv_name(bv), bucket); - bv->bv_value = (struct bt_arg *) - hist_increment((struct hist *)bv->bv_value, bucket, step); + /* hist is NULL before first insert or after clear() */ + hist = (struct hist *)bv->bv_value; + if (hist == NULL) + hist = hist_new(step); + + hist_increment(hist, bucket); + + debug("hist=%p '%s' increment bucket=%p '%s' bval=%p\n", hist, + bv_name(bv), brange, bucket, bval); + + bv->bv_value = (struct bt_arg *)hist; bv->bv_type = B_VT_HIST; } @@ -943,6 +954,7 @@ stmt_insert(struct bt_stmt *bs, struct dt_evt *dtev) struct bt_var *bv = bmap->ba_value; struct map *map; const char *hash; + long val; assert(bmap->ba_type == B_AT_MAP); assert(SLIST_NEXT(bval, ba_next) == NULL); @@ -952,7 +964,36 @@ stmt_insert(struct bt_stmt *bs, struct dt_evt *dtev) /* map is NULL before first insert or after clear() */ map = (struct map *)bv->bv_value; - map = map_insert(map, hash, bval, dtev); + if (map == NULL) + map = map_new(); + + /* Operate on existring value for count(), max(), min() and sum(). */ + switch (bval->ba_type) { + case B_AT_MF_COUNT: + val = ba2long(map_get(map, hash), NULL); + val++; + bval = ba_new(val, B_AT_LONG); + break; + case B_AT_MF_MAX: + val = ba2long(map_get(map, hash), NULL); + val = MAXIMUM(val, ba2long(bval->ba_value, dtev)); + bval = ba_new(val, B_AT_LONG); + break; + case B_AT_MF_MIN: + val = ba2long(map_get(map, hash), NULL); + val = MINIMUM(val, ba2long(bval->ba_value, dtev)); + bval = ba_new(val, B_AT_LONG); + break; + case B_AT_MF_SUM: + val = ba2long(map_get(map, hash), NULL); + val += ba2long(bval->ba_value, dtev); + bval = ba_new(val, B_AT_LONG); + break; + default: + break; + } + + map_insert(map, hash, bval); debug("map=%p '%s' insert key=%p '%s' bval=%p\n", map, bv_name(bv), bkey, hash, bval); @@ -1018,7 +1059,7 @@ void stmt_store(struct bt_stmt *bs, struct dt_evt *dtev) { struct bt_arg *ba = SLIST_FIRST(&bs->bs_args); - struct bt_var *bv = bs->bs_var; + struct bt_var *bvar, *bv = bs->bs_var; assert(SLIST_NEXT(ba, ba_next) == NULL); @@ -1031,33 +1072,33 @@ stmt_store(struct bt_stmt *bs, struct dt_evt *dtev) bv->bv_value = ba; bv->bv_type = B_VT_LONG; break; + case B_AT_VAR: + bvar = ba->ba_value; + bv->bv_type = bvar->bv_type; + bv->bv_value = bvar->bv_value; + break; + case B_AT_TUPLE: + bv->bv_value = baeval(ba, dtev); + bv->bv_type = B_VT_TUPLE; + break; case B_AT_BI_PID: - bv->bv_value = ba_new((long)dtev->dtev_pid, B_AT_LONG); - bv->bv_type = B_VT_LONG; - break; case B_AT_BI_TID: - bv->bv_value = ba_new((long)dtev->dtev_tid, B_AT_LONG); - bv->bv_type = B_VT_LONG; - break; case B_AT_BI_NSECS: - bv->bv_value = ba_new(builtin_nsecs(dtev), B_AT_LONG); - bv->bv_type = B_VT_LONG; - break; case B_AT_BI_ARG0 ... B_AT_BI_ARG9: - /* FALLTHROUGH */ case B_AT_OP_PLUS ... B_AT_OP_LOR: - bv->bv_value = ba_new(ba2long(ba, dtev), B_AT_LONG); + bv->bv_value = baeval(ba, dtev); bv->bv_type = B_VT_LONG; break; case B_AT_FN_STR: - bv->bv_value = ba_new(ba2str(ba, dtev), B_AT_STR); + bv->bv_value = baeval(ba, dtev); bv->bv_type = B_VT_STR; break; default: xabort("store not implemented for type %d", ba->ba_type); } - debug("bv=%p var '%s' store (%p)\n", bv, bv_name(bv), bv->bv_value); + debug("bv=%p var '%s' store (%p)='%s'\n", bv, bv_name(bv), bv->bv_value, + ba2str(bv->bv_value, dtev)); } /* @@ -1160,7 +1201,6 @@ ba_read(struct bt_arg *ba) struct bt_var *bv = ba->ba_value; assert(ba->ba_type == B_AT_VAR); - debug("bv=%p read '%s' (%p)\n", bv, bv_name(bv), bv->bv_value); /* Handle map/hist access after clear(). */ @@ -1170,6 +1210,57 @@ ba_read(struct bt_arg *ba) return bv->bv_value; } +// XXX +extern struct bt_arg *ba_append(struct bt_arg *, struct bt_arg *); + +/* + * Return a new argument that doesn't depend on `dtev'. This is used + * when storing values in variables, maps, etc. + */ +struct bt_arg * +baeval(struct bt_arg *bval, struct dt_evt *dtev) +{ + struct bt_arg *ba, *bh = NULL; + + switch (bval->ba_type) { + case B_AT_VAR: + ba = baeval(ba_read(bval), NULL); + break; + case B_AT_LONG: + case B_AT_BI_PID: + case B_AT_BI_TID: + case B_AT_BI_CPU: + case B_AT_BI_NSECS: + case B_AT_BI_ARG0 ... B_AT_BI_ARG9: + case B_AT_BI_RETVAL: + case B_AT_OP_PLUS ... B_AT_OP_LOR: + ba = ba_new(ba2long(bval, dtev), B_AT_LONG); + break; + case B_AT_STR: + case B_AT_BI_COMM: + case B_AT_BI_KSTACK: + case B_AT_BI_USTACK: + case B_AT_BI_PROBE: + case B_AT_FN_STR: + ba = ba_new(ba2str(bval, dtev), B_AT_STR); + break; + case B_AT_TUPLE: + ba = bval->ba_value; + do { + bh = ba_append(bh, baeval(ba, dtev)); + } while ((ba = SLIST_NEXT(ba, ba_next)) != NULL); + ba = ba_new(bh, B_AT_TUPLE); + break; + default: + xabort("no eval support for type %d", bval->ba_type); + } + + return ba; +} + +/* + * Return a string of coma-separated values + */ const char * ba2hash(struct bt_arg *ba, struct dt_evt *dtev) { @@ -1556,6 +1647,7 @@ ba2str(struct bt_arg *ba, struct dt_evt *dtev) static char buf[STRLEN]; struct bt_var *bv; struct dtioc_probe_info *dtpi; + unsigned long idx; const char *str; buf[0] = '\0'; @@ -1567,6 +1659,26 @@ ba2str(struct bt_arg *ba, struct dt_evt *dtev) snprintf(buf, sizeof(buf), "%ld",(long)ba->ba_value); str = buf; break; + case B_AT_TUPLE: + snprintf(buf, sizeof(buf), "(%s)", ba2hash(ba->ba_value, dtev)); + str = buf; + break; + case B_AT_TMEMBER: + idx = (unsigned long)ba->ba_key; + bv = ba->ba_value; + /* Uninitialized tuple */ + if (bv->bv_value == NULL) { + str = buf; + break; + } + ba = bv->bv_value; + assert(ba->ba_type == B_AT_TUPLE); + ba = ba->ba_value; + while (ba != NULL && idx-- > 0) { + ba = SLIST_NEXT(ba, ba_next); + } + str = ba2str(ba, dtev); + break; case B_AT_NIL: str = ""; break; @@ -1674,6 +1786,8 @@ ba2dtflags(struct bt_arg *ba) switch (bval->ba_type) { case B_AT_STR: case B_AT_LONG: + case B_AT_TUPLE: + case B_AT_TMEMBER: case B_AT_VAR: case B_AT_HIST: case B_AT_NIL: @@ -1720,6 +1834,8 @@ ba2dtflags(struct bt_arg *ba) long bacmp(struct bt_arg *a, struct bt_arg *b) { + long val; + if (a->ba_type != b->ba_type) return a->ba_type - b->ba_type; @@ -1728,8 +1844,24 @@ bacmp(struct bt_arg *a, struct bt_arg *b) return ba2long(a, NULL) - ba2long(b, NULL); case B_AT_STR: return strcmp(ba2str(a, NULL), ba2str(b, NULL)); + case B_AT_TUPLE: + /* Compare two lists of arguments one by one. */ + do { + val = bacmp(a, b); + if (val != 0) + break; + + a = SLIST_NEXT(a, ba_next); + b = SLIST_NEXT(b, ba_next); + if (a == NULL && b != NULL) + val = -1; + else if (a != NULL && b == NULL) + val = 1; + } while (a != NULL && b != NULL); + + return val; default: - errx(1, "no compare support for type %d", a->ba_type); + xabort("no compare support for type %d", a->ba_type); } } diff --git a/usr.sbin/btrace/btrace.h b/usr.sbin/btrace/btrace.h index 78d4618d4..b5fb90f8c 100644 --- a/usr.sbin/btrace/btrace.h +++ b/usr.sbin/btrace/btrace.h @@ -1,4 +1,4 @@ -/* $OpenBSD: btrace.h,v 1.12 2023/05/12 14:14:16 claudio Exp $ */ +/* $OpenBSD: btrace.h,v 1.13 2023/09/11 19:01:26 mpi Exp $ */ /* * Copyright (c) 2019 - 2020 Martin Pieuchot @@ -46,14 +46,15 @@ int kelf_snprintsym(struct syms *, char *, size_t, /* map.c */ struct map; struct hist; +struct map *map_new(void); void map_clear(struct map *); void map_delete(struct map *, const char *); struct bt_arg *map_get(struct map *, const char *); -struct map *map_insert(struct map *, const char *, struct bt_arg *, - struct dt_evt *); +void map_insert(struct map *, const char *, void *); void map_print(struct map *, size_t, const char *); void map_zero(struct map *); -struct hist *hist_increment(struct hist *, const char *, long); +struct hist *hist_new(long); +void hist_increment(struct hist *, const char *); void hist_print(struct hist *, const char *); #define KLEN 1024 /* # of characters in map key, contain a stack trace */ diff --git a/usr.sbin/btrace/map.c b/usr.sbin/btrace/map.c index 0de15630c..1b116577b 100644 --- a/usr.sbin/btrace/map.c +++ b/usr.sbin/btrace/map.c @@ -1,4 +1,4 @@ -/* $OpenBSD: map.c,v 1.23 2023/09/03 10:26:35 mpi Exp $ */ +/* $OpenBSD: map.c,v 1.24 2023/09/11 19:01:26 mpi Exp $ */ /* * Copyright (c) 2020 Martin Pieuchot @@ -33,14 +33,6 @@ #include "bt_parser.h" #include "btrace.h" -#ifndef MIN -#define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b)) -#endif - -#ifndef MAX -#define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b)) -#endif - RB_HEAD(map, mentry); struct mentry { @@ -79,6 +71,18 @@ mget(struct map *map, const char *key) return mep; } +struct map * +map_new(void) +{ + struct map *map; + + map = calloc(1, sizeof(struct map)); + if (map == NULL) + err(1, "map: calloc"); + + return map; +} + void map_clear(struct map *map) { @@ -118,75 +122,14 @@ map_get(struct map *map, const char *key) return mep->mval; } -struct map * -map_insert(struct map *map, const char *key, struct bt_arg *bval, - struct dt_evt *dtev) +void +map_insert(struct map *map, const char *key, void *cookie) { struct mentry *mep; - long val; - - if (map == NULL) { - map = calloc(1, sizeof(struct map)); - if (map == NULL) - err(1, "map: calloc"); - } mep = mget(map, key); - switch (bval->ba_type) { - case B_AT_STR: - free(mep->mval); - mep->mval = ba_new(ba2str(bval, dtev), B_AT_LONG); - break; - case B_AT_LONG: - case B_AT_BI_PID: - case B_AT_BI_TID: - case B_AT_BI_CPU: - case B_AT_BI_NSECS: - case B_AT_BI_ARG0 ... B_AT_BI_ARG9: - case B_AT_BI_RETVAL: - case B_AT_BI_PROBE: - free(mep->mval); - mep->mval = ba_new(ba2long(bval, dtev), B_AT_LONG); - break; - case B_AT_MF_COUNT: - if (mep->mval == NULL) - mep->mval = ba_new(0, B_AT_LONG); - val = (long)mep->mval->ba_value; - val++; - mep->mval->ba_value = (void *)val; - break; - case B_AT_MF_MAX: - if (mep->mval == NULL) - mep->mval = ba_new(0, B_AT_LONG); - val = (long)mep->mval->ba_value; - val = MAX(val, ba2long(bval->ba_value, dtev)); - mep->mval->ba_value = (void *)val; - break; - case B_AT_MF_MIN: - if (mep->mval == NULL) - mep->mval = ba_new(0, B_AT_LONG); - val = (long)mep->mval->ba_value; - val = MIN(val, ba2long(bval->ba_value, dtev)); - mep->mval->ba_value = (void *)val; - break; - case B_AT_MF_SUM: - if (mep->mval == NULL) - mep->mval = ba_new(0, B_AT_LONG); - val = (long)mep->mval->ba_value; - val += ba2long(bval->ba_value, dtev); - mep->mval->ba_value = (void *)val; - break; - case B_AT_BI_COMM: - case B_AT_BI_KSTACK: - case B_AT_BI_USTACK: - free(mep->mval); - mep->mval = ba_new(ba2str(bval, dtev), B_AT_STR); - break; - default: - errx(1, "no insert support for type %d", bval->ba_type); - } - - return map; + free(mep->mval); + mep->mval = cookie; } static int @@ -248,26 +191,36 @@ map_zero(struct map *map) /* * Histogram implemented with map. */ - struct hist { struct map hmap; int hstep; }; struct hist * -hist_increment(struct hist *hist, const char *key, long step) +hist_new(long step) { - static struct bt_arg incba = BA_INITIALIZER(NULL, B_AT_MF_COUNT); + struct hist *hist; - if (hist == NULL) { - hist = calloc(1, sizeof(struct hist)); - if (hist == NULL) - err(1, "hist: calloc"); - hist->hstep = step; - } - assert(hist->hstep == step); + hist = calloc(1, sizeof(struct hist)); + if (hist == NULL) + err(1, "hist: calloc"); + hist->hstep = step; - return (struct hist *)map_insert(&hist->hmap, key, &incba, NULL); + return hist; +} + +void +hist_increment(struct hist *hist, const char *bucket) +{ + struct bt_arg *ba; + long val; + + ba = map_get(&hist->hmap, bucket); + + assert(ba->ba_type == B_AT_LONG); + val = (long)ba->ba_value; + val++; + ba->ba_value = (void *)val; } long