System calls are always made by processes to the kernel.
So to answer the specific questions.
- The parent process makes the
wait call to the kernel. - The child process makes the
exit call to the kernel.
The following is a much simplified view of what happens.
When the process calls exit the kernel stores the argument (the return code) in the internal process table, destroys all the other resources associated with the process (allocated memory, open file descriptors) and marks the process as a zombie.
When the parent calls wait the kernel checks to see if any child is in zombie state. If so then it gets the stored return code from the internal process table, releases the slot in the table and returns from the wait system call passing back the return code. If the child is not in zombie state then the kernel blocks the parent process until the child calls exit.
When any process calls exit then any remaining child processes are reparented to the process with PID 1, so all processes except the first always have a parent.
PID 1 starts everything running (network services, listeners on serial lines, the gui login program), and then goes into an infinite loop calling wait so the kernel process table doesn't fill up with zombies.
There are a lot of things I have simplified, these days you can ask the kernel to reparent to a process other than process number 1 a subreaper, there are lots of forms of the wait call (wait, waitid, waitpid, wait3, wait4 (man pages), interaction with the ptrace system call, what destroying the allocated resources means etc.