19848690cfe9c59a8a92d4be6e5b43c77786066eephilippe#include <config.h>
29848690cfe9c59a8a92d4be6e5b43c77786066eephilippe#include <pthread.h>
39848690cfe9c59a8a92d4be6e5b43c77786066eephilippe#include <stdio.h>
49848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
59848690cfe9c59a8a92d4be6e5b43c77786066eephilippe#ifdef HAVE_TLS
69848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
79848690cfe9c59a8a92d4be6e5b43c77786066eephilippestatic int only_touch_stackvar;
89848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
99848690cfe9c59a8a92d4be6e5b43c77786066eephilippe/* We should have no error on local and global
109848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   as these are both thread local variables. */
119848690cfe9c59a8a92d4be6e5b43c77786066eephilippestatic __thread int local;
129848690cfe9c59a8a92d4be6e5b43c77786066eephilippe__thread int global;
139848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
149848690cfe9c59a8a92d4be6e5b43c77786066eephilippe/* We will wrongly share this variable indirectly  through a pointer
159848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   We should have an error for this. */
169848690cfe9c59a8a92d4be6e5b43c77786066eephilippestatic __thread int badly_shared_local;
179848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
189848690cfe9c59a8a92d4be6e5b43c77786066eephilippe/* ptr_to_badly_shared_local allows to have multiple threads seeing
199848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   the same thread local storage. This is however really bad sharing
209848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   as this can cause SEGV or whatever, as when the thread disappears,
219848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   the badly_shared_local var pointed to can also disappear.
229848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   By default, the regtest does not test this really bad sharing. */
239848690cfe9c59a8a92d4be6e5b43c77786066eephilippepthread_mutex_t protect_ptr_to_badly_shared_local = PTHREAD_MUTEX_INITIALIZER;
249848690cfe9c59a8a92d4be6e5b43c77786066eephilippeint *ptr_to_badly_shared_local;
259848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
269848690cfe9c59a8a92d4be6e5b43c77786066eephilippestatic void local_false_positive(void)
279848690cfe9c59a8a92d4be6e5b43c77786066eephilippe{
289848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   local = local + 1; // no error is expected
299848690cfe9c59a8a92d4be6e5b43c77786066eephilippe}
309848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
319848690cfe9c59a8a92d4be6e5b43c77786066eephilippestatic void global_false_positive(void)
329848690cfe9c59a8a92d4be6e5b43c77786066eephilippe{
339848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   global = global + 1; // no error is expected
349848690cfe9c59a8a92d4be6e5b43c77786066eephilippe}
359848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
369848690cfe9c59a8a92d4be6e5b43c77786066eephilippestatic void badly_shared_local_error_expected(void)
379848690cfe9c59a8a92d4be6e5b43c77786066eephilippe{
389848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   *ptr_to_badly_shared_local = *ptr_to_badly_shared_local + 1; // an error is expected
399848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   // This can cause a SIGSEGV.
409848690cfe9c59a8a92d4be6e5b43c77786066eephilippe}
419848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
429848690cfe9c59a8a92d4be6e5b43c77786066eephilippestatic void *level2(void *p)
439848690cfe9c59a8a92d4be6e5b43c77786066eephilippe{
449848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   int stackvar = 0;
459848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
469848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   stackvar = stackvar + only_touch_stackvar;
479848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
489848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   local_false_positive();
499848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   global_false_positive();
509848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   if (only_touch_stackvar != 0) {
519848690cfe9c59a8a92d4be6e5b43c77786066eephilippe      badly_shared_local_error_expected();
529848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   }
539848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   return 0;
549848690cfe9c59a8a92d4be6e5b43c77786066eephilippe}
559848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
569848690cfe9c59a8a92d4be6e5b43c77786066eephilippe#define NLEVEL2 10
579848690cfe9c59a8a92d4be6e5b43c77786066eephilippestatic void *level1(void *p)
589848690cfe9c59a8a92d4be6e5b43c77786066eephilippe{
599848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   pthread_t threads[NLEVEL2];
609848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   int curthread = 0;
619848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   int i;
629848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
639848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   pthread_mutex_lock(&protect_ptr_to_badly_shared_local);
649848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   if (ptr_to_badly_shared_local == NULL)
659848690cfe9c59a8a92d4be6e5b43c77786066eephilippe      ptr_to_badly_shared_local = &badly_shared_local;
669848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   pthread_mutex_unlock(&protect_ptr_to_badly_shared_local);
679848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
689848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   for(i = 0; i < NLEVEL2; i++) {
699848690cfe9c59a8a92d4be6e5b43c77786066eephilippe      pthread_create(&threads[curthread++], NULL, level2, NULL);
709848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   }
719848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
729848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   for(i = 0; i < curthread; i++)
739848690cfe9c59a8a92d4be6e5b43c77786066eephilippe      pthread_join(threads[i], NULL);
749848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
759848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   return 0;
769848690cfe9c59a8a92d4be6e5b43c77786066eephilippe}
779848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
789848690cfe9c59a8a92d4be6e5b43c77786066eephilippe#define NLEVEL1 3
799848690cfe9c59a8a92d4be6e5b43c77786066eephilippeint main(int argc, char*argv[])
809848690cfe9c59a8a92d4be6e5b43c77786066eephilippe{
819848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   pthread_t threads[NLEVEL1];
829848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   int curthread = 0;
839848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   int i;
849848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
859848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   only_touch_stackvar = argc > 1;
869848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
879848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   for(i = 0; i < NLEVEL1; i++) {
889848690cfe9c59a8a92d4be6e5b43c77786066eephilippe      pthread_create(&threads[curthread++], NULL, level1, NULL);
899848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   }
909848690cfe9c59a8a92d4be6e5b43c77786066eephilippe
919848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   fprintf(stderr, "starting join in main\n");
929848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   fflush(stderr);
939848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   for(i = 0; i < curthread; i++)
949848690cfe9c59a8a92d4be6e5b43c77786066eephilippe      pthread_join(threads[i], NULL);
959848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   fprintf(stderr, "finished join in main\n");
969848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   fflush(stderr);
979848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   return 0;
989848690cfe9c59a8a92d4be6e5b43c77786066eephilippe}
999848690cfe9c59a8a92d4be6e5b43c77786066eephilippe#else
1009848690cfe9c59a8a92d4be6e5b43c77786066eephilippeint main()
1019848690cfe9c59a8a92d4be6e5b43c77786066eephilippe{
1029848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   fprintf(stderr, "starting join in main\n");
1039848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   fflush(stderr);
1049848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   /* do nothing */
1059848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   fprintf(stderr, "finished join in main\n");
1069848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   fflush(stderr);
1079848690cfe9c59a8a92d4be6e5b43c77786066eephilippe   return 0;
1089848690cfe9c59a8a92d4be6e5b43c77786066eephilippe}
1099848690cfe9c59a8a92d4be6e5b43c77786066eephilippe#endif
110