1

Hi am working on an assignment for Unix Programming in college an I have a slight problem.

I think I have the program working but it seems to print out the wrong results.

Here is the question:

Write a program that computes the square roots of the integers from 0 to 99 each in a separate worker thread (100 worker threads and main thread). In the meantime the main thread should display a short message to the user and when ready print the results out in order.

This is my code:

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

#define NUMBER_OF_ROOTS 100

void *calculate_roots(void* input)
{
    int *index = (int *)input;

    double *root = (double *) malloc(sizeof(double));
    *root = sqrt(*index);
    return (void*) root;

}   

int main(void)
{
    pthread_t thread_id[NUMBER_OF_ROOTS];
    int rc;
    double roots[NUMBER_OF_ROOTS];
    int index;

    printf("Calculating square roots ...\n\n");

    for(index = 0; index < NUMBER_OF_ROOTS; index++)
    {
        rc = pthread_create(&thread_id[index], NULL, calculate_roots, (void *) &index);
        if(rc)
        {
            fprintf(stderr, "ERROR, return code from pthread_create() is %d\n", rc);
        }

    }

    for(index = 0; index < NUMBER_OF_ROOTS; index++)
    {
        double* temp;
        pthread_join(thread_id[index], (void*) &temp);

        roots[index] = *temp;
        free(temp);
    }

    for(index = 0; index < NUMBER_OF_ROOTS; index++)
    {
        printf("The root of %i is %lf\n", index, roots[index]);
    }



    pthread_exit(NULL);
}

This is what I get when I run it in the terminal:

Calculating square roots ...

The root of 0 is 2.236068
The root of 1 is 2.449490
The root of 2 is 2.449490
The root of 3 is 2.236068
The root of 4 is 2.645751
The root of 5 is 2.449490
The root of 6 is 2.645751
The root of 7 is 2.828427
The root of 8 is 3.000000
The root of 9 is 3.162278
The root of 10 is 3.316625
The root of 11 is 3.464102
The root of 12 is 3.605551
The root of 13 is 3.741657
The root of 14 is 3.872983
The root of 15 is 4.000000
The root of 16 is 4.123106
The root of 17 is 4.242641
The root of 18 is 4.358899
The root of 19 is 4.472136
The root of 20 is 4.582576
The root of 21 is 4.690416
The root of 22 is 4.795832
The root of 23 is 4.898979
The root of 24 is 5.000000
The root of 25 is 5.099020
The root of 26 is 5.196152
The root of 27 is 5.291503
The root of 28 is 5.385165
The root of 29 is 5.477226
The root of 30 is 5.567764
The root of 31 is 5.656854
The root of 32 is 5.744563
The root of 33 is 5.830952
The root of 34 is 5.916080
The root of 35 is 6.000000
The root of 36 is 6.082763
The root of 37 is 6.164414
The root of 38 is 6.244998
The root of 39 is 6.324555
The root of 40 is 6.403124
The root of 41 is 6.480741
The root of 42 is 6.557439
The root of 43 is 6.633250
The root of 44 is 6.708204
The root of 45 is 6.782330
The root of 46 is 6.855655
The root of 47 is 6.928203
The root of 48 is 7.000000
The root of 49 is 7.071068
The root of 50 is 7.141428
The root of 51 is 7.211103
The root of 52 is 7.280110
The root of 53 is 7.348469
The root of 54 is 7.416198
The root of 55 is 7.483315
The root of 56 is 7.549834
The root of 57 is 7.615773
The root of 58 is 7.681146
The root of 59 is 7.745967
The root of 60 is 7.810250
The root of 61 is 7.874008
The root of 62 is 7.937254
The root of 63 is 8.000000
The root of 64 is 8.062258
The root of 65 is 8.124038
The root of 66 is 8.185353
The root of 67 is 8.246211
The root of 68 is 8.306624
The root of 69 is 8.366600
The root of 70 is 8.426150
The root of 71 is 8.485281
The root of 72 is 8.544004
The root of 73 is 8.602325
The root of 74 is 8.660254
The root of 75 is 8.717798
The root of 76 is 8.774964
The root of 77 is 8.831761
The root of 78 is 8.888194
The root of 79 is 8.944272
The root of 80 is 9.000000
The root of 81 is 9.055385
The root of 82 is 9.110434
The root of 83 is 9.165151
The root of 84 is 9.219544
The root of 85 is 9.273618
The root of 86 is 9.327379
The root of 87 is 9.380832
The root of 88 is 9.433981
The root of 89 is 9.486833
The root of 90 is 9.539392
The root of 91 is 9.591663
The root of 92 is 9.643651
The root of 93 is 9.695360
The root of 94 is 9.746794
The root of 95 is 9.797959
The root of 96 is 9.848858
The root of 97 is 9.899495
The root of 98 is 9.949874
The root of 99 is 0.000000
alk
  • 69,737
  • 10
  • 105
  • 255
KaiUR
  • 86
  • 1
  • 12
  • 1
    `The root of 0 is 2.236068` - nope, I'd say that's not working alright. Did you try using a debuger to find the problem? – Mike Mar 04 '14 at 18:24

1 Answers1

5

You are passing to each thread the same address, that is &index.

Due to this it might very well happen that index had been overwritten before a particular thread was done using it. So it is not sure that each thread gets it very own index value.

To fix this handle the index to the thread-id the same way as you handle the thread-id, give each thread its own instance of index.

struct Thread_Data
{
  pthread_t id;
  int index;
}

struct Thread_Data thread_data[100] = {0};

...

for(index = 0; index < NUMBER_OF_ROOTS; index++)
{
  thread_data[index].index = index;
  rc = pthread_create(&thread_data[index].id, NULL, calculate_roots, &thread_data[index].index);

Also use pthread_exit() to have a thread return a value.

alk
  • 69,737
  • 10
  • 105
  • 255
  • 1
    +1, though `pthread_exit()` [isn't *required*](http://stackoverflow.com/questions/2251452/how-to-return-a-value-from-thread-in-c). The `void*` returned from the thread proc will be the `void*` populated to the out-parameter of `pthread_join`. – WhozCraig Mar 04 '14 at 18:31
  • Indeed, after having re-checked the docs, I need to conclude that the only useful invocation of `pthread_exit()` is to exit `main()`, in case other threads should be left running. @WhozCraig – alk Mar 04 '14 at 18:39
  • 1
    Ya, I concur. Also since the assignment doesn't require maintaining separate arrays of operands *and* roots, I see no reason not to just send the operand in the `root` array slot itself as the thread param, have the function compute the root, and save the result right back where it came from; the array. I.e. `root[index] = index;` then pass `root + index` as the parameter, and simply have the function pull the value, compute the root, and write it back to the same address. The loop index *is* the operand, so not like it isn't recoverable when reporting the results. Nice answer, btw. – WhozCraig Mar 04 '14 at 18:42