poudriere -j 128 performs frequent killpg and process list export calls, both of which traverse the entire list with allproc lock held. This stalls forks, exits and waits as each of these operations takes the lock effectively giving very high contention on proctree lock which when held waits for allproc.
This change implements a very basic lock array for the pid hash and an iterator function which takes a callback. A 30 minute poudriere run has seen drop in proctree wait time to 5% of the previous kernel. Note the traversal still does not scale, but it stops being a bottleneck to the rest of the kernel.
Removal of zombie processes is postponed until reaping so that process list exporting can still see them.
pfind and other functions will be updated later to use the newly introduced locks.
Relevant locks before:
> 13411440062 (sx:proctree)
> 98113595 (sx:allproc)
after:
> 573040146 (sx:proctree)
> 268533 (sx:allproc)
> 211663 (sx:pidhash)