(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
split-5.c
       1  /* { dg-do run } */
       2  /* { dg-require-effective-target split_stack } */
       3  /* { dg-require-effective-target pthread_h } */
       4  /* { dg-require-effective-target ucontext_h } */
       5  /* { dg-options "-pthread -fsplit-stack" } */
       6  
       7  #include <stdlib.h>
       8  #include <pthread.h>
       9  #include <ucontext.h>
      10  
      11  extern void __splitstack_getcontext (void *context[10]);
      12  
      13  extern void __splitstack_setcontext (void *context[10]);
      14  
      15  extern void *__splitstack_makecontext (size_t, void *context[10], size_t *);
      16  
      17  extern void __splitstack_block_signals (int *, int *);
      18  
      19  extern void __splitstack_block_signals_context (void *context[10], int *,
      20  						int *);
      21  
      22  extern void *__splitstack_find (void *, void *, size_t *, void **, void **,
      23  				void **);
      24  
      25  extern void *__splitstack_find_context (void *context[10], size_t *, void **,
      26  					void **, void **);
      27  
      28  static ucontext_t c1;
      29  static void *s1[10];
      30  
      31  static ucontext_t c2;
      32  static void *s2[10];
      33  
      34  static void swap (ucontext_t *, void *fs[10], ucontext_t *, void *ts[10])
      35    __attribute__ ((no_split_stack));
      36  
      37  static void
      38  swap (ucontext_t *fu, void *fs[10], ucontext_t *tu, void *ts[10])
      39  {
      40    __splitstack_getcontext (fs);
      41    __splitstack_setcontext (ts);
      42    swapcontext (fu, tu);
      43    __splitstack_setcontext (fs);
      44  }
      45  
      46  /* Use a noinline function to ensure that the buffer is not removed
      47     from the stack.  */
      48  static void use_buffer (char *buf) __attribute__ ((noinline));
      49  static void
      50  use_buffer (char *buf)
      51  {
      52    buf[0] = '\0';
      53  }
      54  
      55  static void
      56  down (int i, const char *msg, ucontext_t *me, void *mes[10],
      57        ucontext_t *other, void *others[10])
      58  {
      59    char buf[10000];
      60  
      61    if (i > 0)
      62      {
      63        use_buffer (buf);
      64        swap (me, mes, other, others);
      65        down (i - 1, msg, me, mes, other, others);
      66      }
      67    else
      68      {
      69        int c = 0;
      70        void *stack;
      71        size_t stack_size;
      72        void *next_segment = NULL;
      73        void *next_sp = NULL;
      74        void *initial_sp = NULL;
      75  
      76        stack = __splitstack_find_context (mes, &stack_size, &next_segment,
      77  					&next_sp, &initial_sp);
      78        if (stack != NULL)
      79  	{
      80  	  ++c;
      81  	  while (__splitstack_find (next_segment, next_sp, &stack_size,
      82  				    &next_segment, &next_sp, &initial_sp)
      83  		 != NULL)
      84  	    ++c;
      85  	}
      86      }
      87  }
      88  
      89  static void
      90  go1 (void)
      91  {
      92    down (1000, "go1", &c1, s1, &c2, s2);
      93    pthread_exit (NULL);
      94  }
      95  
      96  static void
      97  go2 (void)
      98  {
      99    down (1000, "go2", &c2, s2, &c1, s1);
     100    pthread_exit (NULL);
     101  }
     102  
     103  struct thread_context
     104  {
     105    ucontext_t *u;
     106    void **s;
     107  };
     108  
     109  static void *start_thread (void *) __attribute__ ((no_split_stack));
     110  
     111  static void *
     112  start_thread (void *context)
     113  {
     114    struct thread_context *tc = (struct thread_context *) context;
     115    int block;
     116  
     117    block = 0;
     118    __splitstack_block_signals (&block, NULL);
     119    __splitstack_setcontext (tc->s);
     120    setcontext (tc->u);
     121    abort ();
     122  }
     123  
     124  int
     125  main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
     126  {
     127    pthread_t tid;
     128    int err;
     129    size_t size;
     130    struct thread_context tc;
     131    int block;
     132  
     133    if (getcontext (&c1) < 0)
     134      abort ();
     135  
     136    c2 = c1;
     137  
     138    c1.uc_stack.ss_sp = __splitstack_makecontext (8192, &s1[0], &size);
     139    if (c1.uc_stack.ss_sp == NULL)
     140      abort ();
     141    c1.uc_stack.ss_flags = 0;
     142    c1.uc_stack.ss_size = size;
     143    c1.uc_link = NULL;
     144    block = 0;
     145    __splitstack_block_signals_context (&s1[0], &block, NULL);
     146    makecontext (&c1, go1, 0);
     147  
     148    c2.uc_stack.ss_sp = __splitstack_makecontext (8192, &s2[0], &size);
     149    if (c2.uc_stack.ss_sp == NULL)
     150      abort ();
     151    c2.uc_stack.ss_flags = 0;
     152    c2.uc_stack.ss_size = size;
     153    c2.uc_link = NULL;
     154    __splitstack_block_signals_context (&s2[0], &block, NULL);
     155    makecontext (&c2, go2, 0);
     156  
     157    block = 0;
     158    __splitstack_block_signals (&block, NULL);
     159  
     160    tc.u = &c1;
     161    tc.s = &s1[0];
     162    err = pthread_create (&tid, NULL, start_thread, &tc);
     163    if (err != 0)
     164      abort ();
     165  
     166    err = pthread_join (tid, NULL);
     167    if (err != 0)
     168      abort ();
     169  
     170    return 0;
     171  }