diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2015-06-05 17:44:47 +0200 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2015-06-08 17:38:58 +0200 |
commit | caf28401cac9ece5e314360f8a3a54479df59727 (patch) | |
tree | 7ada0451442ffa1d9d056500ebd878ad80da3e06 /src/continuation.c | |
parent | 39c315241350dde3741c99fee4fff17b22d2b1fa (diff) | |
download | spice-gtk-caf28401cac9ece5e314360f8a3a54479df59727.tar.gz spice-gtk-caf28401cac9ece5e314360f8a3a54479df59727.tar.xz spice-gtk-caf28401cac9ece5e314360f8a3a54479df59727.zip |
Move gtk/ -> src/
For historical reasons, the code was placed under gtk/ subdirectory.
If it was always bugging you, bug no more!
Diffstat (limited to 'src/continuation.c')
-rw-r--r-- | src/continuation.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/continuation.c b/src/continuation.c new file mode 100644 index 0000000..adce858 --- /dev/null +++ b/src/continuation.c @@ -0,0 +1,102 @@ +/* + * GTK VNC Widget + * + * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "config.h" + +/* keep this above system headers, but below config.h */ +#ifdef _FORTIFY_SOURCE +#undef _FORTIFY_SOURCE +#endif + +#include <errno.h> +#include <glib.h> + +#include "continuation.h" + +/* + * va_args to makecontext() must be type 'int', so passing + * the pointer we need may require several int args. This + * union is a quick hack to let us do that + */ +union cc_arg { + void *p; + int i[2]; +}; + +static void continuation_trampoline(int i0, int i1) +{ + union cc_arg arg; + struct continuation *cc; + arg.i[0] = i0; + arg.i[1] = i1; + cc = arg.p; + + if (_setjmp(cc->jmp) == 0) { + ucontext_t tmp; + swapcontext(&tmp, &cc->last); + } + + cc->entry(cc); +} + +void cc_init(struct continuation *cc) +{ + volatile union cc_arg arg; + arg.p = cc; + if (getcontext(&cc->uc) == -1) + g_error("getcontext() failed: %s", g_strerror(errno)); + cc->uc.uc_link = &cc->last; + cc->uc.uc_stack.ss_sp = cc->stack; + cc->uc.uc_stack.ss_size = cc->stack_size; + cc->uc.uc_stack.ss_flags = 0; + + makecontext(&cc->uc, (void *)continuation_trampoline, 2, arg.i[0], arg.i[1]); + swapcontext(&cc->last, &cc->uc); +} + +int cc_release(struct continuation *cc) +{ + if (cc->release) + return cc->release(cc); + + return 0; +} + +int cc_swap(struct continuation *from, struct continuation *to) +{ + to->exited = 0; + if (getcontext(&to->last) == -1) + return -1; + else if (to->exited == 0) + to->exited = 1; // so when coroutine finishes + else if (to->exited == 1) + return 1; // it ends up here + + if (_setjmp(from->jmp) == 0) + _longjmp(to->jmp, 1); + + return 0; +} +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ |