sync code with last improvements from OpenBSD

This commit is contained in:
purplerain 2023-09-12 03:18:43 +00:00
parent 2a511f7966
commit 5455e77c6b
Signed by: purplerain
GPG Key ID: F42C07F07E2E35B7
13 changed files with 283 additions and 177 deletions

View File

@ -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

View File

@ -0,0 +1,4 @@
BEGIN {
$t = (1, 42, "something");
printf("%d %s\n", $t.1, $t.2);
}

View File

@ -0,0 +1 @@
42 something

View File

@ -0,0 +1,8 @@
BEGIN {
$t = (5, comm, "str", probe);
@u = $t;
}
END {
print(@u)
}

View File

@ -0,0 +1 @@
(5, btrace, str, BEGIN)

View File

@ -0,0 +1,5 @@
BEGIN {
$tmp = 5;
@t = $tmp;
@m[42] = @t;
}

View File

@ -0,0 +1 @@
@m[42]: 5

View File

@ -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

View File

@ -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 <mpi@openbsd.org>
* Copyright (c) 2019-2023 Martin Pieuchot <mpi@openbsd.org>
* Copyright (c) 2019 Tobias Heider <tobhe@openbsd.org>
* Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
*
@ -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)
{

View File

@ -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 <mpi@openbsd.org>
@ -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,

View File

@ -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 <mpi@openbsd.org>
* Copyright (c) 2019 - 2023 Martin Pieuchot <mpi@openbsd.org>
*
* 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);
}
}

View File

@ -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 <mpi@openbsd.org>
@ -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 */

View File

@ -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 <mpi@openbsd.org>
@ -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