The kernel provides a convenient routine, the for_each_process() macro, which lets you easily iterate over every process in the task list:
// include/linux/sched/signal.h:
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
Clearly, the macro expands to a for loop, allowing us to loop over the circular list. init_task is a convenient 'head' or starting pointer – it points to the task structure of the very first user space process, traditionally init(1), now systemd(1).
Note that the for_each_process() macro is expressly designed to only iterate over the main() thread of every process and not the ('child' or peer) threads.
A brief snippet of our ch6/foreach/prcs_showall kernel module's output is shown here (when run on our x86_64 Ubuntu 18.04 LTS guest system...