110 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
	
| #include <errno.h>
 | |
| #include <error.h>
 | |
| #include <pthread.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <ucontext.h>
 | |
| 
 | |
| #include "pt-machine.h"
 | |
| 
 | |
| 
 | |
| #define N	4
 | |
| 
 | |
| #ifdef FLOATING_STACKS
 | |
| static char stacks[N][8192];
 | |
| static ucontext_t ctx[N][2];
 | |
| static volatile int failures;
 | |
| 
 | |
| static void
 | |
| fct (long int n)
 | |
| {
 | |
|   /* Just to use the thread local descriptor.  */
 | |
|   printf ("%ld: in %s now\n", n, __FUNCTION__);
 | |
|   errno = 0;
 | |
| }
 | |
| 
 | |
| static void *
 | |
| threadfct (void *arg)
 | |
| {
 | |
|   int n = (int) (long int) arg;
 | |
| 
 | |
|   if (getcontext (&ctx[n][1]) != 0)
 | |
|     {
 | |
|       printf ("%d: cannot get context: %m\n", n);
 | |
|       exit (1);
 | |
|     }
 | |
| 
 | |
|   printf ("%d: %s: before makecontext\n", n, __FUNCTION__);
 | |
| 
 | |
|   ctx[n][1].uc_stack.ss_sp = stacks[n];
 | |
|   ctx[n][1].uc_stack.ss_size = 8192;
 | |
|   ctx[n][1].uc_link = &ctx[n][0];
 | |
|   makecontext (&ctx[n][1], (void (*) (void)) fct, 1, (long int) n);
 | |
| 
 | |
|   printf ("%d: %s: before swapcontext\n", n, __FUNCTION__);
 | |
| 
 | |
|   if (swapcontext (&ctx[n][0], &ctx[n][1]) != 0)
 | |
|     {
 | |
|       ++failures;
 | |
|       printf ("%d: %s: swapcontext failed\n", n, __FUNCTION__);
 | |
|     }
 | |
|   else
 | |
|     printf ("%d: back in %s\n", n, __FUNCTION__);
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #ifdef FLOATING_STACKS
 | |
| static volatile int global;
 | |
| #endif
 | |
| 
 | |
| int
 | |
| main (void)
 | |
| {
 | |
| #ifndef FLOATING_STACKS
 | |
|   puts ("not supported");
 | |
|   return 0;
 | |
| #else
 | |
|   int n;
 | |
|   pthread_t th[N];
 | |
|   ucontext_t mctx;
 | |
| 
 | |
|   puts ("making contexts");
 | |
|   if (getcontext (&mctx) != 0)
 | |
|     {
 | |
|       if (errno == ENOSYS)
 | |
| 	{
 | |
| 	  puts ("context handling not supported");
 | |
| 	  exit (0);
 | |
| 	}
 | |
| 
 | |
|       printf ("%s: getcontext: %m\n", __FUNCTION__);
 | |
|       exit (1);
 | |
|     }
 | |
| 
 | |
|   /* Play some tricks with this context.  */
 | |
|   if (++global == 1)
 | |
|     if (setcontext (&mctx) != 0)
 | |
|       {
 | |
| 	printf ("%s: setcontext: %m\n", __FUNCTION__);
 | |
| 	exit (1);
 | |
|       }
 | |
|   if (global != 2)
 | |
|     {
 | |
|       printf ("%s: 'global' not incremented twice\n", __FUNCTION__);
 | |
|       exit (1);
 | |
|     }
 | |
| 
 | |
|   for (n = 0; n < N; ++n)
 | |
|     if (pthread_create (&th[n], NULL, threadfct, (void *) n) != 0)
 | |
|       error (EXIT_FAILURE, errno, "cannot create all threads");
 | |
| 
 | |
|   for (n = 0; n < N; ++n)
 | |
|     pthread_join (th[n], NULL);
 | |
| 
 | |
|   return failures;
 | |
| #endif
 | |
| }
 |