Update copyright notices with scripts/update-copyrights.
[jlayton/glibc.git] / sysdeps / unix / sysv / linux / s390 / s390-64 / makecontext.c
1 /* Copyright (C) 2001-2013 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <libintl.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <ucontext.h>
24
25 /* This implementation can handle any ARGC value but only
26    normal integer type parameters. Parameters of type float,
27    double, complex and structure with sizes 0, 2, 4 or 8
28    won't work.
29    makecontext sets up a stack and the registers for the
30    user context. The stack looks like this:
31            size                         offset
32     %r15 ->    +-----------------------+
33              8 | back chain (zero)     |  0
34              8 | reserved              |  8
35            144 | save area for (*func) | 16
36                +-----------------------+
37              n | overflow parameters   | 160
38                +-----------------------+
39    The registers are set up like this:
40      %r2-%r6: parameters 1 to 5
41      %r7    : (*func) pointer
42      %r8    : uc_link from ucontext structure
43      %r9    : address of setcontext
44      %r14   : return address to uc_link trampoline
45      %r15   : stack pointer.
46
47    The trampoline looks like this:
48      basr  %r14,%r7
49      lgr   %r2,%r8
50      br    %r9.  */
51
52 void
53 __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
54 {
55   extern void __makecontext_ret (void);
56   unsigned long int *sp;
57   va_list ap;
58
59   sp = (unsigned long int *) (((unsigned long int) ucp->uc_stack.ss_sp
60                                + ucp->uc_stack.ss_size) & -8L);
61
62   /* Set the return address to trampoline.  */
63   ucp->uc_mcontext.gregs[14] = (long int) __makecontext_ret;
64
65   /* Set register parameters.  */
66   va_start (ap, argc);
67   for (int i = 0; i < argc && i < 5; ++i)
68     ucp->uc_mcontext.gregs[2 + i] = va_arg (ap, long int);
69
70   /* The remaining arguments go to the overflow area.  */
71   if (argc > 5)
72     {
73       sp -= argc - 5;
74       for (int i = 5; i < argc; ++i)
75         sp[i - 5] = va_arg (ap, long int);
76     }
77   va_end (ap);
78
79   /* Make room for the save area and set the backchain.  */
80   sp -= 20;
81   *sp = 0;
82
83   /* Pass (*func) to __makecontext_ret in %r7.  */
84   ucp->uc_mcontext.gregs[7] = (long int) func;
85
86   /* Pass ucp->uc_link to __makecontext_ret in %r8.  */
87   ucp->uc_mcontext.gregs[8] = (long int) ucp->uc_link;
88
89   /* Pass address of setcontext in %r9.  */
90   ucp->uc_mcontext.gregs[9] = (long int) &setcontext;
91
92   /* Set stack pointer.  */
93   ucp->uc_mcontext.gregs[15] = (long int) sp;
94 }
95
96 weak_alias (__makecontext, makecontext)