Multi-threading beginner here. On exactly the 5th iteration (i.e. when executing pthread_join(threadID[4], NULL), my program fails with a segmentation fault.
I am creating multiple threads to add/subtract 1 from a counter variable to study race conditions. Everything works smoothly until I try 5 threads or more. On exactly the last iteration of pthread_join(threadID[4], NULL), it fails and I can't determine why. I am sure the issue is there as I used printf statements to see where it reaches before failing.
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <time.h>
int opt_threads;
int opt_iterations;
long nThreads;
long nIterations;
int opt_yield;
long long counter;
void add(long long *pointer, long long value) {
long long sum = *pointer + value;
if (opt_yield)
sched_yield();
*pointer = sum;
}
void *thread_worker(void * arg) {
long i;
for (i=0; i<nIterations; i++) {
add(&counter, 1);
add(&counter, -1);
}
return arg;
}
int main(int argc, char *argv[]) {
int c;
pthread_t *threadID = malloc(nThreads * sizeof(pthread_t));
if (threadID == NULL) {
fprintf(stderr, "Thread memory allocation failed\n");
exit(1);
}
static struct option long_options[] =
{
{"threads", required_argument, 0, 't'},
{"iterations", required_argument, 0, 'i'},
{"yield", no_argument, 0, 'y'},
{0,0,0,0}
};
while (1) {
c = getopt_long(argc, argv, "", long_options, NULL);
if (c==-1) break;
switch(c) {
case 't':
opt_threads = 1;
nThreads = atoi(optarg);
break;
case 'i':
opt_iterations = 1;
nIterations = atoi(optarg);
break;
case 'y':
opt_yield = 1;
break;
default:
fprintf(stderr, "Bad argument!\n");
exit(1);
}
}
counter = 0;
struct timespec start, finish;
int i;
//start clock
clock_gettime(CLOCK_MONOTONIC, &start);
//create
for (i=0; i < nThreads; i++) {
pthread_create(&threadID[i], NULL, &thread_worker, NULL);
printf("Created thread[%ld]\n", i);
}
//wait (join)
/*for (i=0; i < nThreads; i++) {
printf("Now i is %ld\n", i);
if (pthread_join(threadID[i], NULL) != 0)
fprintf(stdout,"ERRRRROOOORRRRRRRR\n");
}*/
pthread_join(threadID[0], NULL);
pthread_join(threadID[1], NULL);
pthread_join(threadID[2], NULL);
pthread_join(threadID[3], NULL);
pthread_join(threadID[4], NULL);
printf("about to end clock\n");
//finish clock
clock_gettime(CLOCK_MONOTONIC, &finish);
printf("finished clock\n");
long seconds = finish.tv_sec - start.tv_sec;
long ns = finish.tv_nsec - start.tv_nsec;
long runTime = (seconds + ns) * 1000000000L;
long nOperations = nThreads * nIterations * 2;
long avgOperations = runTime / nOperations;
long run_time = 1000000000L * (finish.tv_sec - start.tv_sec) + finish.tv_nsec - start.tv_nsec;
//Print
if (opt_yield == 0)
fprintf(stdout, "add-none, %ld, %ld, %lld, %ld, %lld, %lld\n", nThreads, nIterations, nOperations, run_time, run_time/nOperations, counter);
else if (opt_yield == 1)
fprintf(stdout, "add-yield-none, %ld, %ld, %lld, %ld, %lld, %lld\n",nThreads, nIterations, nOperations, run_time, run_time/nOperations, counter);
exit(0);
}
I expect the program to be able to correctly wait for the 5th thread, but it fails with segmentation fault.
thread_worker
? can you post the whole complete code? i suspect something is overwriting memory and the 5th time finally reaches some critical variable like a pointer or array index. – SkaperennThreads
is (beyond what you've said, rather than what you've shown). We have no idea whatthreadID
is. Its probably an array, but we don't know. We have no idea whatthread_worker
does. – WhozCraigpthread_join(threadID[0], NULL); pthread_join(threadID[1], NULL); pthread_join(threadID[2], NULL); pthread_join(threadID[3], NULL); pthread_join(threadID[4], NULL);
This will only work if the command line parameter for threads is 5 – user3629249