Back to index

glibc  2.9
makecontext.c
Go to the documentation of this file.
00001 /* Create new context.
00002    Copyright (C) 2008 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by David S. Miller <davem@davemloft.net>, 2008.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <sysdep.h>
00022 #include <stdarg.h>
00023 #include <stdint.h>
00024 #include <ucontext.h>
00025 
00026 /* Sets up the outgoing arguments and the program counter for a user
00027    context for the requested function call.
00028 
00029    Returning to the correct parent context is pretty simple on
00030    Sparc.  We only need to link up the register windows correctly.
00031    Since global registers are clobbered by calls, we need not be
00032    concernred about those, and thus is all could be worked out without
00033    using a trampoline.
00034 
00035    Except that we must deal with the signal mask, thus a trampoline
00036    is unavoidable. 32-bit stackframe layout:
00037              +-----------------------------------------+
00038              | 7th and further parameters        |
00039              +-----------------------------------------+
00040              | backup storage for initial 6 parameters |
00041              +-----------------------------------------+
00042              | struct return pointer                    |
00043              +-----------------------------------------+
00044              | 8 incoming registers                     |
00045              +-----------------------------------------+
00046              | 8 local registers                 |
00047      %sp -->  +-----------------------------------------+
00048 
00049 */
00050 
00051 void
00052 __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
00053 {
00054   extern void __start_context (void);
00055   unsigned long int *sp;
00056   va_list ap;
00057   int i;
00058 
00059   sp = (unsigned long int *) (ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
00060   sp -= 16 + 7 + argc;
00061   sp = (unsigned long int *) (((uintptr_t) sp) & ~(8 - 1));
00062 
00063   for (i = 0; i < 8; i++)
00064     sp[i + 8] = ucp->uc_mcontext.gregs[REG_O0 + i];
00065 
00066   /* The struct return pointer is essentially unused, so we can
00067      place the link there.  */
00068   sp[16] = (unsigned long int) ucp->uc_link;
00069 
00070   va_start (ap, argc);
00071 
00072   /* Fill in outgoing arguments, including those which will
00073      end up being passed on the stack.  */
00074   for (i = 0; i < argc; i++)
00075     {
00076       unsigned long int arg = va_arg (ap, unsigned long int);
00077       if (i < 6)
00078        ucp->uc_mcontext.gregs[REG_O0 + i] = arg;
00079       else
00080        sp[i + 23] = arg;
00081     }
00082 
00083   va_end (ap);
00084 
00085   ucp->uc_mcontext.gregs[REG_O6] = (unsigned long int) sp;
00086 
00087   ucp->uc_mcontext.gregs[REG_O7] = ((unsigned long int) __start_context) - 8;
00088 
00089   ucp->uc_mcontext.gregs[REG_PC] = (unsigned long int) func;
00090   ucp->uc_mcontext.gregs[REG_nPC] = ucp->uc_mcontext.gregs[REG_PC] + 4;
00091 }
00092 
00093 weak_alias (__makecontext, makecontext)