On Wed, Mar 23, 2022 at 06:13:27PM +0100, Alexander Bluhm wrote: > In my opinion tracepoints give insight at minimal cost. It is worth > it to have it in GENERIC to make it easy to use.
After release I want to revive the btrace of refcounts discussion. As mpi@ mentioned the idea of dt(4) is to have these trace points in GENERIC kernel. If you want to hunt a bug, just turn it on. Refounting is a common place for bugs, leaks can be detected easily. The alternative are some defines that you can compile in and access from ddb. This is more work and you would have to implement it for every recount. https://marc.info/?l=openbsd-tech&m=163786435916039&w=2 There is no measuarable performance difference. dt(4) is written in a way that is is only one additional branch. At least my goal is to add trace points to useful places when we identify them. ok? bluhm Index: dev/dt/dt_prov_static.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/dev/dt/dt_prov_static.c,v retrieving revision 1.13 diff -u -p -r1.13 dt_prov_static.c --- dev/dt/dt_prov_static.c 17 Mar 2022 14:53:59 -0000 1.13 +++ dev/dt/dt_prov_static.c 7 Apr 2022 17:32:23 -0000 @@ -87,6 +87,12 @@ DT_STATIC_PROBE1(smr, barrier_exit, "int DT_STATIC_PROBE0(smr, wakeup); DT_STATIC_PROBE2(smr, thread, "uint64_t", "uint64_t"); +/* + * reference counting + */ +DT_STATIC_PROBE0(refcnt, none); +DT_STATIC_PROBE3(refcnt, inpcb, "void *", "int", "int"); +DT_STATIC_PROBE3(refcnt, tdb, "void *", "int", "int"); /* * List of all static probes @@ -127,15 +133,24 @@ struct dt_probe *const dtps_static[] = { &_DT_STATIC_P(smr, barrier_exit), &_DT_STATIC_P(smr, wakeup), &_DT_STATIC_P(smr, thread), + /* refcnt */ + &_DT_STATIC_P(refcnt, none), + &_DT_STATIC_P(refcnt, inpcb), + &_DT_STATIC_P(refcnt, tdb), }; +struct dt_probe *const *dtps_index_refcnt; + int dt_prov_static_init(void) { int i; - for (i = 0; i < nitems(dtps_static); i++) + for (i = 0; i < nitems(dtps_static); i++) { + if (dtps_static[i] == &_DT_STATIC_P(refcnt, none)) + dtps_index_refcnt = &dtps_static[i]; dt_dev_register_probe(dtps_static[i]); + } return i; } Index: dev/dt/dtvar.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/dev/dt/dtvar.h,v retrieving revision 1.13 diff -u -p -r1.13 dtvar.h --- dev/dt/dtvar.h 27 Feb 2022 10:14:01 -0000 1.13 +++ dev/dt/dtvar.h 7 Apr 2022 17:41:55 -0000 @@ -313,11 +313,30 @@ extern volatile uint32_t dt_tracing; /* #define DT_STATIC_ENTER(func, name, args...) do { \ extern struct dt_probe _DT_STATIC_P(func, name); \ struct dt_probe *dtp = &_DT_STATIC_P(func, name); \ - struct dt_provider *dtpv = dtp->dtp_prov; \ \ if (__predict_false(dt_tracing) && \ __predict_false(dtp->dtp_recording)) { \ + struct dt_provider *dtpv = dtp->dtp_prov; \ + \ dtpv->dtpv_enter(dtpv, dtp, args); \ + } \ +} while (0) + +#define _DT_INDEX_P(func) (dtps_index_##func) + +#define DT_INDEX_ENTER(func, index, args...) do { \ + extern struct dt_probe **_DT_INDEX_P(func); \ + \ + if (__predict_false(index > 0) && \ + __predict_false(dt_tracing) && \ + __predict_true(_DT_INDEX_P(func) != NULL)) { \ + struct dt_probe *dtp = _DT_INDEX_P(func)[index]; \ + \ + if(__predict_false(dtp->dtp_recording)) { \ + struct dt_provider *dtpv = dtp->dtp_prov; \ + \ + dtpv->dtpv_enter(dtpv, dtp, args); \ + } \ } \ } while (0) Index: kern/kern_synch.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_synch.c,v retrieving revision 1.185 diff -u -p -r1.185 kern_synch.c --- kern/kern_synch.c 18 Mar 2022 15:32:06 -0000 1.185 +++ kern/kern_synch.c 7 Apr 2022 16:25:45 -0000 @@ -804,7 +804,15 @@ sys___thrwakeup(struct proc *p, void *v, void refcnt_init(struct refcnt *r) { + refcnt_init_trace(r, 0); +} + +void +refcnt_init_trace(struct refcnt *r, int idx) +{ + r->r_traceidx = idx; atomic_store_int(&r->r_refs, 1); + TRACEINDEX(refcnt, r->r_traceidx, r, 0, +1); } void @@ -814,6 +822,7 @@ refcnt_take(struct refcnt *r) refs = atomic_inc_int_nv(&r->r_refs); KASSERT(refs != 0); + TRACEINDEX(refcnt, r->r_traceidx, r, refs - 1, +1); (void)refs; } @@ -824,6 +833,7 @@ refcnt_rele(struct refcnt *r) refs = atomic_dec_int_nv(&r->r_refs); KASSERT(refs != ~0); + TRACEINDEX(refcnt, r->r_traceidx, r, refs + 1, -1); return (refs == 0); } @@ -842,11 +852,13 @@ refcnt_finalize(struct refcnt *r, const refs = atomic_dec_int_nv(&r->r_refs); KASSERT(refs != ~0); + TRACEINDEX(refcnt, r->r_traceidx, r, refs + 1, -1); while (refs) { sleep_setup(&sls, r, PWAIT, wmesg, 0); refs = atomic_load_int(&r->r_refs); sleep_finish(&sls, refs); } + TRACEINDEX(refcnt, r->r_traceidx, r, refs, 0); } int @@ -855,6 +867,7 @@ refcnt_shared(struct refcnt *r) u_int refs; refs = atomic_load_int(&r->r_refs); + TRACEINDEX(refcnt, r->r_traceidx, r, refs, 0); return (refs > 1); } @@ -864,6 +877,7 @@ refcnt_read(struct refcnt *r) u_int refs; refs = atomic_load_int(&r->r_refs); + TRACEINDEX(refcnt, r->r_traceidx, r, refs, 0); return (refs); } Index: netinet/in_pcb.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.264 diff -u -p -r1.264 in_pcb.c --- netinet/in_pcb.c 22 Mar 2022 18:02:54 -0000 1.264 +++ netinet/in_pcb.c 7 Apr 2022 16:25:45 -0000 @@ -235,7 +235,7 @@ in_pcballoc(struct socket *so, struct in return (ENOBUFS); inp->inp_table = table; inp->inp_socket = so; - refcnt_init(&inp->inp_refcnt); + refcnt_init_trace(&inp->inp_refcnt, DT_REFCNT_IDX_INPCB); inp->inp_seclevel[SL_AUTH] = IPSEC_AUTH_LEVEL_DEFAULT; inp->inp_seclevel[SL_ESP_TRANS] = IPSEC_ESP_TRANS_LEVEL_DEFAULT; inp->inp_seclevel[SL_ESP_NETWORK] = IPSEC_ESP_NETWORK_LEVEL_DEFAULT; Index: netinet/ip_ipsp.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipsp.c,v retrieving revision 1.269 diff -u -p -r1.269 ip_ipsp.c --- netinet/ip_ipsp.c 10 Mar 2022 15:21:08 -0000 1.269 +++ netinet/ip_ipsp.c 7 Apr 2022 16:25:45 -0000 @@ -1048,7 +1048,7 @@ tdb_alloc(u_int rdomain) tdbp = pool_get(&tdb_pool, PR_WAITOK | PR_ZERO); - refcnt_init(&tdbp->tdb_refcnt); + refcnt_init_trace(&tdbp->tdb_refcnt, DT_REFCNT_IDX_TDB); mtx_init(&tdbp->tdb_mtx, IPL_SOFTNET); TAILQ_INIT(&tdbp->tdb_policy_head); Index: sys/refcnt.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/sys/refcnt.h,v retrieving revision 1.6 diff -u -p -r1.6 refcnt.h --- sys/refcnt.h 16 Mar 2022 14:13:01 -0000 1.6 +++ sys/refcnt.h 7 Apr 2022 16:25:45 -0000 @@ -21,24 +21,30 @@ /* * Locks used to protect struct members in this file: + * I immutable after creation * a atomic operations */ struct refcnt { unsigned int r_refs; /* [a] reference counter */ + int r_traceidx; /* [I] index for dt(4) tracing */ }; -#define REFCNT_INITIALIZER() { .r_refs = 1 } +#define REFCNT_INITIALIZER() { .r_refs = 1, .r_traceidx = 0 } #ifdef _KERNEL void refcnt_init(struct refcnt *); +void refcnt_init_trace(struct refcnt *, int id); void refcnt_take(struct refcnt *); int refcnt_rele(struct refcnt *); void refcnt_rele_wake(struct refcnt *); void refcnt_finalize(struct refcnt *, const char *); int refcnt_shared(struct refcnt *); unsigned int refcnt_read(struct refcnt *); + +#define DT_REFCNT_IDX_INPCB 1 +#define DT_REFCNT_IDX_TDB 2 #endif /* _KERNEL */ Index: sys/tracepoint.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/sys/tracepoint.h,v retrieving revision 1.1 diff -u -p -r1.1 tracepoint.h --- sys/tracepoint.h 21 Jan 2020 16:16:23 -0000 1.1 +++ sys/tracepoint.h 7 Apr 2022 16:25:45 -0000 @@ -25,11 +25,13 @@ #if NDT > 0 #include <dev/dt/dtvar.h> -#define TRACEPOINT(func, name, args...) DT_STATIC_ENTER(func, name, args) +#define TRACEPOINT(func, name, args...) DT_STATIC_ENTER(func, name, args) +#define TRACEINDEX(func, index, args...) DT_INDEX_ENTER(func, index, args) #else /* NDT > 0 */ -#define TRACEPOINT(func, name, args...) +#define TRACEPOINT(func, name, args...) +#define TRACEINDEX(func, index, args...) #endif /* NDT > 0 */ #endif /* _KERNEL */