tags:

views:

125

answers:

3

Hello, The following code produces wrong and inconsistent output with gcc (4.1.2 20080704) but correct and expected output with icc (Version 11.1) . But when I moved the thread_data_array[] definition from main() to global (immediately after the struct thread_data definition) it works fine with both compilers. I do not see why this change should make any difference. I would like to generate threads recursively so I need to call it from a function but not define as global. Could someone explain what is wrong the code please?

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define NUM_THREADS 4

struct thread_data {
    int  thread_id;
    int  sum;
};

/* struct thread_data thread_data_array[NUM_THREADS]; */

void *p_task(void *threadarg)
{
    struct thread_data *my_data;
    int taskid;
    int sum;

    my_data = (struct thread_data *) threadarg;
    taskid = my_data->thread_id;
    sum = my_data->sum;

    printf("Thread #%d with sum %d\n", taskid, sum);

    for ( sum = 0; sum < 000000000; sum++ ) {
        for ( taskid = 0; taskid < 000000000; taskid++ ) {
            sum+=taskid;
        }
    }

    return my_data;
}

int main ()
{
    struct thread_data thread_data_array[NUM_THREADS]; /*this does not work*/

    pthread_t threads[NUM_THREADS];
    int rc;
    long t;

    for ( t = 0; t < NUM_THREADS; t++ ) {
        thread_data_array[t].thread_id = t;
        thread_data_array[t].sum = (int) t*2;
        rc = pthread_create( &threads[t], NULL, p_task, (void *) &thread_data_array[t] );
    }

    pthread_exit(NULL);

    return 0;

}
+4  A: 

Well, my first thought would be that the main thread is actually exiting, and taking its stack frame with it, before the other threads are finished. From what I remember about pthreads (and this is over a decade and a half ago, using them with DCE), there's absolutely nothing special about the main thread other than the stack size.

If the array is declared global, the exit from main will have no effect on it but, if it's in the stack frame for main, I'd be very careful using it after it exits.

I'm basing this partially on guesswork since you haven't actually explained what the behavior is that you're seeing.

I would suggest inserting the following code before the pthread_exit in main:

for (t = 0; t < NUM_THREADS; t++ )
    pthread_join (threads[t], NULL);
paxdiablo
Thanks. "(void) pthread_join(threads[t], NULL);" worked. :)
A: 

You destroy your stack frame before you've joined the threads using the data on the stack.

Before you call pthread_exit(), you want to call pthread_join() for each thread you created.

janm
Ok, now I understand. Thanks. :)
A: 

I suspect that when pthread_exit() is called and the thread exits, the stack for the thread is no longer valid.

You have two choices.

  1. Use pthread_join() to wait for the thread to finish.
  2. Dynamically allocate the thread_data array.
R Samuel Klatchko
I thought pthread_exit would fix the problem of waiting. It didn't. I was confused as the data was valid by the time the thread was called, info was displayed, but something else happened and garbage was being printed.