> Date: Wed, 8 Nov 2017 10:37:02 +0100
> From: Martin Pieuchot <m...@openbsd.org>
> 
> We're at the stage where we want to run multiple parts of the Network
> Stack in parallel.  sashan@ is trying to get multiple network threads
> running to exercise parallelism in pf_test() and tb@ is trying to push
> the NET_LOCK() further down in ioctl(2) path.
> 
> However we want to be able to gradually select which code paths can be
> executed in parallel as the rest of the stack.  So the way to move
> forward is to introduce a read version of the NET_LOCK(), NET_RLOCK()
> and change code paths on a case-by-case basis.
> 
> Diff below does that for the input processing path.  Note that the 3
> tasks below cannot run in parallel because they are scheduled on the
> same taskq.
> 
> Regarding assert macros, NET_ASSERT_LOCK() now required either a read
> or write lock.  I also introduced a NET_ASSERT_WLOCK() to put in paths
> that are not ready to be run in parallel of the rest of the stack.
> 
> Once that's in we can slowly convert existing NET_LOCK() to NET_WLOCK()
> to be explicit.
> 
> Ok?

makes sense to me

> Index: net/if.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if.c,v
> retrieving revision 1.523
> diff -u -p -r1.523 if.c
> --- net/if.c  4 Nov 2017 16:58:46 -0000       1.523
> +++ net/if.c  8 Nov 2017 09:01:12 -0000
> @@ -905,7 +905,7 @@ if_input_process(void *xifidx)
>        * to PF globals, pipex globals, unicast and multicast addresses
>        * lists.
>        */
> -     NET_LOCK();
> +     NET_RLOCK();
>       s = splnet();
>       while ((m = ml_dequeue(&ml)) != NULL) {
>               /*
> @@ -922,7 +922,7 @@ if_input_process(void *xifidx)
>                       m_freem(m);
>       }
>       splx(s);
> -     NET_UNLOCK();
> +     NET_RUNLOCK();
>  out:
>       if_put(ifp);
>  }
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.329
> diff -u -p -r1.329 ip_input.c
> --- netinet/ip_input.c        5 Nov 2017 13:19:59 -0000       1.329
> +++ netinet/ip_input.c        8 Nov 2017 09:06:57 -0000
> @@ -1814,11 +1814,11 @@ ip_send_dispatch(void *xmq)
>       if (ml_empty(&ml))
>               return;
>  
> -     NET_LOCK();
> +     NET_RLOCK();
>       while ((m = ml_dequeue(&ml)) != NULL) {
>               ip_output(m, NULL, NULL, 0, NULL, NULL, 0);
>       }
> -     NET_UNLOCK();
> +     NET_RUNLOCK();
>  }
>  
>  void
> Index: netinet6/ip6_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
> retrieving revision 1.207
> diff -u -p -r1.207 ip6_input.c
> --- netinet6/ip6_input.c      1 Nov 2017 06:35:38 -0000       1.207
> +++ netinet6/ip6_input.c      8 Nov 2017 09:07:16 -0000
> @@ -1459,7 +1459,7 @@ ip6_send_dispatch(void *xmq)
>       if (ml_empty(&ml))
>               return;
>  
> -     NET_LOCK();
> +     NET_RLOCK();
>       while ((m = ml_dequeue(&ml)) != NULL) {
>               /*
>                * To avoid a "too big" situation at an intermediate router and
> @@ -1470,7 +1470,7 @@ ip6_send_dispatch(void *xmq)
>                */
>               ip6_output(m, NULL, NULL, IPV6_MINMTU, NULL, NULL);
>       }
> -     NET_UNLOCK();
> +     NET_RUNLOCK();
>  }
>  
>  void
> Index: sys/systm.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/systm.h,v
> retrieving revision 1.133
> diff -u -p -r1.133 systm.h
> --- sys/systm.h       11 Aug 2017 21:24:20 -0000      1.133
> +++ sys/systm.h       8 Nov 2017 09:21:51 -0000
> @@ -296,26 +296,34 @@ int     uiomove(void *, size_t, struct uio *
>  
>  extern struct rwlock netlock;
>  
> -#define      NET_LOCK()                                                      
> \
> -do {                                                                 \
> -     rw_enter_write(&netlock);                                       \
> -} while (0)
> +#define NET_LOCK()   NET_WLOCK()
> +#define NET_UNLOCK() NET_WUNLOCK()
>  
> -#define      NET_UNLOCK()                                                    
> \
> +#define      NET_WLOCK()     do { rw_enter_write(&netlock); } while (0)
> +#define      NET_WUNLOCK()   do { rw_exit_write(&netlock); } while (0)
> +
> +#define      NET_ASSERT_WLOCKED()                                            
> \
>  do {                                                                 \
> -     rw_exit_write(&netlock);                                        \
> +     int _s = rw_status(&netlock);                                   \
> +     if (_s != RW_WRITE)                                             \
> +             splassert_fail(RW_WRITE, _s, __func__);                 \
>  } while (0)
>  
> +#define      NET_RLOCK()     do { rw_enter_read(&netlock); } while (0)
> +#define      NET_RUNLOCK()   do { rw_exit_read(&netlock); } while (0)
> +
>  #define      NET_ASSERT_LOCKED()                                             
> \
>  do {                                                                 \
> -     if (rw_status(&netlock) != RW_WRITE)                            \
> -             splassert_fail(RW_WRITE, rw_status(&netlock), __func__);\
> +     int _s = rw_status(&netlock);                                   \
> +     if (_s != RW_WRITE && _s != RW_READ)                            \
> +             splassert_fail(RW_READ, _s, __func__);                  \
>  } while (0)
>  
>  #define      NET_ASSERT_UNLOCKED()                                           
> \
>  do {                                                                 \
> -     if (rw_status(&netlock) == RW_WRITE)                            \
> -             splassert_fail(0, rw_status(&netlock), __func__);       \
> +     int _s = rw_status(&netlock);                                   \
> +     if (_s == RW_WRITE || _s == RW_READ)                            \
> +             splassert_fail(0, _s, __func__);                        \
>  } while (0)
>  
>  __returns_twice int  setjmp(label_t *);
> 
> 

Reply via email to