Ok it looks like current techniques are stackless runtimes and compiling coroutines to stackless continuations:
https://en.wikipedia.org/wiki/Stackless_Python
https://stackless.readthedocs.io/en/v3.6.4-slp/library/stack...
http://jessenoller.com/blog/2009/02/23/stackless-you-got-you...
https://engagedscholarship.csuohio.edu/cgi/viewcontent.cgi?r...
https://pdfs.semanticscholar.org/b9aa/49e4b7a00e6c9f0d8c18ba...
https://www.osnews.com/story/9822/protothreads-extremely-lig...
This looks like a rare gem, although I just started reading it:
https://cs.indiana.edu/~dfried/dfried/mex.pdf
I grew up with the cooperative multithreading of classic Mac OS and was really shocked when I first saw Javascript back in the 90s and it had no notion of it (because it didn't have generators). That sent us down the callback hell evolutionary dead end, through promises/futures and finally to async/await where we are now. That could have been largely avoided if we had listened to programming language experts!