Home | History | Annotate | Download | only in tests
      1 #include <config.h>
      2 #include <pthread.h>
      3 #include <stdio.h>
      4 
      5 #ifdef HAVE_TLS
      6 
      7 static int only_touch_stackvar;
      8 
      9 /* We should have no error on local and global
     10    as these are both thread local variables. */
     11 static __thread int local;
     12 __thread int global;
     13 
     14 /* We will wrongly share this variable indirectly  through a pointer
     15    We should have an error for this. */
     16 static __thread int badly_shared_local;
     17 
     18 /* ptr_to_badly_shared_local allows to have multiple threads seeing
     19    the same thread local storage. This is however really bad sharing
     20    as this can cause SEGV or whatever, as when the thread disappears,
     21    the badly_shared_local var pointed to can also disappear.
     22    By default, the regtest does not test this really bad sharing. */
     23 pthread_mutex_t protect_ptr_to_badly_shared_local = PTHREAD_MUTEX_INITIALIZER;
     24 int *ptr_to_badly_shared_local;
     25 
     26 static void local_false_positive(void)
     27 {
     28    local = local + 1; // no error is expected
     29 }
     30 
     31 static void global_false_positive(void)
     32 {
     33    global = global + 1; // no error is expected
     34 }
     35 
     36 static void badly_shared_local_error_expected(void)
     37 {
     38    *ptr_to_badly_shared_local = *ptr_to_badly_shared_local + 1; // an error is expected
     39    // This can cause a SIGSEGV.
     40 }
     41 
     42 static void *level2(void *p)
     43 {
     44    int stackvar = 0;
     45 
     46    stackvar = stackvar + only_touch_stackvar;
     47 
     48    local_false_positive();
     49    global_false_positive();
     50    if (only_touch_stackvar != 0) {
     51       badly_shared_local_error_expected();
     52    }
     53    return 0;
     54 }
     55 
     56 #define NLEVEL2 10
     57 static void *level1(void *p)
     58 {
     59    pthread_t threads[NLEVEL2];
     60    int curthread = 0;
     61    int i;
     62 
     63    pthread_mutex_lock(&protect_ptr_to_badly_shared_local);
     64    if (ptr_to_badly_shared_local == NULL)
     65       ptr_to_badly_shared_local = &badly_shared_local;
     66    pthread_mutex_unlock(&protect_ptr_to_badly_shared_local);
     67 
     68    for(i = 0; i < NLEVEL2; i++) {
     69       pthread_create(&threads[curthread++], NULL, level2, NULL);
     70    }
     71 
     72    for(i = 0; i < curthread; i++)
     73       pthread_join(threads[i], NULL);
     74 
     75    return 0;
     76 }
     77 
     78 #define NLEVEL1 3
     79 int main(int argc, char*argv[])
     80 {
     81    pthread_t threads[NLEVEL1];
     82    int curthread = 0;
     83    int i;
     84 
     85    only_touch_stackvar = argc > 1;
     86 
     87    for(i = 0; i < NLEVEL1; i++) {
     88       pthread_create(&threads[curthread++], NULL, level1, NULL);
     89    }
     90 
     91    fprintf(stderr, "starting join in main\n");
     92    fflush(stderr);
     93    for(i = 0; i < curthread; i++)
     94       pthread_join(threads[i], NULL);
     95    fprintf(stderr, "finished join in main\n");
     96    fflush(stderr);
     97    return 0;
     98 }
     99 #else
    100 int main()
    101 {
    102    fprintf(stderr, "starting join in main\n");
    103    fflush(stderr);
    104    /* do nothing */
    105    fprintf(stderr, "finished join in main\n");
    106    fflush(stderr);
    107    return 0;
    108 }
    109 #endif
    110