]> git.proxmox.com Git - mirror_qemu.git/blob - include/qemu/coroutine-tls.h
util/reserved-region: Add new ReservedRegion helpers
[mirror_qemu.git] / include / qemu / coroutine-tls.h
1 /*
2 * QEMU Thread Local Storage for coroutines
3 *
4 * Copyright Red Hat
5 *
6 * SPDX-License-Identifier: LGPL-2.1-or-later
7 *
8 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
9 * See the COPYING.LIB file in the top-level directory.
10 *
11 * It is forbidden to access Thread Local Storage in coroutines because
12 * compiler optimizations may cause values to be cached across coroutine
13 * re-entry. Coroutines can run in more than one thread through the course of
14 * their life, leading bugs when stale TLS values from the wrong thread are
15 * used as a result of compiler optimization.
16 *
17 * An example is:
18 *
19 * ..code-block:: c
20 * :caption: A coroutine that may see the wrong TLS value
21 *
22 * static __thread AioContext *current_aio_context;
23 * ...
24 * static void coroutine_fn foo(void)
25 * {
26 * aio_notify(current_aio_context);
27 * qemu_coroutine_yield();
28 * aio_notify(current_aio_context); // <-- may be stale after yielding!
29 * }
30 *
31 * This header provides macros for safely defining variables in Thread Local
32 * Storage:
33 *
34 * ..code-block:: c
35 * :caption: A coroutine that safely uses TLS
36 *
37 * QEMU_DEFINE_STATIC_CO_TLS(AioContext *, current_aio_context)
38 * ...
39 * static void coroutine_fn foo(void)
40 * {
41 * aio_notify(get_current_aio_context());
42 * qemu_coroutine_yield();
43 * aio_notify(get_current_aio_context()); // <-- safe
44 * }
45 */
46
47 #ifndef QEMU_COROUTINE_TLS_H
48 #define QEMU_COROUTINE_TLS_H
49
50 /*
51 * To stop the compiler from caching TLS values we define accessor functions
52 * with __attribute__((noinline)) plus asm volatile("") to prevent
53 * optimizations that override noinline.
54 *
55 * The compiler can still analyze noinline code and make optimizations based on
56 * that knowledge, so an inline asm output operand is used to prevent
57 * optimizations that make assumptions about the address of the TLS variable.
58 *
59 * This is fragile and ultimately needs to be solved by a mechanism that is
60 * guaranteed to work by the compiler (e.g. stackless coroutines), but for now
61 * we use this approach to prevent issues.
62 */
63
64 /**
65 * QEMU_DECLARE_CO_TLS:
66 * @type: the variable's C type
67 * @var: the variable name
68 *
69 * Declare an extern variable in Thread Local Storage from a header file:
70 *
71 * .. code-block:: c
72 * :caption: Declaring an extern variable in Thread Local Storage
73 *
74 * QEMU_DECLARE_CO_TLS(int, my_count)
75 * ...
76 * int c = get_my_count();
77 * set_my_count(c + 1);
78 * *get_ptr_my_count() = 0;
79 *
80 * This is a coroutine-safe replacement for the __thread keyword and is
81 * equivalent to the following code:
82 *
83 * .. code-block:: c
84 * :caption: Declaring a TLS variable using __thread
85 *
86 * extern __thread int my_count;
87 * ...
88 * int c = my_count;
89 * my_count = c + 1;
90 * *(&my_count) = 0;
91 */
92 #define QEMU_DECLARE_CO_TLS(type, var) \
93 __attribute__((noinline)) type get_##var(void); \
94 __attribute__((noinline)) void set_##var(type v); \
95 __attribute__((noinline)) type *get_ptr_##var(void);
96
97 /**
98 * QEMU_DEFINE_CO_TLS:
99 * @type: the variable's C type
100 * @var: the variable name
101 *
102 * Define a variable in Thread Local Storage that was previously declared from
103 * a header file with QEMU_DECLARE_CO_TLS():
104 *
105 * .. code-block:: c
106 * :caption: Defining a variable in Thread Local Storage
107 *
108 * QEMU_DEFINE_CO_TLS(int, my_count)
109 *
110 * This is a coroutine-safe replacement for the __thread keyword and is
111 * equivalent to the following code:
112 *
113 * .. code-block:: c
114 * :caption: Defining a TLS variable using __thread
115 *
116 * __thread int my_count;
117 */
118 #define QEMU_DEFINE_CO_TLS(type, var) \
119 static __thread type co_tls_##var; \
120 type get_##var(void) { asm volatile(""); return co_tls_##var; } \
121 void set_##var(type v) { asm volatile(""); co_tls_##var = v; } \
122 type *get_ptr_##var(void) \
123 { type *ptr = &co_tls_##var; asm volatile("" : "+rm" (ptr)); return ptr; }
124
125 /**
126 * QEMU_DEFINE_STATIC_CO_TLS:
127 * @type: the variable's C type
128 * @var: the variable name
129 *
130 * Define a static variable in Thread Local Storage:
131 *
132 * .. code-block:: c
133 * :caption: Defining a static variable in Thread Local Storage
134 *
135 * QEMU_DEFINE_STATIC_CO_TLS(int, my_count)
136 * ...
137 * int c = get_my_count();
138 * set_my_count(c + 1);
139 * *get_ptr_my_count() = 0;
140 *
141 * This is a coroutine-safe replacement for the __thread keyword and is
142 * equivalent to the following code:
143 *
144 * .. code-block:: c
145 * :caption: Defining a static TLS variable using __thread
146 *
147 * static __thread int my_count;
148 * ...
149 * int c = my_count;
150 * my_count = c + 1;
151 * *(&my_count) = 0;
152 */
153 #define QEMU_DEFINE_STATIC_CO_TLS(type, var) \
154 static __thread type co_tls_##var; \
155 static __attribute__((noinline, unused)) \
156 type get_##var(void) \
157 { asm volatile(""); return co_tls_##var; } \
158 static __attribute__((noinline, unused)) \
159 void set_##var(type v) \
160 { asm volatile(""); co_tls_##var = v; } \
161 static __attribute__((noinline, unused)) \
162 type *get_ptr_##var(void) \
163 { type *ptr = &co_tls_##var; asm volatile("" : "+rm" (ptr)); return ptr; }
164
165 #endif /* QEMU_COROUTINE_TLS_H */