System calls are atomic in Unix. That is either all of the effects of a system call are visible to other processes or none of them are. Hence, basic synchronization is performed using system calls.
There are two types of system calls; fast and slow. Fast system calls can be performed without any waiting; an example is reading the processes PID. Slow system calls may require waiting; for example, many file system syscalls (including all that use a pathname) may have one or more waits as they traverse directories and inodes.
A slow system call can be suspended, but only at well defined points which are explicitly coded into the kernel. Hence, the filesystem path accessing syscall may suspend and wake up after each inode or directory read. If the system call is suspended (as opposed to completed) the process will be blocked.
There are two ways to make slow system calls into fast (non-blocking) calls: