I still think it is worth to have refcount debugging in generic kernel dt(4). Having tools is easier than first adding printf to hunt a bug. I see no downside.
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 21 Apr 2022 21:06:03 -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 21 Apr 2022 21:06:03 -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(dt_tracing) && \ + __predict_false(index > 0) && \ + __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 21 Apr 2022 21:06:03 -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.265 diff -u -p -r1.265 in_pcb.c --- netinet/in_pcb.c 14 Apr 2022 14:10:22 -0000 1.265 +++ netinet/in_pcb.c 21 Apr 2022 21:06:03 -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 21 Apr 2022 21:06:03 -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 21 Apr 2022 21:06:03 -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 21 Apr 2022 21:06:03 -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 */