Interestingly enough, plan 9 did away with threads and replaced fork() with rfork() http://man.9front.org/2/fork.
Instead of having to deal with the duality of threads and processes they they opted to implement threading using light weight processes that share the parents data and bss segments. This is only turned on if you pass the RFMEM fag to rfork(), otherwise it behaves the same as unix fork and gives the child a copy of those segments.
This simplifies the system design as you only deal with processes which is arguably a more correct and simplified approach (I mean the OS only has 30 something syscalls). The api is implemented via a CSP library simply called thread. You replace main() with threadmain() and the thread api gives you all the concurrency tools. Or you can create your own threading library yourself if you so choose to.
If you are familiar with Go's CSP concurrency then you can thank plan 9's thread as Rob Pike, Ken Thompson and Russ Cox came from Bell Labs and built plan 9. And those ideas were born in Alef and Newsqueak.
It's a cleaner design, but I don't think it addresses the core of the issue.
You can still have say a "multi-threaded program" with a global mutex (the threads are created with RFMEM), and then when you want to fork (without RFMEM), you can be prone to deadlocks.
I guess the thread library has channels, and that doesn't happen? But as far as I know there are still mutexes in Go, and I would presume plan 9.
Go also has problems forking since it has a multi-threaded runtime. It only exposes os.ForkExec(), not os.Fork() and os.Execv().
FWIW, FreeBSD has rfork(2) as well. It’s not used for threading, though - FreeBSD has the usual, kernel-level threads instead of faking them on top of processes.
Unfortunately the current development state of Inferno is partially in Limbo (pun intended). This is why plan 9 users like myself tend not to mention it. The code is maintained by Vita Nova and available as open source but sees little if any development. There have been various ports but nothing is maintained. There is no stable bare metal image for i386 or Arm boards like RPi. It also doesn't build on 64 bit platforms, you need a 32bit chroot to build and 32 bit libs to run. It also fails to build on OpenBSD due to rthreads. I'd love to work on it but simply don't have the time. As for now, 9front boots and runs on modern hardware. I have a CPU server running an a low power Celeron J1900 board. However, I do have Inferno running hosted on my Raspberry Pi. Unfortunately it's quite unstable and crashes frequently.
Instead of having to deal with the duality of threads and processes they they opted to implement threading using light weight processes that share the parents data and bss segments. This is only turned on if you pass the RFMEM fag to rfork(), otherwise it behaves the same as unix fork and gives the child a copy of those segments.
This simplifies the system design as you only deal with processes which is arguably a more correct and simplified approach (I mean the OS only has 30 something syscalls). The api is implemented via a CSP library simply called thread. You replace main() with threadmain() and the thread api gives you all the concurrency tools. Or you can create your own threading library yourself if you so choose to.
If you are familiar with Go's CSP concurrency then you can thank plan 9's thread as Rob Pike, Ken Thompson and Russ Cox came from Bell Labs and built plan 9. And those ideas were born in Alef and Newsqueak.