From 7378f04882677d2e51ffc7f7ed96cc72c949717b Mon Sep 17 00:00:00 2001 From: Martin Pieuchot Date: Tue, 28 Jan 2020 12:13:50 +0000 Subject: Implement delete() and @map[key] access. --- usr.sbin/btrace/TODO | 1 - usr.sbin/btrace/bt_parse.y | 70 +++++++++++++++++++++++++++++---------------- usr.sbin/btrace/bt_parser.h | 4 ++- usr.sbin/btrace/btrace.c | 32 +++++++++++++-------- usr.sbin/btrace/btrace.h | 3 +- usr.sbin/btrace/map.c | 63 ++++++++++++++++++++++++++++------------ 6 files changed, 116 insertions(+), 57 deletions(-) diff --git a/usr.sbin/btrace/TODO b/usr.sbin/btrace/TODO index 4cd60171f47..f709815ddcc 100644 --- a/usr.sbin/btrace/TODO +++ b/usr.sbin/btrace/TODO @@ -10,7 +10,6 @@ Missing features: - @ = lhist(x, min, max, step) - @ = min(x) - @ = max(x) -- delete(@map[key]) Improvements: diff --git a/usr.sbin/btrace/bt_parse.y b/usr.sbin/btrace/bt_parse.y index 494b771403a..f69f256d6eb 100644 --- a/usr.sbin/btrace/bt_parse.y +++ b/usr.sbin/btrace/bt_parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: bt_parse.y,v 1.4 2020/01/28 12:09:19 mpi Exp $ */ +/* $OpenBSD: bt_parse.y,v 1.5 2020/01/28 12:13:49 mpi Exp $ */ /* * Copyright (c) 2019 - 2020 Martin Pieuchot @@ -62,9 +62,9 @@ struct bt_var *bv_find(const char *); struct bt_arg *bv_get(const char *); struct bt_stmt *bv_set(const char *, struct bt_arg *); -struct bt_smt *bn_set(const char *, struct bt_arg *, struct bt_arg *); -struct bt_stmt *bm_fn(enum bt_action, const char *, struct bt_arg *, - struct bt_arg *); +struct bt_arg *bm_get(const char *, struct bt_arg *); +struct bt_stmt *bm_set(const char *, struct bt_arg *, struct bt_arg *); +struct bt_stmt *bm_fn(enum bt_action, struct bt_arg *, struct bt_arg *); /* * Lexer @@ -101,16 +101,16 @@ static int yylex(void); %token COMM HZ KSTACK USTACK NSECS PID RETVAL TID /* Functions */ %token F_CLEAR F_DELETE F_EXIT F_PRINT F_PRINTF F_TIME F_ZERO -/* Map funcitons */ +/* Map functions */ %token M_COUNT %token STRING CSTRING %token NUMBER %type gvar -%type filterval oper builtin func0 func1 funcn mfunc1 mapfunc +%type filterval oper builtin fn0 fn1 fnN mfn0 mfn1 %type probe %type predicate %type action stmt stmtlist -%type arg arglist marg term +%type arg arglist map marg term %type beginend %% @@ -166,19 +166,22 @@ builtin : PID { $$ = B_AT_BI_PID; } | RETVAL { $$ = B_AT_BI_RETVAL; } ; -func0 : F_EXIT { $$ = B_AC_EXIT; } +fn0 : F_EXIT { $$ = B_AC_EXIT; } ; -func1 : F_CLEAR { $$ = B_AC_CLEAR; } +fn1 : F_CLEAR { $$ = B_AC_CLEAR; } | F_TIME { $$ = B_AC_TIME; } | F_ZERO { $$ = B_AC_ZERO; } ; -funcn : F_PRINTF { $$ = B_AC_PRINTF; } +fnN : F_PRINTF { $$ = B_AC_PRINTF; } | F_PRINT { $$ = B_AC_PRINT; } ; -mapfunc : M_COUNT '(' ')' { $$ = B_AT_MF_COUNT; } +mfn0 : M_COUNT '(' ')' { $$ = B_AT_MF_COUNT; } + ; + +mfn1 : F_DELETE { $$ = B_AC_DELETE; } ; term : '(' term ')' { $$ = $2; } @@ -189,18 +192,22 @@ term : '(' term ')' { $$ = $2; } | NUMBER { $$ = ba_new($1, B_AT_LONG); } | builtin { $$ = ba_new(NULL, $1); } | gvar { $$ = bv_get($1); } + | map { $$ = $1; } + ; + +gvar : '@' STRING { $$ = $2; } + +map : gvar '[' arg ']' { $$ = bm_get($1, $3); } ; marg : arg { $$ = $1; } - | mapfunc { $$ = ba_new(NULL, $1); }; + | mfn0 { $$ = ba_new(NULL, $1); }; ; arg : CSTRING { $$ = ba_new($1, B_AT_STR); } | term ; -gvar : '@' STRING { $$ = $2; } - arglist : arg | arglist ',' arg { $$ = ba_append($1, $3); } ; @@ -208,9 +215,10 @@ arglist : arg stmt : '\n' { $$ = NULL; } | gvar '=' arg ';' { $$ = bv_set($1, $3); } | gvar '[' arg ']' '=' marg ';' { $$ = bm_set($1, $3, $6); } - | funcn '(' arglist ')' ';' { $$ = bs_new($1, $3, NULL); } - | func1 '(' arg ')' ';' { $$ = bs_new($1, $3, NULL); } - | func0 '(' ')' ';' { $$ = bs_new($1, NULL, NULL); } + | fnN '(' arglist ')' ';' { $$ = bs_new($1, $3, NULL); } + | fn1 '(' arg ')' ';' { $$ = bs_new($1, $3, NULL); } + | fn0 '(' ')' ';' { $$ = bs_new($1, NULL, NULL); } + | mfn1 '(' map ')' ';' { $$ = bm_fn($1, $3, NULL); } ; stmtlist : stmt @@ -441,22 +449,36 @@ bv_get(const char *vname) } struct bt_stmt * -bm_fn(enum bt_action mact, const char *mname, struct bt_arg *mkey, - struct bt_arg *mval) +bm_fn(enum bt_action mact, struct bt_arg *ba, struct bt_arg *mval) +{ + return bs_new(mact, ba, (struct bt_var *)mval); +} + +/* Create a 'map store' statement to assign a value to a map entry. */ +struct bt_stmt * +bm_set(const char *mname, struct bt_arg *mkey, struct bt_arg *mval) { + struct bt_arg *ba; struct bt_var *bv; bv = bv_find(mname); if (bv == NULL) bv = bv_new(mname); - return bs_new(mact, ba_append(mval, mkey), bv); + ba = ba_new(bv, B_AT_MAP); + ba->ba_key = mkey; + return bs_new(B_AC_INSERT, ba, (struct bt_var *)mval); } -/* Create a 'map store' statement to assign a value to a map entry. */ -struct bt_stmt * -bm_set(const char *mname, struct bt_arg *mkey, struct bt_arg *mval) +/* Create an argument that points to a variable and attach a key to it. */ +struct bt_arg * +bm_get(const char *mname, struct bt_arg *mkey) { - return bm_fn(B_AC_INSERT, mname, mkey, mval); + struct bt_arg *ba; + + ba = bv_get(mname); + ba->ba_type = B_AT_MAP; + ba->ba_key = mkey; + return ba; } struct keyword { diff --git a/usr.sbin/btrace/bt_parser.h b/usr.sbin/btrace/bt_parser.h index 4083faddbc6..392331576ed 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.2 2020/01/27 14:15:25 mpi Exp $ */ +/* $OpenBSD: bt_parser.h,v 1.3 2020/01/28 12:13:49 mpi Exp $ */ /* * Copyright (c) 2019 Martin Pieuchot @@ -98,10 +98,12 @@ struct bt_var { struct bt_arg { SLIST_ENTRY(bt_arg) ba_next; void *ba_value; + struct bt_arg *ba_key; /* key for maps */ enum bt_argtype { B_AT_STR = 1, /* C-style string */ B_AT_LONG, /* Number (integer) */ B_AT_VAR, /* global variable (@var) */ + B_AT_MAP, /* global map (@map[]) */ B_AT_BI_PID, B_AT_BI_TID, diff --git a/usr.sbin/btrace/btrace.c b/usr.sbin/btrace/btrace.c index 13175d0dba3..c5048233cf5 100644 --- a/usr.sbin/btrace/btrace.c +++ b/usr.sbin/btrace/btrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: btrace.c,v 1.2 2020/01/27 14:15:25 mpi Exp $ */ +/* $OpenBSD: btrace.c,v 1.3 2020/01/28 12:13:49 mpi Exp $ */ /* * Copyright (c) 2019 - 2020 Martin Pieuchot @@ -675,14 +675,16 @@ stmt_clear(struct bt_stmt *bs) void stmt_delete(struct bt_stmt *bs, struct dt_evt *dtev) { - struct bt_arg *bkey = SLIST_FIRST(&bs->bs_args); - struct bt_var *bv = bs->bs_var; - - assert(SLIST_NEXT(bkey, ba_next) == NULL); + struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args); + struct bt_var *bv = bmap->ba_value; - map_delete(bv, ba2hash(bkey, dtev)); + assert(bmap->ba_type == B_AT_MAP); + assert(bs->bs_var == NULL); + bkey = bmap->ba_key; debug("map=%p '%s' delete key=%p\n", bv->bv_value, bv->bv_name, bkey); + + map_delete(bv, ba2hash(bkey, dtev)); } /* @@ -694,16 +696,18 @@ stmt_delete(struct bt_stmt *bs, struct dt_evt *dtev) void stmt_insert(struct bt_stmt *bs, struct dt_evt *dtev) { - struct bt_arg *bkey, *bval = SLIST_FIRST(&bs->bs_args); - struct bt_var *bv = bs->bs_var; + struct bt_arg *bkey, *bmap = SLIST_FIRST(&bs->bs_args); + struct bt_arg *bval = (struct bt_arg *)bs->bs_var; + struct bt_var *bv = bmap->ba_value; - bkey = SLIST_NEXT(bval, ba_next); - assert(SLIST_NEXT(bkey, ba_next) == NULL); - - map_insert(bv, ba2hash(bkey, dtev), bval); + assert(bmap->ba_type == B_AT_MAP); + assert(SLIST_NEXT(bval, ba_next) == NULL); + bkey = bmap->ba_key; debug("map=%p '%s' insert key=%p bval=%p\n", bv->bv_value, bv->bv_name, bkey, bval); + + map_insert(bv, ba2hash(bkey, dtev), bval); } /* @@ -802,6 +806,7 @@ stmt_zero(struct bt_stmt *bs) debug("map=%p '%s' zero\n", bv->bv_value, bv->bv_name); } + struct bt_arg * ba_read(struct bt_arg *ba) { @@ -936,6 +941,9 @@ ba2str(struct bt_arg *ba, struct dt_evt *dtev) snprintf(buf, sizeof(buf) - 1, "%ld", (long)dtev->dtev_sysretval); str = buf; break; + case B_AT_MAP: + str = ba2str(map_get(ba->ba_value, ba2str(ba->ba_key, dtev)), dtev); + break; case B_AT_VAR: str = ba2str(ba_read(ba), dtev); break; diff --git a/usr.sbin/btrace/btrace.h b/usr.sbin/btrace/btrace.h index df99fb6fe06..dc87b49cb91 100644 --- a/usr.sbin/btrace/btrace.h +++ b/usr.sbin/btrace/btrace.h @@ -1,4 +1,4 @@ -/* $OpenBSD: btrace.h,v 1.1 2020/01/21 16:24:55 mpi Exp $ */ +/* $OpenBSD: btrace.h,v 1.2 2020/01/28 12:13:49 mpi Exp $ */ /* * Copyright (c) 2019 - 2020 Martin Pieuchot @@ -40,6 +40,7 @@ int kelf_snprintsym(char *, size_t, unsigned long); /* map.c */ void map_clear(struct bt_var *); void map_delete(struct bt_var *, const char *); +struct bt_arg *map_get(struct bt_var *, const char *); void map_insert(struct bt_var *, const char *, struct bt_arg *); void map_print(struct bt_var *, size_t); diff --git a/usr.sbin/btrace/map.c b/usr.sbin/btrace/map.c index eaf9559972d..97abb6efbf5 100644 --- a/usr.sbin/btrace/map.c +++ b/usr.sbin/btrace/map.c @@ -1,4 +1,4 @@ -/* $OpenBSD: map.c,v 1.1 2020/01/21 16:24:55 mpi Exp $ */ +/* $OpenBSD: map.c,v 1.2 2020/01/28 12:13:49 mpi Exp $ */ /* * Copyright (c) 2020 Martin Pieuchot @@ -43,7 +43,8 @@ struct mentry { struct bt_arg *mval; }; -int mcmp(struct mentry *, struct mentry *); +int mcmp(struct mentry *, struct mentry *); +struct mentry *mget(struct mtree *, const char *); RB_GENERATE(mtree, mentry, mlink, mcmp); @@ -53,6 +54,25 @@ mcmp(struct mentry *me0, struct mentry *me1) return strncmp(me0->mkey, me1->mkey, KLEN - 1); } +struct mentry * +mget(struct mtree *map, const char *key) +{ + struct mentry me, *mep; + + strlcpy(me.mkey, key, KLEN); + mep = RB_FIND(mtree, map, &me); + if (mep == NULL) { + mep = calloc(1, sizeof(struct mentry)); + if (mep == NULL) + err(1, "mentry: calloc"); + + strlcpy(mep->mkey, key, KLEN); + RB_INSERT(mtree, map, mep); + } + + return mep; +} + void map_clear(struct bt_var *bv) { @@ -77,15 +97,30 @@ map_delete(struct bt_var *bv, const char *key) struct mentry me, *mep; strlcpy(me.mkey, key, KLEN); - mep = RB_REMOVE(mtree, map, &me); - free(mep); + mep = RB_FIND(mtree, map, &me); + if (mep != NULL) { + RB_REMOVE(mtree, map, mep); + free(mep); + } } +struct bt_arg * +map_get(struct bt_var *bv, const char *key) +{ + struct mtree *map = (struct mtree *)bv->bv_value; + struct mentry *mep; + + mep = mget(map, key); + if (mep->mval == NULL) + mep->mval = ba_new(0, B_AT_LONG); + + return mep->mval; +} void map_insert(struct bt_var *bv, const char *key, struct bt_arg *bval) { struct mtree *map = (struct mtree *)bv->bv_value; - struct mentry me, *mep; + struct mentry *mep; long val; if (map == NULL) { @@ -95,17 +130,7 @@ map_insert(struct bt_var *bv, const char *key, struct bt_arg *bval) bv->bv_value = (struct bt_arg *)map; } - strlcpy(me.mkey, key, KLEN); - mep = RB_FIND(mtree, map, &me); - if (mep == NULL) { - mep = calloc(1, sizeof(struct mentry)); - if (mep == NULL) - err(1, "mentry: calloc"); - - strlcpy(mep->mkey, key, KLEN); - RB_INSERT(mtree, map, mep); - } - + mep = mget(map, key); switch (bval->ba_type) { case B_AT_MF_COUNT: if (mep->mval == NULL) @@ -116,6 +141,7 @@ map_insert(struct bt_var *bv, const char *key, struct bt_arg *bval) break; case B_AT_STR: case B_AT_LONG: + free(mep->mval); mep->mval = bval; break; default: @@ -123,12 +149,13 @@ map_insert(struct bt_var *bv, const char *key, struct bt_arg *bval) } } +static struct bt_arg nullba = { {NULL }, (void *)0, NULL, B_AT_LONG }; +static struct bt_arg maxba = { { NULL }, (void *)LONG_MAX, NULL, B_AT_LONG }; + /* Print at most `top' entries of the map ordered by value. */ void map_print(struct bt_var *bv, size_t top) { - static struct bt_arg nullba = { { NULL }, (void *)0, B_AT_LONG }; - static struct bt_arg maxba = { { NULL }, (void *)LONG_MAX, B_AT_LONG }; struct mtree *map = (void *)bv->bv_value; struct mentry *mep, *mcur; struct bt_arg *bhigh, *bprev; -- cgit v1.2.3