As I've said, storage for the list elements comes from an array. In fact, so does storage for the dummy head and tail elements. The array that makes up the list storage is arranged as follows:
So, as you can see, it is not necessary to store the process ID (PID) of each process in the list element. It can be taken from the location of that element in the array.
In this array, positions 0 through NPROC - 1 are list nodes - they refer to processes on lists. Elements NPROC and greater are arranged in pairs. Each pair contains the head and the tail for one list.
This arrangement allows list routines to know if they are at the beginning or end of the list by examining the index to see if it is greater or equal to NPROC.
In file q.h where the array is sized, you will see that the size is NPROC + NSEM + NSEM + 4. This creates an array with one entry for each of:
and a head and tail for the sleep list.