summaryrefslogtreecommitdiffstats
path: root/src/continuation.c
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2015-06-05 17:44:47 +0200
committerMarc-André Lureau <marcandre.lureau@redhat.com>2015-06-08 17:38:58 +0200
commitcaf28401cac9ece5e314360f8a3a54479df59727 (patch)
tree7ada0451442ffa1d9d056500ebd878ad80da3e06 /src/continuation.c
parent39c315241350dde3741c99fee4fff17b22d2b1fa (diff)
downloadspice-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.c102
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:
+ */