1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include "qemu-common.h"
27#include "qemu/coroutine_int.h"
28
29typedef struct
30{
31 Coroutine base;
32
33 LPVOID fiber;
34 CoroutineAction action;
35} CoroutineWin32;
36
37static __thread CoroutineWin32 leader;
38static __thread Coroutine *current;
39
40
41
42
43
44
45
46
47
48CoroutineAction __attribute__((noinline))
49qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
50 CoroutineAction action)
51{
52 CoroutineWin32 *from = DO_UPCAST(CoroutineWin32, base, from_);
53 CoroutineWin32 *to = DO_UPCAST(CoroutineWin32, base, to_);
54
55 current = to_;
56
57 to->action = action;
58 SwitchToFiber(to->fiber);
59 return from->action;
60}
61
62static void CALLBACK coroutine_trampoline(void *co_)
63{
64 Coroutine *co = co_;
65
66 while (true) {
67 co->entry(co->entry_arg);
68 qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
69 }
70}
71
72Coroutine *qemu_coroutine_new(void)
73{
74 const size_t stack_size = COROUTINE_STACK_SIZE;
75 CoroutineWin32 *co;
76
77 co = g_malloc0(sizeof(*co));
78 co->fiber = CreateFiber(stack_size, coroutine_trampoline, &co->base);
79 return &co->base;
80}
81
82void qemu_coroutine_delete(Coroutine *co_)
83{
84 CoroutineWin32 *co = DO_UPCAST(CoroutineWin32, base, co_);
85
86 DeleteFiber(co->fiber);
87 g_free(co);
88}
89
90Coroutine *qemu_coroutine_self(void)
91{
92 if (!current) {
93 current = &leader.base;
94 leader.fiber = ConvertThreadToFiber(NULL);
95 }
96 return current;
97}
98
99bool qemu_in_coroutine(void)
100{
101 return current && current->caller;
102}
103