Back to index

glibc  2.9
makecontext.c
Go to the documentation of this file.
00001 /* Copyright (C) 2001 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <libintl.h>
00021 #include <stdarg.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <ucontext.h>
00025 
00026 /* This implementation can handle any ARGC value but only
00027    normal integer type parameters. Parameters of type float,
00028    double, complex and structure with sizes 0, 2, 4 or 8
00029    won't work.
00030    makecontext sets up a stack and the registers for the
00031    context. The stack looks like this:
00032            size                         offset
00033     %r15 ->    +-----------------------+
00034              4 | back chain (zero)     |  0
00035              4 | reserved              |  4
00036             88 | save area for (*func) |  8
00037                +-----------------------+
00038              n | overflow parameters   | 96
00039                +-----------------------+
00040    The registers are set up like this:
00041      %r2-%r6: parameters 1 to 5
00042      %r7    : (*func) pointer
00043      %r8    : uc_link from ucontext structure
00044      %r9    : address of setcontext
00045      %r14   : return address to uc_link trampoline
00046      %r15   : stack pointer.
00047 
00048    The trampoline looks like this:
00049      basr  %r14,%r7
00050      lr    %r2,%r8
00051      br    %r9.  */
00052 
00053 void
00054 __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
00055 {
00056   extern void __makecontext_ret (void);
00057   unsigned long *sp;
00058   va_list ap;
00059   int i;
00060 
00061   sp = (unsigned long *) (((unsigned long) ucp->uc_stack.ss_sp
00062                         + ucp->uc_stack.ss_size) & -8L);
00063 
00064   /* Set the return address to trampoline.  */
00065   ucp->uc_mcontext.gregs[14] = (long) __makecontext_ret;
00066 
00067   /* Set register parameters.  */
00068   va_start (ap, argc);
00069   for (i = 0; (i < argc) && (i < 5); i++)
00070     ucp->uc_mcontext.gregs[2+i] = va_arg (ap, long);
00071 
00072   /* The remaining arguments go to the overflow area.  */
00073   if (argc > 5) {
00074     sp -= argc - 5;
00075     for (i = 5; i < argc; i++)
00076       sp[i] = va_arg(ap, long);
00077   }
00078   va_end (ap);
00079 
00080   /* Make room for the save area and set the backchain.  */
00081   sp -= 24;
00082   *sp = 0;
00083 
00084   /* Pass (*func) to __start_context in %r7.  */
00085   ucp->uc_mcontext.gregs[7] = (long) func;
00086 
00087   /* Pass ucp->uc_link to __start_context in %r8.  */
00088   ucp->uc_mcontext.gregs[8] = (long) ucp->uc_link;
00089 
00090   /* Pass address of setcontext in %r9.  */
00091   ucp->uc_mcontext.gregs[9] = (long) &setcontext;
00092 
00093   /* Set stack pointer.  */
00094   ucp->uc_mcontext.gregs[15] = (long) sp;
00095 }
00096 
00097 asm(".text\n"
00098     ".type __makecontext_ret,@function\n"
00099     "__makecontext_ret:\n"
00100     "      basr  %r14,%r7\n"
00101     "      lr    %r2,%r8\n"
00102     "      br    %r9\n"
00103     ".size __makecontext_ret, .-__makecontext_ret");
00104 
00105 weak_alias (__makecontext, makecontext)