diff --git a/tests/test11 b/tests/test11 index 48690872d..cc3c47206 100755 Binary files a/tests/test11 and b/tests/test11 differ diff --git a/tests/test11.c b/tests/test11.c index 615949fca..56005cf87 100644 --- a/tests/test11.c +++ b/tests/test11.c @@ -8,95 +8,124 @@ void foo(void); /* Functions that use the TLS data */ void bar(void); -#define checkResults(string, val) { \ - if (val) { \ - printf("Failed with %d at %s", val, string); \ - fflush(stdout); \ - exit(1); \ - } \ +#define checkResults(string, val) { \ + if (val) { \ + printf("Failed with %d at %s", val, string); \ + exit(1); \ + } \ } /* - 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, - not shared/common to all thread. - These variables are stored in thread local storage (TLS) area. + 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, + not shared/common to all thread. + These variables are stored in thread local storage (TLS) area. */ __thread int TLS_data1 = 10; __thread int TLS_data2 = 20; __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 pthread_t thread[NUMTHREADS]; typedef struct { - int data1; - int data2; + int data1; + int data2; } threadparm_t; void *thread_run(void *parm) { - int rc; - threadparm_t *gData; + int rc; + threadparm_t *gData; - printf("Thread %d: Entered (%d/%d)\n", (pthread_self()==thread[0])?1:2, TLS_data1, TLS_data2); - fflush(stdout); + pthread_mutex_lock(mutex_ptr); + 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*/ - TLS_data1 = gData->data1; - TLS_data2 = gData->data2; - strcpy(TLS_data3, "---"); - TLS_data3[1] = (pthread_self()==thread[0])?'1':'2'; + /* Assign the value from global variable to thread specific variable*/ + TLS_data1 = gData->data1; + TLS_data2 = gData->data2; + strcpy(TLS_data3, "---"); + TLS_data3[1] = (pthread_self()==thread[0])?'1':'2'; - foo(); - return NULL; + foo(); + return NULL; } void foo() { - printf("Thread %d: foo(), TLS data=%d %d \"%s\"\n", - (pthread_self()==thread[0])?1:2, TLS_data1, TLS_data2, TLS_data3); - fflush(stdout); - while(!thread[1]) - usleep(300); - if(pthread_self()==thread[0]) - pthread_join(thread[1], NULL); - bar(); + if (pthread_self()==thread[0]) { + printf("Thread 1: foo(), TLS data=%d %d \"%s\"\n", TLS_data1, TLS_data2, TLS_data3); + fflush(stdout); + status = 1; + pthread_cond_broadcast(thread_state_cond_ptr); + while (status) pthread_cond_wait(thread_state_cond_ptr, mutex_ptr); + pthread_mutex_unlock(mutex_ptr); + } 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() { - printf("Thread %d: bar(), TLS data=%d %d \"%s\"\n", - (pthread_self()==thread[0])?1:2, TLS_data1, TLS_data2, TLS_data3); - fflush(stdout); - return; + printf("Thread %d: bar(), TLS data=%d %d \"%s\"\n", + (pthread_self()==thread[0])?1:2, TLS_data1, TLS_data2, TLS_data3); + fflush(stdout); + return; } - int main(int argc, char **argv) { - int rc=0; - int i; - 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); - } + int rc=0; + int i; + threadparm_t gData[NUMTHREADS]; - printf("Main completed\n"); - return 0; + 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); + } + + //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; } -