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 */ 166