Try to fix the flakyness of test11

This commit is contained in:
ptitSeb 2022-04-10 14:25:16 +02:00
parent 1c83a9f0b7
commit 74cd8cd6fe
2 changed files with 89 additions and 60 deletions

Binary file not shown.

View File

@ -8,95 +8,124 @@
void foo(void); /* Functions that use the TLS data */ void foo(void); /* Functions that use the TLS data */
void bar(void); void bar(void);
#define checkResults(string, val) { \ #define checkResults(string, val) { \
if (val) { \ if (val) { \
printf("Failed with %d at %s", val, string); \ printf("Failed with %d at %s", val, string); \
fflush(stdout); \ exit(1); \
exit(1); \ } \
} \
} }
/* /*
Use the keyword provided by pthread.h to delcare the following variable Use the keyword provided by pthread.h to delcare the following variable
is thread specific, i.e. it is only visible to a specific thread, is thread specific, i.e. it is only visible to a specific thread,
not shared/common to all thread. not shared/common to all thread.
These variables are stored in thread local storage (TLS) area. These variables are stored in thread local storage (TLS) area.
*/ */
__thread int TLS_data1 = 10; __thread int TLS_data1 = 10;
__thread int TLS_data2 = 20; __thread int TLS_data2 = 20;
__thread char TLS_data3[10]; __thread char TLS_data3[10];
// Sync, because it's needed apparently...
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t* mutex_ptr = &mutex;
static pthread_cond_t thread_state_cond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t* thread_state_cond_ptr = &thread_state_cond;
static int status = 0;
#define NUMTHREADS 2 #define NUMTHREADS 2
pthread_t thread[NUMTHREADS]; pthread_t thread[NUMTHREADS];
typedef struct { typedef struct {
int data1; int data1;
int data2; int data2;
} threadparm_t; } threadparm_t;
void *thread_run(void *parm) void *thread_run(void *parm)
{ {
int rc; int rc;
threadparm_t *gData; threadparm_t *gData;
printf("Thread %d: Entered (%d/%d)\n", (pthread_self()==thread[0])?1:2, TLS_data1, TLS_data2); pthread_mutex_lock(mutex_ptr);
fflush(stdout); if (pthread_self()==thread[0]) {
printf("Thread 1: Entered (%d/%d)\n", TLS_data1, TLS_data2);
fflush(stdout);
} else {
while (!status) pthread_cond_wait(thread_state_cond_ptr, mutex_ptr);
printf("Thread 2: Entered (%d/%d)\n", TLS_data1, TLS_data2);
fflush(stdout);
pthread_mutex_unlock(mutex_ptr);
status = 0;
pthread_cond_broadcast(thread_state_cond_ptr);
}
gData = (threadparm_t *)parm; gData = (threadparm_t *)parm;
/* Assign the value from global variable to thread specific variable*/ /* Assign the value from global variable to thread specific variable*/
TLS_data1 = gData->data1; TLS_data1 = gData->data1;
TLS_data2 = gData->data2; TLS_data2 = gData->data2;
strcpy(TLS_data3, "---"); strcpy(TLS_data3, "---");
TLS_data3[1] = (pthread_self()==thread[0])?'1':'2'; TLS_data3[1] = (pthread_self()==thread[0])?'1':'2';
foo(); foo();
return NULL; return NULL;
} }
void foo() { void foo() {
printf("Thread %d: foo(), TLS data=%d %d \"%s\"\n", if (pthread_self()==thread[0]) {
(pthread_self()==thread[0])?1:2, TLS_data1, TLS_data2, TLS_data3); printf("Thread 1: foo(), TLS data=%d %d \"%s\"\n", TLS_data1, TLS_data2, TLS_data3);
fflush(stdout); fflush(stdout);
while(!thread[1]) status = 1;
usleep(300); pthread_cond_broadcast(thread_state_cond_ptr);
if(pthread_self()==thread[0]) while (status) pthread_cond_wait(thread_state_cond_ptr, mutex_ptr);
pthread_join(thread[1], NULL); pthread_mutex_unlock(mutex_ptr);
bar(); } else {
printf("Thread 2: foo(), TLS data=%d %d \"%s\"\n", TLS_data1, TLS_data2, TLS_data3);
fflush(stdout);
}
while(!thread[1])
usleep(300);
if(pthread_self()==thread[0])
pthread_join(thread[1], NULL);
bar();
} }
void bar() { void bar() {
printf("Thread %d: bar(), TLS data=%d %d \"%s\"\n", printf("Thread %d: bar(), TLS data=%d %d \"%s\"\n",
(pthread_self()==thread[0])?1:2, TLS_data1, TLS_data2, TLS_data3); (pthread_self()==thread[0])?1:2, TLS_data1, TLS_data2, TLS_data3);
fflush(stdout); fflush(stdout);
return; return;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int rc=0; int rc=0;
int i; int i;
threadparm_t gData[NUMTHREADS]; threadparm_t gData[NUMTHREADS];
printf("Create/start %d threads\n", NUMTHREADS);
fflush(stdout);
for (i=0; i < NUMTHREADS; i++) {
/* Create per-thread TLS data and pass it to the thread */
gData[i].data1 = i;
gData[i].data2 = (i+1)*2;
rc = pthread_create(&thread[i], NULL, thread_run, &gData[i]);
checkResults("pthread_create()\n", rc);
usleep(200);
}
//printf("Wait for all threads to complete, and release their resources\n");
for (i=0; i < NUMTHREADS; i++) {
rc = pthread_join(thread[i], NULL);
//checkResults("pthread_join()\n", rc);
}
printf("Main completed\n"); printf("Create/start %d threads\n", NUMTHREADS);
return 0; fflush(stdout);
for (i=0; i < NUMTHREADS; i++) {
/* Create per-thread TLS data and pass it to the thread */
gData[i].data1 = i;
gData[i].data2 = (i+1)*2;
rc = pthread_create(&thread[i], NULL, thread_run, &gData[i]);
checkResults("pthread_create()\n", rc);
}
//printf("Wait for all threads to complete, and release their resources\n");
for (i=0; i < NUMTHREADS; i++) {
rc = pthread_join(thread[i], NULL);
//checkResults("pthread_join()\n", rc);
}
thread_state_cond_ptr = NULL;
i = pthread_cond_destroy(&thread_state_cond);
checkResults("destroying cond\n", i);
mutex_ptr = NULL;
i = pthread_mutex_destroy(&mutex);
checkResults("destroying mutex\n", i);
printf("Main completed\n");
fflush(stdout);
return 0;
} }