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?

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