(root)/
glibc-2.38/
stdlib/
tst-makecontext3.c
       1  /* Copyright (C) 2001-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <stdio.h>
      20  #include <stdlib.h>
      21  #include <string.h>
      22  #include <ucontext.h>
      23  #include <unistd.h>
      24  
      25  static ucontext_t ctx[3];
      26  
      27  static int was_in_f1;
      28  static int was_in_f2;
      29  
      30  static char st2[32768];
      31  
      32  static volatile int flag;
      33  
      34  static void
      35  f1 (int a00, int a01, int a02, int a03, int a04, int a05, int a06, int a07,
      36      int a08, int a09, int a10, int a11, int a12, int a13, int a14, int a15,
      37      int a16, int a17, int a18, int a19, int a20, int a21, int a22, int a23,
      38      int a24, int a25, int a26, int a27, int a28, int a29, int a30, int a31,
      39      int a32)
      40  {
      41    printf ("start f1(a00=%08x,a01=%08x,a02=%08x,a03=%08x,\n"
      42  	  "         a04=%08x,a05=%08x,a06=%08x,a07=%08x,\n"
      43  	  "         a08=%08x,a09=%08x,a10=%08x,a11=%08x,\n"
      44  	  "         a12=%08x,a13=%08x,a14=%08x,a15=%08x,\n"
      45  	  "         a16=%08x,a17=%08x,a18=%08x,a19=%08x,\n"
      46  	  "         a20=%08x,a21=%08x,a22=%08x,a23=%08x,\n"
      47  	  "         a24=%08x,a25=%08x,a26=%08x,a27=%08x,\n"
      48  	  "         a28=%08x,a29=%08x,a30=%08x,a31=%08x,\n"
      49  	  "         a32=%08x) [%d]\n",
      50  	  a00, a01, a02, a03, a04, a05, a06, a07,
      51  	  a08, a09, a10, a11, a12, a13, a14, a15,
      52  	  a16, a17, a18, a19, a20, a21, a22, a23,
      53  	  a24, a25, a26, a27, a28, a29, a30, a31,
      54  	  a32, flag);
      55  
      56    if (a00 != (0x00000001 << flag) || a01 != (0x00000004 << flag)
      57        || a02 != (0x00000012 << flag) || a03 != (0x00000048 << flag)
      58        || a04 != (0x00000123 << flag) || a05 != (0x0000048d << flag)
      59        || a06 != (0x00001234 << flag) || a07 != (0x000048d1 << flag)
      60        || a08 != (0x00012345 << flag) || a09 != (0x00048d15 << flag)
      61        || a10 != (0x00123456 << flag) || a11 != (0x0048d159 << flag)
      62        || a12 != (0x01234567 << flag) || a13 != (0x048d159e << flag)
      63        || a14 != (0x12345678 << flag) || a15 != (0x48d159e2 << flag)
      64        || a16 != (0x23456789 << flag) || a17 != (0x8d159e26 << flag)
      65        || a18 != (0x3456789a << flag) || a19 != (0xd159e26a << flag)
      66        || a20 != (0x456789ab << flag) || a21 != (0x159e26af << flag)
      67        || a22 != (0x56789abc << flag) || a23 != (0x59e26af3 << flag)
      68        || a24 != (0x6789abcd << flag) || a25 != (0x9e26af37 << flag)
      69        || a26 != (0x789abcde << flag) || a27 != (0xe26af37b << flag)
      70        || a28 != (0x89abcdef << flag) || a29 != (0x26af37bc << flag)
      71        || a30 != (0x9abcdef0 << flag) || a31 != (0x6af37bc3 << flag)
      72        || a32 != (0xabcdef0f << flag))
      73      {
      74        puts ("arg mismatch");
      75        exit (-1);
      76      }
      77  
      78    if (flag && swapcontext (&ctx[1], &ctx[2]) != 0)
      79      {
      80        printf ("%s: swapcontext: %m\n", __FUNCTION__);
      81        exit (1);
      82      }
      83    printf ("finish f1 [%d]\n", flag);
      84    flag++;
      85    was_in_f1++;
      86  }
      87  
      88  static void
      89  f2 (void)
      90  {
      91    puts ("start f2");
      92    if (swapcontext (&ctx[2], &ctx[1]) != 0)
      93      {
      94        printf ("%s: swapcontext: %m\n", __FUNCTION__);
      95        exit (1);
      96      }
      97    puts ("finish f2");
      98    was_in_f2 = 1;
      99  }
     100  
     101  volatile int global;
     102  
     103  
     104  static int back_in_main;
     105  
     106  
     107  static void
     108  check_called (void)
     109  {
     110    if (back_in_main == 0)
     111      {
     112        puts ("program did not reach main again");
     113        _exit (1);
     114      }
     115  }
     116  
     117  
     118  int
     119  main (void)
     120  {
     121    atexit (check_called);
     122  
     123    char st1[32768];
     124  
     125    puts ("making contexts");
     126    if (getcontext (&ctx[0]) != 0)
     127      {
     128        if (errno == ENOSYS)
     129  	{
     130  	  back_in_main = 1;
     131  	  exit (0);
     132  	}
     133  
     134        printf ("%s: getcontext: %m\n", __FUNCTION__);
     135        exit (1);
     136      }
     137  
     138    if (getcontext (&ctx[1]) != 0)
     139      {
     140        printf ("%s: getcontext: %m\n", __FUNCTION__);
     141        exit (1);
     142      }
     143  
     144    ctx[1].uc_stack.ss_sp = st1;
     145    ctx[1].uc_stack.ss_size = sizeof st1;
     146    ctx[1].uc_link = &ctx[0];
     147    errno = 0;
     148    makecontext (&ctx[1], (void (*) (void)) f1, 33,
     149  	       0x00000001 << flag, 0x00000004 << flag,
     150  	       0x00000012 << flag, 0x00000048 << flag,
     151  	       0x00000123 << flag, 0x0000048d << flag,
     152  	       0x00001234 << flag, 0x000048d1 << flag,
     153  	       0x00012345 << flag, 0x00048d15 << flag,
     154  	       0x00123456 << flag, 0x0048d159 << flag,
     155  	       0x01234567 << flag, 0x048d159e << flag,
     156  	       0x12345678 << flag, 0x48d159e2 << flag,
     157  	       0x23456789 << flag, 0x8d159e26 << flag,
     158  	       0x3456789a << flag, 0xd159e26a << flag,
     159  	       0x456789ab << flag, 0x159e26af << flag,
     160  	       0x56789abc << flag, 0x59e26af3 << flag,
     161  	       0x6789abcd << flag, 0x9e26af37 << flag,
     162  	       0x789abcde << flag, 0xe26af37b << flag,
     163  	       0x89abcdef << flag, 0x26af37bc << flag,
     164  	       0x9abcdef0 << flag, 0x6af37bc3 << flag,
     165  	       0xabcdef0f << flag);
     166  
     167    /* Without this check, a stub makecontext can make us spin forever.  */
     168    if (errno == ENOSYS)
     169      {
     170        puts ("makecontext not implemented");
     171        back_in_main = 1;
     172        return 0;
     173      }
     174  
     175    /* Play some tricks with this context.  */
     176    if (++global == 1)
     177      if (setcontext (&ctx[1]) != 0)
     178        {
     179  	printf ("%s: setcontext: %m\n", __FUNCTION__);
     180  	exit (1);
     181        }
     182    if (global != 2)
     183      {
     184        printf ("%s: 'global' not incremented twice\n", __FUNCTION__);
     185        exit (1);
     186      }
     187  
     188    if (getcontext (&ctx[2]) != 0)
     189      {
     190        printf ("%s: second getcontext: %m\n", __FUNCTION__);
     191        exit (1);
     192      }
     193    ctx[2].uc_stack.ss_sp = st2;
     194    ctx[2].uc_stack.ss_size = sizeof st2;
     195    ctx[2].uc_link = &ctx[1];
     196    makecontext (&ctx[2], f2, 0);
     197  
     198    puts ("swapping contexts");
     199    if (swapcontext (&ctx[0], &ctx[2]) != 0)
     200      {
     201        printf ("%s: swapcontext: %m\n", __FUNCTION__);
     202        exit (1);
     203      }
     204    puts ("back at main program");
     205    back_in_main = 1;
     206  
     207    if (was_in_f1 < 2)
     208      {
     209        puts ("didn't reach f1 twice");
     210        exit (1);
     211      }
     212    if (was_in_f2 == 0)
     213      {
     214        puts ("didn't reach f2");
     215        exit (1);
     216      }
     217  
     218    puts ("test succeeded");
     219    return 0;
     220  }