The Mach kernel is presented as a drop-in replacement for traditional UNIX kernels. It's not a new Operating System, but rather a new way of implementing the set of system calls that is UNIX. The implementation is designed to be more portable and extensible. There is a clear separation between machine-dependant code and machine-independent code. The goal is for new features and/or hardware support to be added without needing to change the high-level API. User applications should be able to use new features transparently. It does, however, add some new abstractions such as tasks, ports, and messages. The original Mach was built with and compared to the 4.3 BSD kernel. It has evolved since then, being adapted for use in Mac OS X as well as Linux, which is proof that their goals of extensibility and portability have been met. However, that is outside of the scope of this paper which was written in 1986. TASKS Instead of the typical UNIX processes and threads, Mach has tasks and threads. Tasks are the basic unit of resource allocation, like a process. They include VM address space and protected access to system resources. Unlike a process, they are without execution context. Tasks are orthogonal to threads. Threads are the units execution, existing inside of tasks. The advantage is that instead of expensive operations like fork(), multiple threads within the same task can be used to achieve parallelism or to saturate a multi-processor system. Today, I believe more Unix-like systems than Mach have this advantage due to user libraries that can use multiple kernel threads within one process. However, I have not yet done enough research to determine if this is actually the case. Threads share all resources inside of a task, and tasks can share resources through Copy-On-Write VM pages or shared memory. PORTS UNIX systems have a multitude of abstractions for communication: pipes, streams, sockets, PTYs, semaphores, IOCTLs on special files, shared memory, etc. And none of these have uniform system calls for their use. This corroborates our discussion from last week about the advantages of UNIX's choice of representing everything as a file (taken further by Plan 9 with currently unknown results) under a uniform API. It does raise one question however, should sockets look and act like files or not? Mach solves this by giving all communication a single interface: ports. Ports are controlled and privileged kernel objects that are like queues for sending and receiving data. Tasks can or cannot have various privileges with respect to a given port, such as send or receive. MESSAGES Messages are simply typed data objects that tasks can use to communicate, move data, share capabilities for ports, and synchronize. These abstracts form the base of the Mach kernel on top of which more advanced system calls may be built. They give applications a uniform API for the majority of the tasks they would want to accomplish, which should make application development easier for Mach. This is a positive step, simplifying the programming to a level much like it was with the original UNIX. With Mach, instead of everything being a file, now everything is done by passing messages through ports. This includes sharing memory, synchronizing tasks, and even communicating over the network. In the VM subsystem, Copy-On-Write is frequently employed to make operations more efficient. I am curious as to whether Mach originated the COW semantics, or if they were simply implemented as an improvement over naive copying of memory. Tasks have very specific control of which parts of their address space is to be shared with peers or children, giving the user a great deal of flexibility like many of the original UNIX design decisions. This is even more evident in the implementation of the VM subsystem, where behaviour is programmable. For example, mmap() can be implemented using primitive operations and the file system server as a ``pager''. The pager is what controls where the backing storage for VM pages comes from. It is another example of the clean separation of portable and non-portable code in the implementation of Mach. Mach also includes some handy features such as a built-in kernel debugger, which most UNIXen of the time did not have, and a remote file system. The RFS has an interesting implementation details wherein remote volumes are not mounted. They are represented as special files that are cached locally. Accesses to the file prompt messages to be sent over the network to check the status of the remote file. In conclusion, Mach looks like it served very effectively as it intended: a new foundation for UNIX development. The concentration on portability and a consistent interface for all objects within the system is a major advantage for operating system development.