Some of these cooperatively multithreaded implementations have "green" varieties of all your standard functions; these are greenlet-aware (that is, aware of the cooperative threading & I/O loop that's happening) functions that do things like, for example, sleep. So, you might have a my_green_library.sleep and a calls_the_os.sleep; the latter of which will yield the hardware thread directly to the OS, and block that thread completely until its done. Whereas the former will perform a sort of userland context switch, and note something to the I/O loop, and then sleep until the next event.
Worse, this problem makes composition hard: you need to know the entire implementation of any function you call, in order to be aware of whether or not it will cause the calling thread to block.
Worse, this problem makes composition hard: you need to know the entire implementation of any function you call, in order to be aware of whether or not it will cause the calling thread to block.