Back to index

glibc  2.9
tst-context.c
Go to the documentation of this file.
00001 /* Ack, a hack!  We need to get the proper definition, or lack thereof,
00002    for FLOATING_STACKS.  But when !IS_IN_libpthread, this can get defined
00003    incidentally by <tls.h>.  So kludge around it.  */
00004 
00005 #define IS_IN_libpthread
00006 #include <tls.h>
00007 #undef IS_IN_libpthread
00008 #undef USE___THREAD
00009 
00010 #include <errno.h>
00011 #include <error.h>
00012 #include <pthread.h>
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <ucontext.h>
00016 
00017 
00018 #define N     4
00019 
00020 #ifdef FLOATING_STACKS
00021 static char stacks[N][8192];
00022 static ucontext_t ctx[N][2];
00023 static volatile int failures;
00024 
00025 static void
00026 fct (long int n)
00027 {
00028   /* Just to use the thread local descriptor.  */
00029   printf ("%ld: in %s now\n", n, __FUNCTION__);
00030   errno = 0;
00031 }
00032 
00033 static void *
00034 threadfct (void *arg)
00035 {
00036   int n = (int) (long int) arg;
00037 
00038   if (getcontext (&ctx[n][1]) != 0)
00039     {
00040       printf ("%d: cannot get context: %m\n", n);
00041       exit (1);
00042     }
00043 
00044   printf ("%d: %s: before makecontext\n", n, __FUNCTION__);
00045 
00046   ctx[n][1].uc_stack.ss_sp = stacks[n];
00047   ctx[n][1].uc_stack.ss_size = 8192;
00048   ctx[n][1].uc_link = &ctx[n][0];
00049   makecontext (&ctx[n][1], (void (*) (void)) fct, 1, (long int) n);
00050 
00051   printf ("%d: %s: before swapcontext\n", n, __FUNCTION__);
00052 
00053   if (swapcontext (&ctx[n][0], &ctx[n][1]) != 0)
00054     {
00055       ++failures;
00056       printf ("%d: %s: swapcontext failed\n", n, __FUNCTION__);
00057     }
00058   else
00059     printf ("%d: back in %s\n", n, __FUNCTION__);
00060 
00061   return NULL;
00062 }
00063 #endif
00064 
00065 
00066 #ifdef FLOATING_STACKS
00067 static volatile int global;
00068 #endif
00069 
00070 int
00071 main (void)
00072 {
00073 #ifndef FLOATING_STACKS
00074   puts ("not supported");
00075   return 0;
00076 #else
00077   int n;
00078   pthread_t th[N];
00079   ucontext_t mctx;
00080 
00081   puts ("making contexts");
00082   if (getcontext (&mctx) != 0)
00083     {
00084       if (errno == ENOSYS)
00085        {
00086          puts ("context handling not supported");
00087          exit (0);
00088        }
00089 
00090       printf ("%s: getcontext: %m\n", __FUNCTION__);
00091       exit (1);
00092     }
00093 
00094   /* Play some tricks with this context.  */
00095   if (++global == 1)
00096     if (setcontext (&mctx) != 0)
00097       {
00098        printf ("%s: setcontext: %m\n", __FUNCTION__);
00099        exit (1);
00100       }
00101   if (global != 2)
00102     {
00103       printf ("%s: 'global' not incremented twice\n", __FUNCTION__);
00104       exit (1);
00105     }
00106 
00107   for (n = 0; n < N; ++n)
00108     if (pthread_create (&th[n], NULL, threadfct, (void *) (long int) n) != 0)
00109       error (EXIT_FAILURE, errno, "cannot create all threads");
00110 
00111   for (n = 0; n < N; ++n)
00112     pthread_join (th[n], NULL);
00113 
00114   return failures;
00115 #endif
00116 }