(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
hppa/
makecontext.c
       1  /* Create new context.
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       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     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <libintl.h>
      20  #include <stdarg.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <sysdep.h>
      24  #include <ucontext.h>
      25  
      26  /* POSIX only supports integer arguments.  */
      27  
      28  /* Stack must be 64-byte aligned at all times.  */
      29  #define STACK_ALIGN 64
      30  /* Size of frame marker in unsigned long words.  */
      31  #define FRAME_SIZE_UL 8
      32  /* Size of frame marker in bytes.  */
      33  #define FRAME_SIZE_BYTES (8 * sizeof (unsigned long))
      34  /* Size of X arguments in bytes.  */
      35  #define ARGS(x) (x * sizeof (unsigned long))
      36  
      37  void
      38  __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
      39  {
      40    unsigned long *sp, *osp;
      41    va_list ap;
      42    int i;
      43  
      44    /* Create a 64-byte aligned frame to store args. Use ss_sp if
      45       it is available, otherwise be robust and use the currently
      46       saved stack pointer.  */
      47    if (ucp->uc_stack.ss_sp && ucp->uc_stack.ss_size)
      48      osp = (unsigned long *)ucp->uc_stack.ss_sp;
      49    else
      50      osp = (unsigned long *)ucp->uc_mcontext.sc_gr[30];
      51  
      52    sp = (unsigned long *)((((unsigned long) osp)
      53  			   + FRAME_SIZE_BYTES + ARGS(argc) + STACK_ALIGN)
      54  			 & ~(STACK_ALIGN - 1));
      55  
      56    /* Use new frame.  */
      57    ucp->uc_mcontext.sc_gr[30] = ((unsigned long) sp);
      58  
      59    /* Finish frame setup.  */
      60    if (ucp->uc_link)
      61      {
      62        /* Returning to the next context and next frame.  */
      63        sp[-4 / sizeof (unsigned long)] = ucp->uc_link->uc_mcontext.sc_gr[30];
      64        sp[-20 / sizeof (unsigned long)] = ucp->uc_link->uc_mcontext.sc_gr[2];
      65      }
      66    else
      67      {
      68        /* This is the main context. No frame marker, and no return address.  */
      69        sp[-4 / sizeof (unsigned long)] = 0x0;
      70        sp[-20 / sizeof (unsigned long)] = 0x0;
      71      }
      72  
      73    /* Store address to jump to.  */
      74    ucp->uc_mcontext.sc_gr[2] = (unsigned long) func;
      75  
      76    /* Process arguments.  */
      77    va_start (ap, argc);
      78    for (i = 0; i < argc; ++i)
      79      {
      80        if (i < 4)
      81  	{
      82  	  ucp->uc_mcontext.sc_gr[26-i] = va_arg (ap, int);
      83  	  continue;
      84  	}
      85  
      86        if ((i < 8) && (sizeof (unsigned long) == 8))
      87  	{
      88  	  /* 64bit: r19-r22 are arg7-arg4.  */
      89  	  ucp->uc_mcontext.sc_gr[22+4-i] = va_arg (ap, int);
      90  	  continue;
      91  	}
      92  
      93        /* All other arguments go on the stack.  */
      94        sp[-1 * (FRAME_SIZE_UL + 1 + i)] = va_arg (ap, int);
      95      }
      96    va_end (ap);
      97  }
      98  weak_alias(__makecontext, makecontext)