Back to index

glibc  2.9
tst-context1.c
Go to the documentation of this file.
00001 /* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <error.h>
00022 #include <limits.h>
00023 #include <pthread.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <ucontext.h>
00027 
00028 #define N     4
00029 #if __WORDSIZE == 64
00030 #define GUARD_PATTERN 0xdeadbeafdeadbeaf
00031 #else
00032 #define GUARD_PATTERN 0xdeadbeaf
00033 #endif
00034 
00035 typedef struct {
00036        ucontext_t uctx;
00037        unsigned long guard[3];
00038    } tst_context_t;
00039 
00040 static char stacks[N][2 * PTHREAD_STACK_MIN];
00041 static tst_context_t ctx[N][2];
00042 static volatile int failures;
00043 
00044 
00045 static void
00046 fct (long int n)
00047 {
00048   char on_stack[1];
00049 
00050   /* Just to use the thread local descriptor.  */
00051   printf ("%ld: in %s now, on_stack = %p\n", n, __FUNCTION__, on_stack);
00052   errno = 0;
00053 
00054   if (ctx[n][1].uctx.uc_link != &ctx[n][0].uctx)
00055     {
00056       printf ("context[%ld][1] uc_link damaged, = %p\n", n,
00057              ctx[n][1].uctx.uc_link);
00058       exit (1);
00059     }
00060 
00061   if ((ctx[n][0].guard[0] != GUARD_PATTERN)
00062   ||  (ctx[n][0].guard[1] != GUARD_PATTERN)
00063   ||  (ctx[n][0].guard[2] != GUARD_PATTERN))
00064     {
00065       printf ("%ld: %s context[0] overflow detected!\n", n, __FUNCTION__);
00066       ++failures;
00067     }
00068 
00069   if ((ctx[n][1].guard[0] != GUARD_PATTERN)
00070   ||  (ctx[n][1].guard[1] != GUARD_PATTERN)
00071   ||  (ctx[n][1].guard[2] != GUARD_PATTERN))
00072     {
00073       printf ("%ld: %s context[1] overflow detected!\n", n, __FUNCTION__);
00074       ++failures;
00075     }
00076 
00077   if (n < 0 || n >= N)
00078     {
00079       printf ("%ld out of range\n", n);
00080       exit (1);
00081     }
00082 
00083   if (on_stack < stacks[n] || on_stack >= stacks[n] + sizeof (stacks[0]))
00084     {
00085       printf ("%ld: on_stack not on appropriate stack\n", n);
00086       exit (1);
00087     }
00088 }
00089 
00090 
00091 static void *
00092 tf (void *arg)
00093 {
00094   int n = (int) (long int) arg;
00095 
00096   ctx[n][0].guard[0] = GUARD_PATTERN;
00097   ctx[n][0].guard[1] = GUARD_PATTERN;
00098   ctx[n][0].guard[2] = GUARD_PATTERN;
00099 
00100   ctx[n][1].guard[0] = GUARD_PATTERN;
00101   ctx[n][1].guard[1] = GUARD_PATTERN;
00102   ctx[n][1].guard[2] = GUARD_PATTERN;
00103 
00104   if (getcontext (&ctx[n][1].uctx) != 0)
00105     {
00106       printf ("%d: cannot get context: %m\n", n);
00107       exit (1);
00108     }
00109 
00110   printf ("%d: %s: before makecontext\n", n, __FUNCTION__);
00111 
00112   ctx[n][1].uctx.uc_stack.ss_sp = stacks[n];
00113   ctx[n][1].uctx.uc_stack.ss_size = sizeof (stacks[n]);
00114   ctx[n][1].uctx.uc_link = &ctx[n][0].uctx;
00115   makecontext (&ctx[n][1].uctx, (void (*) (void)) fct, 1, (long int) n);
00116 
00117   printf ("%d: %s: before swapcontext\n", n, __FUNCTION__);
00118 
00119   if (swapcontext (&ctx[n][0].uctx, &ctx[n][1].uctx) != 0)
00120     {
00121       ++failures;
00122       printf ("%d: %s: swapcontext failed\n", n, __FUNCTION__);
00123     }
00124   else
00125     printf ("%d: back in %s\n", n, __FUNCTION__);
00126 
00127   return NULL;
00128 }
00129 
00130 
00131 static volatile int global;
00132 
00133 
00134 static int
00135 do_test (void)
00136 {
00137   int n;
00138   pthread_t th[N];
00139   ucontext_t mctx;
00140 
00141   puts ("making contexts");
00142   if (getcontext (&mctx) != 0)
00143     {
00144       if (errno == ENOSYS)
00145        {
00146          puts ("context handling not supported");
00147          exit (0);
00148        }
00149 
00150       printf ("%s: getcontext: %m\n", __FUNCTION__);
00151       exit (1);
00152     }
00153 
00154   /* Play some tricks with this context.  */
00155   if (++global == 1)
00156     if (setcontext (&mctx) != 0)
00157       {
00158        puts ("setcontext failed");
00159        exit (1);
00160       }
00161   if (global != 2)
00162     {
00163       puts ("global not incremented twice");
00164       exit (1);
00165     }
00166   puts ("global OK");
00167 
00168   pthread_attr_t at;
00169 
00170   if (pthread_attr_init (&at) != 0)
00171     {
00172       puts ("attr_init failed");
00173       return 1;
00174     }
00175 
00176   if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
00177     {
00178       puts ("attr_setstacksize failed");
00179       return 1;
00180     }
00181 
00182   for (n = 0; n < N; ++n)
00183     if (pthread_create (&th[n], &at, tf, (void *) (long int) n) != 0)
00184       {
00185        puts ("create failed");
00186        exit (1);
00187       }
00188 
00189   if (pthread_attr_destroy (&at) != 0)
00190     {
00191       puts ("attr_destroy failed");
00192       return 1;
00193     }
00194 
00195   for (n = 0; n < N; ++n)
00196     if (pthread_join (th[n], NULL) != 0)
00197       {
00198        puts ("join failed");
00199        exit (1);
00200       }
00201 
00202   return failures;
00203 }
00204 
00205 #define TEST_FUNCTION do_test ()
00206 #include "../test-skeleton.c"