summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordeischen <deischen@FreeBSD.org>2003-07-19 04:41:08 +0000
committerdeischen <deischen@FreeBSD.org>2003-07-19 04:41:08 +0000
commit0800e2f8d165a62038aea1d18fc367168e60b617 (patch)
tree39f25a574077dd4f3c635ebb2967fbf56ce55256
parent51fb04092a97192e7331d750d8a9e973c6144599 (diff)
downloadFreeBSD-src-0800e2f8d165a62038aea1d18fc367168e60b617.zip
FreeBSD-src-0800e2f8d165a62038aea1d18fc367168e60b617.tar.gz
Add amd64 versions of makecontext() and signalcontext() needed
for libkse (makecontext() is also needed for libthr). These probably will need some tweaking.
-rw-r--r--lib/libc/amd64/gen/Makefile.inc3
-rw-r--r--lib/libc/amd64/gen/makecontext.c103
-rw-r--r--lib/libc/amd64/gen/signalcontext.c103
3 files changed, 208 insertions, 1 deletions
diff --git a/lib/libc/amd64/gen/Makefile.inc b/lib/libc/amd64/gen/Makefile.inc
index 15a1f2f..e50bbe6 100644
--- a/lib/libc/amd64/gen/Makefile.inc
+++ b/lib/libc/amd64/gen/Makefile.inc
@@ -3,4 +3,5 @@
SRCS+= _setjmp.S setjmp.S sigsetjmp.S \
fabs.S modf.S \
- frexp.c infinity.c isinf.c ldexp.c
+ frexp.c infinity.c isinf.c ldexp.c \
+ makecontext.c signalcontext.c
diff --git a/lib/libc/amd64/gen/makecontext.c b/lib/libc/amd64/gen/makecontext.c
new file mode 100644
index 0000000..87cf7bf
--- /dev/null
+++ b/lib/libc/amd64/gen/makecontext.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+typedef void (*func_t)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t);
+
+/* Prototypes */
+static void ctx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args);
+
+__weak_reference(__makecontext, makecontext);
+
+void
+__makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
+{
+ uint64_t *args;
+ uint64_t *sp;
+ va_list ap;
+ int i;
+
+ /* A valid context is required. */
+ if ((ucp == NULL) || (ucp->uc_mcontext.mc_len != sizeof(mcontext_t)))
+ return;
+ else if ((argc < 0) || (argc > 6) || (ucp->uc_stack.ss_sp == NULL) ||
+ (ucp->uc_stack.ss_size < MINSIGSTKSZ)) {
+ /*
+ * This should really return -1 with errno set to ENOMEM
+ * or something, but the spec says that makecontext is
+ * a void function. At least make sure that the context
+ * isn't valid so it can't be used without an error.
+ */
+ ucp->uc_mcontext.mc_len = 0;
+ return;
+ }
+
+ /* Align the stack to 16 bytes. */
+ sp = (uint64_t *)(ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
+ sp = (uint64_t *)((uint64_t)sp & -15UL);
+
+ /* Allocate space for a maximum of 6 arguments on the stack. */
+ args = sp - 6;
+
+ /* Account for arguments on stack and align to 16 bytes. */
+ sp -= 8;
+
+ /* Add the arguments: */
+ va_start(ap, argc);
+ for (i = 0; i < argc; i++)
+ args[i] = va_arg(ap, uint64_t);
+ va_end(ap);
+ for (i = argc; i < 6; i++)
+ args[i] = 0;
+
+ ucp->uc_mcontext.mc_rdi = (register_t)ucp;
+ ucp->uc_mcontext.mc_rsi = (register_t)start;
+ ucp->uc_mcontext.mc_rdx = (register_t)args;
+ ucp->uc_mcontext.mc_rbp = (register_t)sp;
+ ucp->uc_mcontext.mc_rbx = (register_t)sp;
+ ucp->uc_mcontext.mc_rsp = (register_t)sp;
+ ucp->uc_mcontext.mc_rip = (register_t)ctx_wrapper;
+}
+
+static void
+ctx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args)
+{
+ (*func)(args[0], args[1], args[2], args[3], args[4], args[5]);
+ if (ucp->uc_link == NULL)
+ exit(0);
+ setcontext((const ucontext_t *)ucp->uc_link);
+ /* should never get here */
+ abort();
+ /* NOTREACHED */
+}
diff --git a/lib/libc/amd64/gen/signalcontext.c b/lib/libc/amd64/gen/signalcontext.c
new file mode 100644
index 0000000..c713a4e
--- /dev/null
+++ b/lib/libc/amd64/gen/signalcontext.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <strings.h>
+
+typedef void (*handler_t)(uint64_t, uint64_t, uint64_t);
+
+/* Prototypes */
+static void ctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args);
+
+__weak_reference(__signalcontext, signalcontext);
+
+int
+__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
+{
+ uint64_t *args;
+ siginfo_t *sig_si;
+ ucontext_t *sig_uc;
+ uint64_t sp;
+
+ /* Bail out if we don't have a valid ucontext pointer. */
+ if (ucp == NULL)
+ abort();
+
+ /*
+ * Build a signal frame and copy the arguments of signal handler
+ * 'func' onto the stack. We only need 3 arguments, but we
+ * create room for 4 so that we are 16-byte aligned.
+ */
+ sp = (ucp->uc_mcontext.mc_rsp - sizeof(ucontext_t)) & ~15UL;
+ sig_uc = (ucontext_t *)sp;
+ bcopy(ucp, sig_uc, sizeof(*sig_uc));
+ sp = (sp - sizeof(siginfo_t)) & ~15UL;
+ sig_si = (siginfo_t *)sp;
+ bzero(sig_si, sizeof(*sig_si));
+ sig_si->si_signo = sig;
+ sp -= 4 * sizeof(uint64_t);
+ args = (uint64_t *)sp;
+ args[0] = sig;
+ args[1] = (intptr_t)sig_si;
+ args[2] = (intptr_t)sig_uc;
+ args[3] = 0;
+ sp -= 16;
+
+ /*
+ * Setup the ucontext of the signal handler.
+ */
+ bzero(&ucp->uc_mcontext, sizeof(ucp->uc_mcontext));
+ ucp->uc_link = sig_uc;
+ sigdelset(&ucp->uc_sigmask, sig);
+
+ ucp->uc_mcontext.mc_rdi = (register_t)ucp;
+ ucp->uc_mcontext.mc_rsi = (register_t)func;
+ ucp->uc_mcontext.mc_rdx = (register_t)args;
+ ucp->uc_mcontext.mc_rbp = (register_t)sp;
+ ucp->uc_mcontext.mc_rbx = (register_t)sp;
+ ucp->uc_mcontext.mc_rsp = (register_t)sp;
+ ucp->uc_mcontext.mc_rip = (register_t)ctx_wrapper;
+ return (0);
+}
+
+static void
+ctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args)
+{
+
+ (*func)(args[0], args[1], args[2]);
+ if (ucp->uc_link == NULL)
+ exit(0);
+ setcontext((const ucontext_t *)ucp->uc_link);
+ /* should never get here */
+ abort();
+ /* NOTREACHED */
+}
OpenPOWER on IntegriCloud