NetBSD only comparatively recently added support for multithreading and it did so in a very ambitious way. Threading implementations can roughly be divided into three categories, depending on the number of kernel scheduler entities are mapped to threads. The simplest model is 1:N, which means that all threading is implemented in userspace using timer events. The model used by most is 1:1, meaning all thread scheduling is handled by the kernel.
The third approach is to adopt a M:N model, in which some threads are scheduled by the kernel, whereas others are handled in userspace. This is the most flexible; it means that fewer kernel resources are needed and allows faster, userspace-only, context switching to be used where appropriate. This is also the hardest to get right. Solaris used to use this model, but moved to 1:1 recently. FreeBSD 5.x also introduced an M:N model, but the team is now moving back to a 1:1 approach. The NetBSD team seems to be sticking with M:N. I asked what the secret was. Bill Studenmund gave this answer:
As to what the secret is, a main issue has been getting the exact internal functioning correct. This version of the library has a number of critical code sections (usually a few lines of code each) fixed.
The benchmarks certainly look promising, and Bill adds:
The current library has been used in a number of high-performance applications and is stable.
One side-effect of NetBSD’s focus on portability is the fact that the system is very clean, with well-separated abstraction layers. Geert Hendrickx summed up the NetBSD philosophy with this:
We strive to build a clean, open source, portable, standards-compliant, secure, and performant UNIX-like operating system, and I think we’re doing a good job at that. Many people regard NetBSD as a "reference" UNIX implementation, centered around code quality.
Thanks to all the members of the NetBSD team who answered questions in time for this article, and especially to Geert Hendrickx for his assistance.