mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 08:26:14 +00:00
110 lines
2.6 KiB
C
110 lines
2.6 KiB
C
#include <config.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef HAVE_TLS
|
|
|
|
static int only_touch_stackvar;
|
|
|
|
/* We should have no error on local and global
|
|
as these are both thread local variables. */
|
|
static __thread int local;
|
|
__thread int global;
|
|
|
|
/* We will wrongly share this variable indirectly through a pointer
|
|
We should have an error for this. */
|
|
static __thread int badly_shared_local;
|
|
|
|
/* ptr_to_badly_shared_local allows to have multiple threads seeing
|
|
the same thread local storage. This is however really bad sharing
|
|
as this can cause SEGV or whatever, as when the thread disappears,
|
|
the badly_shared_local var pointed to can also disappear.
|
|
By default, the regtest does not test this really bad sharing. */
|
|
pthread_mutex_t protect_ptr_to_badly_shared_local = PTHREAD_MUTEX_INITIALIZER;
|
|
int *ptr_to_badly_shared_local;
|
|
|
|
static void local_false_positive(void)
|
|
{
|
|
local = local + 1; // no error is expected
|
|
}
|
|
|
|
static void global_false_positive(void)
|
|
{
|
|
global = global + 1; // no error is expected
|
|
}
|
|
|
|
static void badly_shared_local_error_expected(void)
|
|
{
|
|
*ptr_to_badly_shared_local = *ptr_to_badly_shared_local + 1; // an error is expected
|
|
// This can cause a SIGSEGV.
|
|
}
|
|
|
|
static void *level2(void *p)
|
|
{
|
|
int stackvar = 0;
|
|
|
|
stackvar = stackvar + only_touch_stackvar;
|
|
|
|
local_false_positive();
|
|
global_false_positive();
|
|
if (only_touch_stackvar != 0) {
|
|
badly_shared_local_error_expected();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define NLEVEL2 10
|
|
static void *level1(void *p)
|
|
{
|
|
pthread_t threads[NLEVEL2];
|
|
int curthread = 0;
|
|
int i;
|
|
|
|
pthread_mutex_lock(&protect_ptr_to_badly_shared_local);
|
|
if (ptr_to_badly_shared_local == NULL)
|
|
ptr_to_badly_shared_local = &badly_shared_local;
|
|
pthread_mutex_unlock(&protect_ptr_to_badly_shared_local);
|
|
|
|
for(i = 0; i < NLEVEL2; i++) {
|
|
pthread_create(&threads[curthread++], NULL, level2, NULL);
|
|
}
|
|
|
|
for(i = 0; i < curthread; i++)
|
|
pthread_join(threads[i], NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define NLEVEL1 3
|
|
int main(int argc, char*argv[])
|
|
{
|
|
pthread_t threads[NLEVEL1];
|
|
int curthread = 0;
|
|
int i;
|
|
|
|
only_touch_stackvar = argc > 1;
|
|
|
|
for(i = 0; i < NLEVEL1; i++) {
|
|
pthread_create(&threads[curthread++], NULL, level1, NULL);
|
|
}
|
|
|
|
fprintf(stderr, "starting join in main\n");
|
|
fflush(stderr);
|
|
for(i = 0; i < curthread; i++)
|
|
pthread_join(threads[i], NULL);
|
|
fprintf(stderr, "finished join in main\n");
|
|
fflush(stderr);
|
|
return 0;
|
|
}
|
|
#else
|
|
int main()
|
|
{
|
|
fprintf(stderr, "starting join in main\n");
|
|
fflush(stderr);
|
|
/* do nothing */
|
|
fprintf(stderr, "finished join in main\n");
|
|
fflush(stderr);
|
|
return 0;
|
|
}
|
|
#endif
|