The BSD Layer
Atop Mach sits a modified BSD kernel. Back in the NeXT days, this was based on 4BSD. Now it is based on FreeBSD, and code flows both to and from this project on a fairly regular basis. You may have noticed that OS X advertised fine-grained kernel locking in 10.4, shortly after the same feature appeared in stable releases of FreeBSD. FreeBSD is also the source of Darwin's libc, the library that implements the core features required by the POSIX and C language specifications, among other things.
If you do any relatively low-level programming on OS X, you can find lots of things that look familiar from FreeBSD. The most obvious of these is the kqueue() interface. This provides a unified mechanism for waiting for events from the kernel. These events can be things like timers, signals, data ready for reading on a file descriptor, and so on. On OS X, they also include Mach port status changes. A typical Mac OS X application spends most of its time in the kevent() system call, waiting for an event from the kernel to wake it up.
The BSD layer provides most of the operating system services that the Mach layer does not. Mach provides a few basic abstractions: ports, messages, tasks, threads, and memory objects. A task is a collection of threads and access rights to memory objects and ports. It corresponds roughly with a UNIX process, and a Mach thread corresponds roughly with a POSIX thread. Part of the responsibility of the BSD layer in the XNU kernel is making this rough mapping concrete. The process tables are maintained by the modified FreeBSD kernel, as are the filesystem and network stacks, UNIX-style IPC, and quite a few other things.
You can do a lot on OS X without getting down to the Mach layer. Some calls, like fork() or pthread_create(), are partially handled down there. fork() in particular is quite complex. This call needs to mark the address space as copy-on-write by manipulating the relevant Mach memory objects, create a new Mach task for the copied objects, and create a new Mach thread with a copy of the original thread's stack. Back up in the BSD layer, it also needs to create new entries in the process table, copy any file descriptors that the process has open, and so on.
Because the Mach layer is responsible for threads, it is also responsible for scheduling. This means that the new FreeBSD scheduler is not present in OS X.