1 /* 2 * sigaltstack coroutine initialization code 3 * 4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws> 5 * Copyright (C) 2011 Kevin Wolf <kwolf@redhat.com> 6 * Copyright (C) 2012 Alex Barcelo <abarcelo@ac.upc.edu> 7 ** This file is partly based on pth_mctx.c, from the GNU Portable Threads 8 ** Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com> 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 22 */ 23 24 /* XXX Is there a nicer way to disable glibc's stack check for longjmp? */ 25 #ifdef _FORTIFY_SOURCE 26 #undef _FORTIFY_SOURCE 27 #endif 28 #include "qemu/osdep.h" 29 #include <pthread.h> 30 #include "qemu-common.h" 31 #include "qemu/coroutine_int.h" 32 33 typedef struct { 34 Coroutine base; 35 void *stack; 36 sigjmp_buf env; 37 } CoroutineUContext; 38 39 /** 40 * Per-thread coroutine bookkeeping 41 */ 42 typedef struct { 43 /** Currently executing coroutine */ 44 Coroutine *current; 45 46 /** The default coroutine */ 47 CoroutineUContext leader; 48 49 /** Information for the signal handler (trampoline) */ 50 sigjmp_buf tr_reenter; 51 volatile sig_atomic_t tr_called; 52 void *tr_handler; 53 } CoroutineThreadState; 54 55 static pthread_key_t thread_state_key; 56 57 static CoroutineThreadState *coroutine_get_thread_state(void) 58 { 59 CoroutineThreadState *s = pthread_getspecific(thread_state_key); 60 61 if (!s) { 62 s = g_malloc0(sizeof(*s)); 63 s->current = &s->leader.base; 64 pthread_setspecific(thread_state_key, s); 65 } 66 return s; 67 } 68 69 static void qemu_coroutine_thread_cleanup(void *opaque) 70 { 71 CoroutineThreadState *s = opaque; 72 73 g_free(s); 74 } 75 76 static void __attribute__((constructor)) coroutine_init(void) 77 { 78 int ret; 79 80 ret = pthread_key_create(&thread_state_key, qemu_coroutine_thread_cleanup); 81 if (ret != 0) { 82 fprintf(stderr, "unable to create leader key: %s\n", strerror(errno)); 83 abort(); 84 } 85 } 86 87 /* "boot" function 88 * This is what starts the coroutine, is called from the trampoline 89 * (from the signal handler when it is not signal handling, read ahead 90 * for more information). 91 */ 92 static void coroutine_bootstrap(CoroutineUContext *self, Coroutine *co) 93 { 94 /* Initialize longjmp environment and switch back the caller */ 95 if (!sigsetjmp(self->env, 0)) { 96 siglongjmp(*(sigjmp_buf *)co->entry_arg, 1); 97 } 98 99 while (true) { 100 co->entry(co->entry_arg); 101 qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE); 102 } 103 } 104 105 /* 106 * This is used as the signal handler. This is called with the brand new stack 107 * (thanks to sigaltstack). We have to return, given that this is a signal 108 * handler and the sigmask and some other things are changed. 109 */ 110 static void coroutine_trampoline(int signal) 111 { 112 CoroutineUContext *self; 113 Coroutine *co; 114 CoroutineThreadState *coTS; 115 116 /* Get the thread specific information */ 117 coTS = coroutine_get_thread_state(); 118 self = coTS->tr_handler; 119 coTS->tr_called = 1; 120 co = &self->base; 121 122 /* 123 * Here we have to do a bit of a ping pong between the caller, given that 124 * this is a signal handler and we have to do a return "soon". Then the 125 * caller can reestablish everything and do a siglongjmp here again. 126 */ 127 if (!sigsetjmp(coTS->tr_reenter, 0)) { 128 return; 129 } 130 131 /* 132 * Ok, the caller has siglongjmp'ed back to us, so now prepare 133 * us for the real machine state switching. We have to jump 134 * into another function here to get a new stack context for 135 * the auto variables (which have to be auto-variables 136 * because the start of the thread happens later). Else with 137 * PIC (i.e. Position Independent Code which is used when PTH 138 * is built as a shared library) most platforms would 139 * horrible core dump as experience showed. 140 */ 141 coroutine_bootstrap(self, co); 142 } 143 144 Coroutine *qemu_coroutine_new(void) 145 { 146 const size_t stack_size = 1 << 20; 147 CoroutineUContext *co; 148 CoroutineThreadState *coTS; 149 struct sigaction sa; 150 struct sigaction osa; 151 stack_t ss; 152 stack_t oss; 153 sigset_t sigs; 154 sigset_t osigs; 155 sigjmp_buf old_env; 156 157 /* The way to manipulate stack is with the sigaltstack function. We 158 * prepare a stack, with it delivering a signal to ourselves and then 159 * put sigsetjmp/siglongjmp where needed. 160 * This has been done keeping coroutine-ucontext as a model and with the 161 * pth ideas (GNU Portable Threads). See coroutine-ucontext for the basics 162 * of the coroutines and see pth_mctx.c (from the pth project) for the 163 * sigaltstack way of manipulating stacks. 164 */ 165 166 co = g_malloc0(sizeof(*co)); 167 co->stack = g_malloc(stack_size); 168 co->base.entry_arg = &old_env; /* stash away our jmp_buf */ 169 170 coTS = coroutine_get_thread_state(); 171 coTS->tr_handler = co; 172 173 /* 174 * Preserve the SIGUSR2 signal state, block SIGUSR2, 175 * and establish our signal handler. The signal will 176 * later transfer control onto the signal stack. 177 */ 178 sigemptyset(&sigs); 179 sigaddset(&sigs, SIGUSR2); 180 pthread_sigmask(SIG_BLOCK, &sigs, &osigs); 181 sa.sa_handler = coroutine_trampoline; 182 sigfillset(&sa.sa_mask); 183 sa.sa_flags = SA_ONSTACK; 184 if (sigaction(SIGUSR2, &sa, &osa) != 0) { 185 abort(); 186 } 187 188 /* 189 * Set the new stack. 190 */ 191 ss.ss_sp = co->stack; 192 ss.ss_size = stack_size; 193 ss.ss_flags = 0; 194 if (sigaltstack(&ss, &oss) < 0) { 195 abort(); 196 } 197 198 /* 199 * Now transfer control onto the signal stack and set it up. 200 * It will return immediately via "return" after the sigsetjmp() 201 * was performed. Be careful here with race conditions. The 202 * signal can be delivered the first time sigsuspend() is 203 * called. 204 */ 205 coTS->tr_called = 0; 206 pthread_kill(pthread_self(), SIGUSR2); 207 sigfillset(&sigs); 208 sigdelset(&sigs, SIGUSR2); 209 while (!coTS->tr_called) { 210 sigsuspend(&sigs); 211 } 212 213 /* 214 * Inform the system that we are back off the signal stack by 215 * removing the alternative signal stack. Be careful here: It 216 * first has to be disabled, before it can be removed. 217 */ 218 sigaltstack(NULL, &ss); 219 ss.ss_flags = SS_DISABLE; 220 if (sigaltstack(&ss, NULL) < 0) { 221 abort(); 222 } 223 sigaltstack(NULL, &ss); 224 if (!(oss.ss_flags & SS_DISABLE)) { 225 sigaltstack(&oss, NULL); 226 } 227 228 /* 229 * Restore the old SIGUSR2 signal handler and mask 230 */ 231 sigaction(SIGUSR2, &osa, NULL); 232 pthread_sigmask(SIG_SETMASK, &osigs, NULL); 233 234 /* 235 * Now enter the trampoline again, but this time not as a signal 236 * handler. Instead we jump into it directly. The functionally 237 * redundant ping-pong pointer arithmetic is necessary to avoid 238 * type-conversion warnings related to the `volatile' qualifier and 239 * the fact that `jmp_buf' usually is an array type. 240 */ 241 if (!sigsetjmp(old_env, 0)) { 242 siglongjmp(coTS->tr_reenter, 1); 243 } 244 245 /* 246 * Ok, we returned again, so now we're finished 247 */ 248 249 return &co->base; 250 } 251 252 void qemu_coroutine_delete(Coroutine *co_) 253 { 254 CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_); 255 256 g_free(co->stack); 257 g_free(co); 258 } 259 260 CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_, 261 CoroutineAction action) 262 { 263 CoroutineUContext *from = DO_UPCAST(CoroutineUContext, base, from_); 264 CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, to_); 265 CoroutineThreadState *s = coroutine_get_thread_state(); 266 int ret; 267 268 s->current = to_; 269 270 ret = sigsetjmp(from->env, 0); 271 if (ret == 0) { 272 siglongjmp(to->env, action); 273 } 274 return ret; 275 } 276 277 Coroutine *qemu_coroutine_self(void) 278 { 279 CoroutineThreadState *s = coroutine_get_thread_state(); 280 281 return s->current; 282 } 283 284 bool qemu_in_coroutine(void) 285 { 286 CoroutineThreadState *s = pthread_getspecific(thread_state_key); 287 288 return s && s->current->caller; 289 } 290 291