On 22/10/15(Thu) 19:42, Martin Pieuchot wrote: > Now that we have a single refcounting mechanism for route entries, I'd > like to use atomic operations and grab the KERNEL_LOCK only if a CPU is > dropping the last reference on an entry. > > Currently this only matters for MPLS. I intentionally use atomic_* ops > because I'd like to see be able to see if a counter goes negative. > > For symmetry reasons I'm also moving the KERNEL_LOCK() inside rtalloc(). > These two functions are my current targets. > > Comments, oks?
Updated diff after some comments from dlg@ and bluhm@. Index: net/route.c =================================================================== RCS file: /cvs/src/sys/net/route.c,v retrieving revision 1.258 diff -u -p -r1.258 route.c --- net/route.c 22 Oct 2015 17:19:38 -0000 1.258 +++ net/route.c 23 Oct 2015 12:38:58 -0000 @@ -215,6 +215,7 @@ rtalloc(struct sockaddr *dst, int flags, info.rti_info[RTAX_DST] = dst; s = splsoftnet(); + KERNEL_LOCK(); rt = rtable_match(tableid, dst); if (rt != NULL) { if ((rt->rt_flags & RTF_CLONING) && ISSET(flags, RT_RESOLVE)) { @@ -236,6 +237,7 @@ miss: if (ISSET(flags, RT_REPORT)) rt_missmsg(RTM_MISS, &info, 0, NULL, error, tableid); } + KERNEL_UNLOCK(); splx(s); return (rt); } @@ -337,25 +339,29 @@ rtalloc_mpath(struct sockaddr *dst, uint void rtref(struct rtentry *rt) { - rt->rt_refcnt++; + atomic_inc_int(&rt->rt_refcnt); } void rtfree(struct rtentry *rt) { struct ifaddr *ifa; + int refcnt; if (rt == NULL) return; - if (--rt->rt_refcnt <= 0) { + refcnt = (int)atomic_dec_int_nv(&rt->rt_refcnt); + if (refcnt <= 0) { KASSERT(!ISSET(rt->rt_flags, RTF_UP)); KASSERT(!RT_ROOT(rt)); - rttrash--; - if (rt->rt_refcnt < 0) { + atomic_dec_int(&rttrash); + if (refcnt < 0) { printf("rtfree: %p not freed (neg refs)\n", rt); return; } + + KERNEL_LOCK(); rt_timer_remove_all(rt); ifa = rt->rt_ifa; if (ifa) @@ -368,6 +374,8 @@ rtfree(struct rtentry *rt) if (rt->rt_gateway) free(rt->rt_gateway, M_RTABLE, 0); free(rt_key(rt), M_RTABLE, 0); + KERNEL_UNLOCK(); + pool_put(&rtentry_pool, rt); } } @@ -773,7 +781,7 @@ rtrequest1(int req, struct rt_addrinfo * rt->rt_flags &= ~RTF_UP; if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) ifa->ifa_rtrequest(RTM_DELETE, rt); - rttrash++; + atomic_inc_int(&rttrash); if (ret_nrt != NULL) *ret_nrt = rt;