On Fri, Oct 23, 2015 at 02:41:34PM +0200, Martin Pieuchot wrote:
> 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@.

OK 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;

Reply via email to