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 size_t stack_size; 37 sigjmp_buf env; 38 } CoroutineSigAltStack; 39 40 /** 41 * Per-thread coroutine bookkeeping 42 */ 43 typedef struct { 44 /** Currently executing coroutine */ 45 Coroutine *current; 46 47 /** The default coroutine */ 48 CoroutineSigAltStack leader; 49 50 /** Information for the signal handler (trampoline) */ 51 sigjmp_buf tr_reenter; 52 volatile sig_atomic_t tr_called; 53 void *tr_handler; 54 } CoroutineThreadState; 55 56 static pthread_key_t thread_state_key; 57 58 static CoroutineThreadState *coroutine_get_thread_state(void) 59 { 60 CoroutineThreadState *s = pthread_getspecific(thread_state_key); 61 62 if (!s) { 63 s = g_malloc0(sizeof(*s)); 64 s->current = &s->leader.base; 65 pthread_setspecific(thread_state_key, s); 66 } 67 return s; 68 } 69 70 static void qemu_coroutine_thread_cleanup(void *opaque) 71 { 72 CoroutineThreadState *s = opaque; 73 74 g_free(s); 75 } 76 77 static void __attribute__((constructor)) coroutine_init(void) 78 { 79 int ret; 80 81 ret = pthread_key_create(&thread_state_key, qemu_coroutine_thread_cleanup); 82 if (ret != 0) { 83 fprintf(stderr, "unable to create leader key: %s\n", strerror(errno)); 84 abort(); 85 } 86 } 87 88 /* "boot" function 89 * This is what starts the coroutine, is called from the trampoline 90 * (from the signal handler when it is not signal handling, read ahead 91 * for more information). 92 */ 93 static void coroutine_bootstrap(CoroutineSigAltStack *self, Coroutine *co) 94 { 95 /* Initialize longjmp environment and switch back the caller */ 96 if (!sigsetjmp(self->env, 0)) { 97 siglongjmp(*(sigjmp_buf *)co->entry_arg, 1); 98 } 99 100 while (true) { 101 co->entry(co->entry_arg); 102 qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE); 103 } 104 } 105 106 /* 107 * This is used as the signal handler. This is called with the brand new stack 108 * (thanks to sigaltstack). We have to return, given that this is a signal 109 * handler and the sigmask and some other things are changed. 110 */ 111 static void coroutine_trampoline(int signal) 112 { 113 CoroutineSigAltStack *self; 114 Coroutine *co; 115 CoroutineThreadState *coTS; 116 117 /* Get the thread specific information */ 118 coTS = coroutine_get_thread_state(); 119 self = coTS->tr_handler; 120 coTS->tr_called = 1; 121 co = &self->base; 122 123 /* 124 * Here we have to do a bit of a ping pong between the caller, given that 125 * this is a signal handler and we have to do a return "soon". Then the 126 * caller can reestablish everything and do a siglongjmp here again. 127 */ 128 if (!sigsetjmp(coTS->tr_reenter, 0)) { 129 return; 130 } 131 132 /* 133 * Ok, the caller has siglongjmp'ed back to us, so now prepare 134 * us for the real machine state switching. We have to jump 135 * into another function here to get a new stack context for 136 * the auto variables (which have to be auto-variables 137 * because the start of the thread happens later). Else with 138 * PIC (i.e. Position Independent Code which is used when PTH 139 * is built as a shared library) most platforms would 140 * horrible core dump as experience showed. 141 */ 142 coroutine_bootstrap(self, co); 143 } 144 145 Coroutine *qemu_coroutine_new(void) 146 { 147 CoroutineSigAltStack *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_size = COROUTINE_STACK_SIZE; 168 co->stack = qemu_alloc_stack(&co->stack_size); 169 co->base.entry_arg = &old_env; /* stash away our jmp_buf */ 170 171 coTS = coroutine_get_thread_state(); 172 coTS->tr_handler = co; 173 174 /* 175 * Preserve the SIGUSR2 signal state, block SIGUSR2, 176 * and establish our signal handler. The signal will 177 * later transfer control onto the signal stack. 178 */ 179 sigemptyset(&sigs); 180 sigaddset(&sigs, SIGUSR2); 181 pthread_sigmask(SIG_BLOCK, &sigs, &osigs); 182 sa.sa_handler = coroutine_trampoline; 183 sigfillset(&sa.sa_mask); 184 sa.sa_flags = SA_ONSTACK; 185 if (sigaction(SIGUSR2, &sa, &osa) != 0) { 186 abort(); 187 } 188 189 /* 190 * Set the new stack. 191 */ 192 ss.ss_sp = co->stack; 193 ss.ss_size = co->stack_size; 194 ss.ss_flags = 0; 195 if (sigaltstack(&ss, &oss) < 0) { 196 abort(); 197 } 198 199 /* 200 * Now transfer control onto the signal stack and set it up. 201 * It will return immediately via "return" after the sigsetjmp() 202 * was performed. Be careful here with race conditions. The 203 * signal can be delivered the first time sigsuspend() is 204 * called. 205 */ 206 coTS->tr_called = 0; 207 pthread_kill(pthread_self(), SIGUSR2); 208 sigfillset(&sigs); 209 sigdelset(&sigs, SIGUSR2); 210 while (!coTS->tr_called) { 211 sigsuspend(&sigs); 212 } 213 214 /* 215 * Inform the system that we are back off the signal stack by 216 * removing the alternative signal stack. Be careful here: It 217 * first has to be disabled, before it can be removed. 218 */ 219 sigaltstack(NULL, &ss); 220 ss.ss_flags = SS_DISABLE; 221 if (sigaltstack(&ss, NULL) < 0) { 222 abort(); 223 } 224 sigaltstack(NULL, &ss); 225 if (!(oss.ss_flags & SS_DISABLE)) { 226 sigaltstack(&oss, NULL); 227 } 228 229 /* 230 * Restore the old SIGUSR2 signal handler and mask 231 */ 232 sigaction(SIGUSR2, &osa, NULL); 233 pthread_sigmask(SIG_SETMASK, &osigs, NULL); 234 235 /* 236 * Now enter the trampoline again, but this time not as a signal 237 * handler. Instead we jump into it directly. The functionally 238 * redundant ping-pong pointer arithmetic is necessary to avoid 239 * type-conversion warnings related to the `volatile' qualifier and 240 * the fact that `jmp_buf' usually is an array type. 241 */ 242 if (!sigsetjmp(old_env, 0)) { 243 siglongjmp(coTS->tr_reenter, 1); 244 } 245 246 /* 247 * Ok, we returned again, so now we're finished 248 */ 249 250 return &co->base; 251 } 252 253 void qemu_coroutine_delete(Coroutine *co_) 254 { 255 CoroutineSigAltStack *co = DO_UPCAST(CoroutineSigAltStack, base, co_); 256 257 qemu_free_stack(co->stack, co->stack_size); 258 g_free(co); 259 } 260 261 CoroutineAction qemu_coroutine_switch(Coroutine *from_, Coroutine *to_, 262 CoroutineAction action) 263 { 264 CoroutineSigAltStack *from = DO_UPCAST(CoroutineSigAltStack, base, from_); 265 CoroutineSigAltStack *to = DO_UPCAST(CoroutineSigAltStack, base, to_); 266 CoroutineThreadState *s = coroutine_get_thread_state(); 267 int ret; 268 269 s->current = to_; 270 271 ret = sigsetjmp(from->env, 0); 272 if (ret == 0) { 273 siglongjmp(to->env, action); 274 } 275 return ret; 276 } 277 278 Coroutine *qemu_coroutine_self(void) 279 { 280 CoroutineThreadState *s = coroutine_get_thread_state(); 281 282 return s->current; 283 } 284 285 bool qemu_in_coroutine(void) 286 { 287 CoroutineThreadState *s = pthread_getspecific(thread_state_key); 288 289 return s && s->current->caller; 290 } 291 292