In your code you basically do following:
- prepare some data for thread
- run thread
- wait till it finished
- go to next iteration
so this code it absolutely sequential
to make it non sequential you need something like this:
- prepare some data
- run thread
- go to next iteration
- wait until all threads are finished
try something like this:
for (i = 0; i < M; i++)
{
for(j = 0; j < N; j++)
{
struct coords *data = (struct coords*)malloc(sizeof(struct coords));
data->i = i;
data->j = j;
pthread_attr_init(&attributes[threadIndex]);
pthread_create(&threads[threadIndex], &attributes[threadIndex], calc_val, &data);
threadIndex++;
}
}
for (i=0;i<numThreads;i++)
pthread_join(threads[i], NULL);
next problem about memory allocation - you can do it either when all threads are finished (then you need to store somewhere all allocated pointers), or you can just free in it each thread as you asked in comments