FYI each coroutine is normally considered its own thread of execution (which is a distinct thing from a kernel scheduled thread).
Coroutines are distinct from threads as they normally lack a scheduler (the decision to which coroutine run next is either made statically ot explicitly by the coroutine); coroutines meant to be used on top of an userspace scheduler are often called fibers (or simply userspace, or green, threads).
Single Thread: 1 thread of execution, 1 execution stack
Coroutine: 1 thread of execution, multiple execution stacks
Multi threading: multiple threads of execution, multiple execution stacks