I can currently think of two ways of implementing a coroutine:
I think these two are popularly known as stackless and stackful coroutines.
What are other theoretically possible ways of implementing a coroutine? What are advantages and disadvantages of them? Which languages use which implementations?
Your option (1) is indeed a stackless coroutine, and this is how it's implemented in Kotlin, and usually Javascript (async/await), for example. This is how you do it when you don't necessarily have the low-level control of the call stack that other methods require. Languages that use this strategy require suspendable functions to be marked in some way. That's called the "red/blue function problem". See: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
Languages that do have low-level control of the call stack can implement coroutines in various ways, but none of them look like your option (2). They generally involve copying data into and out of the call stack when required (like Java project Loom) or using a completely different data structure in place of the call stack (like early Go implementations). In these languages, coroutine-callable functions don't usually need special markings.