Parallelize ifnet.if_addrhead accessing by duplicating the list itself
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 7 Mar 2008 11:34:21 +0000 (11:34 +0000)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 7 Mar 2008 11:34:21 +0000 (11:34 +0000)
commitb26321761f0797b0f857a7a03f96de2e75e186c2
treee2f31dac4be06c7a3ece9f292a99d606693aae06
parentb4882ee60bc478810bdcf24d7a08a71069b0c033
Parallelize ifnet.if_addrhead accessing by duplicating the list itself
on each CPU, each list element points to ifaddr:
- Add SI_SUB_PRE_DRIVERS before SI_SUB_DRIVERS, so action could be taken
  before drivers' initialization (mainly before NIC driver's if_attach())
- Move netisr_init() to the FIRST of SI_SUB_PRE_DRIVERS, so that
  netmsg_service_port_init() could be called in earlier stage of system
  initialization.
- Create one thread on each CPU to propagate changes to ifnet.if_addrhead.
  Their thread ports are registered with netmsg_service_port_init() for
  port syncing operation.
- Change to ifnet.if_addrhead begins in netisr0, i.e. serial of changes
  to ifnet.if_addrhead are serialized by netisr0
- ifaddr's refcnt is moved to its list elements, i.e. per-CPU refcnt.
  They are initialized to 1 instead of 0.
- A magic field is added to ifaddr list element to make sure that IFAREF
  and IFAFREE are called on valid ifaddr list element.  This field is
  initialized to a magic value and is wiped out once the list element's
  refcnt drops to 0
- To close the gap between testing and freeing, once the ifaddr list
  element's refcnt drops to 0, ifa_portfn(0) (a thread's port on CPU0) is
  poked to check whether ifaddr is referenced on other CPUs, if not, then
  ifaddr is freed on ifa_portfn(0)

Reviewed-by: dillon@ (earlier version)
52 files changed:
sys/contrib/ipfilter/netinet/fil.c
sys/dev/netif/sr/if_sr.c
sys/emulation/linux/linux_ioctl.c
sys/net/ef/if_ef.c
sys/net/if.c
sys/net/if_atmsubr.c
sys/net/if_var.h
sys/net/ip6fw/ip6_fw.c
sys/net/ipfw/ip_fw2.c
sys/net/net_osdep.h
sys/net/netisr.c
sys/net/pf/pf_if.c
sys/net/rtsock.c
sys/net/sppp/if_spppsubr.c
sys/net/stf/if_stf.c
sys/net/tun/if_tun.c
sys/netgraph/eiface/ng_eiface.c
sys/netgraph/fec/ng_fec.c
sys/netgraph/iface/ng_iface.c
sys/netinet/if_ether.c
sys/netinet/in.c
sys/netinet/ip_carp.c
sys/netinet/ip_divert.c
sys/netinet/ip_icmp.c
sys/netinet/ip_input.c
sys/netinet/sctp_asconf.c
sys/netinet/sctp_output.c
sys/netinet/sctp_pcb.c
sys/netinet/sctp_usrreq.c
sys/netinet/sctputil.c
sys/netinet6/icmp6.c
sys/netinet6/in6.c
sys/netinet6/in6_ifattach.c
sys/netinet6/in6_prefix.c
sys/netinet6/in6_var.h
sys/netinet6/nd6.c
sys/netinet6/nd6_nbr.c
sys/netinet6/nd6_rtr.c
sys/netproto/atalk/aarp.c
sys/netproto/atalk/at_control.c
sys/netproto/atm/atm_if.c
sys/netproto/ipx/ipx.c
sys/netproto/ipx/ipx_input.c
sys/netproto/ipx/ipx_usrreq.c
sys/netproto/ns/idp_usrreq.c
sys/netproto/ns/ns.c
sys/netproto/ns/ns_input.c
sys/platform/pc32/i386/autoconf.c
sys/sys/kernel.h
sys/vfs/nfs/bootp_subr.c
usr.bin/netstat/if.c
usr.sbin/ifmcstat/ifmcstat.c