3 ms·
> Why aren't there OS-native green threads, or at the very least user-space scheduling affordances for runtimes that want to implement them without overhead in
by Jtsummers 4y ago
> Why aren't there OS-native green threads, or at the very least user-space scheduling affordances for runtimes that want to implement them without overhead in calling blocking code?
Green threads are, definitionally, not OS threads, they are user space threads. So you will never see OS-native green threads as it's an oxymoron. The way many green thread systems work is to either lie to you (you really only have one OS thread, the green threads exist to write concurrent code, which can be much simpler, but not parallel code using Pike's distinction), or to introduce multiple OS threads ("carrier threads" in the terms of this article) which green threads are distributed across (this is what Java is doing here, Go has done for a long time, BEAM languages for a long time, and many others).
EDIT:
To extend this, many people think of "green threads" as lightweight threading mechanisms. That's kind of accurate for many systems, but not always true. If that's the sense that's meant, then OS-native lightweight threads are certainly possible in the future. But there's probably not much reason to add them when user space lightweight concurrency mechanisms already exist, and there's no consensus on which ones are "best" (by whatever metric).
- Sakos 4y ago> To extend this, many people think of "green threads" as lightweight threading mechanisms. That's kind of accurate for many systems, but not always true. If that's the sense that's meant, then OS-native lightweight threads are certainly possible in the future. But there's probably not much reason to add them when user space lightweight concurrency mechanisms already exist, and there's no consensus on which ones are "best" (by whatever metric). Wouldn't it make sense to implement them kernel-side when looking at how every programming language seems to have to reinvent the wheel regarding green threads?
- Jtsummers 4y agoGreen threads (today) aren't a singular thing, the definition is that they're in user space not kernel space. They are implemented in a variety of ways: https://en.wikipedia.org/wiki/Green_thread https://en.wikipedia.org/wiki/Green_thread Do you imitate a more traditional OS-thread style with preemption, do you use cooperating tasks, coroutines, what? Since there is no singular best or consensus model, there is little reason for an OS to adopt wholesale one of these variations at this time. The original green threads (from that page) shared one OS thread and used cooperative multitasking (most coroutine approaches would be analogous to this). But today, like with Go and BEAM languages, they're distributed across real OS threads to get parallelism. Which approach should an OS adopt? And if it did, would other languages/runtimes abandon their own models if it were significantly different?
- smasher164 4y agoPreemptive threads with growable stacks. There was some discussion around getting segmented stacks into the kernel, but I'm not sure that's the best approach. There might have to be some novel work done in making contiguous stacks work in a shared address space.
- wtetzner 4y agoI think the reasons green threads can work in languages is that the runtime understands the language semantics, and can take advantage of them. The OS doesn't understand the language and its concurrency semantics, and only has a blob of machine code to work with.
- smasher164 4y agoNot really tbh. The Go runtime has a work-stealing scheduler and does a lot of work to provide the same abstractions that pthreads have, but for goroutines.
- throwawaymaths 4y agoErlang runtime has a work stealing scheduler but it has specific constraints like "how to make sure each running execution context gets a fair share of time and can't lock up the VM (I think you can still lock the go VM with an infinite loop)... So each VM has different concerns.
- smasher164 4y ago> still lock the go VM with an infinite loop This is no longer an issue now with Go's async preemption. Also, this is less a "language-level concern" and more a consequence of a poor implementation of preemptive scheduling. Moreover, this is something OS threads already support.
- throwawaymaths 4y agoYes, but os threads come with overheads during context switches and for sure during the startup/teardown because you have to take a trip to the kernel to do those things. I don't see how it should be the os's business how to do m:n green threads. I think BEAM, for example can do a lot of clever coordination-free scheduling (it implements mutexes which are aware of the scheduling layout and I think don't bother to coordinate if they aren't necessary). In Erlang, the GC is green-thread aware, since green threads in Erlang don't share much memory -- I don't think there is a good generalized way for an OS to know these sorts of things without kneecapping some pl or another. Arguably a better place for this is the standard library of your (low level) PL. I think rust and zig do this.
- smasher164 4y ago> If that's the sense that's meant Yeah that's what I meant, a lightweight threading mechanism provided by the OS. > there's probably not much reason to add them when user space lightweight concurrency mechanisms already exist Yeah... I don't think there's consensus on that. It seems that many people find OS threads to be an understandable concurrency model, but find them too heavyweight. So the languages end up introducing other abstractions at either the type-level (which has other benefits mind you!) or runtime to compensate.
- gpderetta 4y agoKernel support for green threads (or better, M:N) was a big topic 20 years ago. Look for "scheduler activation" for example. It kind of petered off as kernel only threads were fast enough with significantly less complexity. In might be worth revisiting again.
- smasher164 4y agoYeah, scheduler activations were one approach, albeit one that wasn't deemed effective. I think FreeBSD ended up removing the feature. A more recent attempt that's interesting is ghOSt from Google: https://storage.googleapis.com/pub-tools-public-publication-data/pdf/0ee589331b9bf270b13d40ba09453cde14006869.pdf https://storage.googleapis.com/pub-tools-public-publication-....
- tedunangst 4y agoThe problem solved by SA is equivalently solved by a scalable multiplex IO syscall like kevent and userland scheduling. There's no particular need for the upcall if blocking information is available another way. I think it's dead.
- gpderetta 4y agoYou might want to preempt after scheduling quanta expirations, page faults, etc. And there is still the issue of existing code that use the standard blocking system APIs. Also a synchronous API can be more efficient if it is not going to block and only the kernel can know. In practice you are right, so far SA hasn't been worth the complexity.