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: