> 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 *); > >