diff options
Diffstat (limited to 'REORG.TODO/sysdeps/unix/sysv/linux/s390/s390-64/makecontext.c')
-rw-r--r-- | REORG.TODO/sysdeps/unix/sysv/linux/s390/s390-64/makecontext.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/REORG.TODO/sysdeps/unix/sysv/linux/s390/s390-64/makecontext.c b/REORG.TODO/sysdeps/unix/sysv/linux/s390/s390-64/makecontext.c new file mode 100644 index 0000000000..01ba5255f6 --- /dev/null +++ b/REORG.TODO/sysdeps/unix/sysv/linux/s390/s390-64/makecontext.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2001-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + The GNU C 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.1 of the License, or (at your option) any later version. + + The GNU C 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 the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <libintl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <ucontext.h> + +/* This implementation can handle any ARGC value but only + normal integer type parameters. Parameters of type float, + double, complex and structure with sizes 0, 2, 4 or 8 + won't work. + makecontext sets up a stack and the registers for the + user context. The stack looks like this: + size offset + %r15 -> +-----------------------+ + 8 | back chain (zero) | 0 + 8 | reserved | 8 + 144 | save area for (*func) | 16 + +-----------------------+ + n | overflow parameters | 160 + +-----------------------+ + The registers are set up like this: + %r2-%r6: parameters 1 to 5 + %r7 : (*func) pointer + %r8 : uc_link from ucontext structure + %r9 : address of setcontext + %r14 : return address to uc_link trampoline + %r15 : stack pointer. + + The trampoline looks like this: + basr %r14,%r7 + lgr %r2,%r8 + br %r9. */ + +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) +{ + extern void __makecontext_ret (void); + unsigned long int *sp; + va_list ap; + + sp = (unsigned long int *) (((unsigned long int) ucp->uc_stack.ss_sp + + ucp->uc_stack.ss_size) & -8L); + + /* Set the return address to trampoline. */ + ucp->uc_mcontext.gregs[14] = (long int) __makecontext_ret; + + /* Set register parameters. */ + va_start (ap, argc); + for (int i = 0; i < argc && i < 5; ++i) + ucp->uc_mcontext.gregs[2 + i] = va_arg (ap, long int); + + /* The remaining arguments go to the overflow area. */ + if (argc > 5) + { + sp -= argc - 5; + for (int i = 5; i < argc; ++i) + sp[i - 5] = va_arg (ap, long int); + } + va_end (ap); + + /* Make room for the save area and set the backchain. */ + sp -= 20; + *sp = 0; + + /* Pass (*func) to __makecontext_ret in %r7. */ + ucp->uc_mcontext.gregs[7] = (long int) func; + + /* Pass ucp->uc_link to __makecontext_ret in %r8. */ + ucp->uc_mcontext.gregs[8] = (long int) ucp->uc_link; + + /* Pass address of setcontext in %r9. */ + ucp->uc_mcontext.gregs[9] = (long int) &setcontext; + + /* Set stack pointer. */ + ucp->uc_mcontext.gregs[15] = (long int) sp; +} + +weak_alias (__makecontext, makecontext) |