chiark / gitweb /
Apply https://sourceware.org/git/?p=glibc.git;a=commit;h=d5dd6189d506068ed11c8bfa1e1e...
[eglibc.git] / linuxthreads / tst-context.c
1 /* Ack, a hack!  We need to get the proper definition, or lack thereof,
2    for FLOATING_STACKS.  But when !IS_IN_libpthread, this can get defined
3    incidentally by <tls.h>.  So kludge around it.  */
4
5 #define IS_IN_libpthread
6 #include <tls.h>
7 #undef IS_IN_libpthread
8 #undef USE___THREAD
9
10 #include <errno.h>
11 #include <error.h>
12 #include <pthread.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <ucontext.h>
16
17
18 #define N       4
19
20 #ifdef FLOATING_STACKS
21 static char stacks[N][8192];
22 static ucontext_t ctx[N][2];
23 static volatile int failures;
24
25 static void
26 fct (long int n)
27 {
28   /* Just to use the thread local descriptor.  */
29   printf ("%ld: in %s now\n", n, __FUNCTION__);
30   errno = 0;
31 }
32
33 static void *
34 threadfct (void *arg)
35 {
36   int n = (int) (long int) arg;
37
38   if (getcontext (&ctx[n][1]) != 0)
39     {
40       printf ("%d: cannot get context: %m\n", n);
41       exit (1);
42     }
43
44   printf ("%d: %s: before makecontext\n", n, __FUNCTION__);
45
46   ctx[n][1].uc_stack.ss_sp = stacks[n];
47   ctx[n][1].uc_stack.ss_size = 8192;
48   ctx[n][1].uc_link = &ctx[n][0];
49   makecontext (&ctx[n][1], (void (*) (void)) fct, 1, (long int) n);
50
51   printf ("%d: %s: before swapcontext\n", n, __FUNCTION__);
52
53   if (swapcontext (&ctx[n][0], &ctx[n][1]) != 0)
54     {
55       ++failures;
56       printf ("%d: %s: swapcontext failed\n", n, __FUNCTION__);
57     }
58   else
59     printf ("%d: back in %s\n", n, __FUNCTION__);
60
61   return NULL;
62 }
63 #endif
64
65
66 #ifdef FLOATING_STACKS
67 static volatile int global;
68 #endif
69
70 int
71 main (void)
72 {
73 #ifndef FLOATING_STACKS
74   puts ("not supported");
75   return 0;
76 #else
77   int n;
78   pthread_t th[N];
79   ucontext_t mctx;
80
81   puts ("making contexts");
82   if (getcontext (&mctx) != 0)
83     {
84       if (errno == ENOSYS)
85         {
86           puts ("context handling not supported");
87           exit (0);
88         }
89
90       printf ("%s: getcontext: %m\n", __FUNCTION__);
91       exit (1);
92     }
93
94   /* Play some tricks with this context.  */
95   if (++global == 1)
96     if (setcontext (&mctx) != 0)
97       {
98         printf ("%s: setcontext: %m\n", __FUNCTION__);
99         exit (1);
100       }
101   if (global != 2)
102     {
103       printf ("%s: 'global' not incremented twice\n", __FUNCTION__);
104       exit (1);
105     }
106
107   for (n = 0; n < N; ++n)
108     if (pthread_create (&th[n], NULL, threadfct, (void *) (long int) n) != 0)
109       error (EXIT_FAILURE, errno, "cannot create all threads");
110
111   for (n = 0; n < N; ++n)
112     pthread_join (th[n], NULL);
113
114   return failures;
115 #endif
116 }