Multithreading in C - Final created thread overtakes output of other threads? - c

I'm a beginner at C, and am trying out multithreading. I wrote a program to try and calculate values of Euler's phi function through the use of multiple threads. I'm using brute force, checking each individual number less than the given input for common factors.
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
int has_common_factor(int number1, int number2);
void *phi_function(void *);
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int out = 0;
int NTHREADS,inp;
int main(int argc, char *argv[])
{
int c = 0;
while(1){
c = getopt(argc, argv, "p:n:");
if (c == -1){
break;
}
switch(c){
case 'p': inp = atoi(optarg);
break;
case 'n': NTHREADS = atoi(optarg);
break;
default: printf("Invalid Option");
return 1;
}
}
//pthread_t thread_id[NTHREADS];
pthread_t *thread_id;
thread_id = (pthread_t *)malloc(sizeof(pthread_t) * NTHREADS);
int i, j, arg;
for (i = 0; i < NTHREADS; i++)
{
arg = i * inp / NTHREADS + 1;
pthread_create(&thread_id[i], NULL, phi_function, (void *)&arg);
}
for (j = 0; j < NTHREADS; j++)
{
pthread_join(thread_id[j], NULL);
}
printf("Final value: %d\n", out);
}
void *phi_function(void *ptr)
{
printf("threadid: %ld\n",pthread_self());
int i;
int *min;
min = (int *)ptr;
FILE *fptr;
sleep(*min);
char filename[100];
sprintf(filename,"output%d", *min);
fptr = fopen(filename,"w");
for (i = *min; i < *min + inp / NTHREADS; i++)
{
int j;
if (has_common_factor(i, inp) == 0) {
pthread_mutex_lock(&mutex1);
out++;
printf("i = %d\n",i);
pthread_mutex_unlock(&mutex1);
fprintf(fptr,"i = %d\n",i);
}
}
fclose(fptr);
}
int has_common_factor(int number1, int number2) {
int j;
for (j=2; j<=number1; j++) {
if (number1 %j == 0 && number2 %j ==0) {
return 1;
}
}
return 0;
}
I used threading by splitting the input into N different equal sized ranges, and making each of N threads check each range for relatively prime integers. I also printed out all of the relatively prime integers detected to check for any errors. The program works fine for 1 integer, giving the correct outputs for all the numbers I checked, but something interesting happens when using more than 1 thread.
After compiling and running with two threads, using 2 threads and an input of 20, like this:
./thread -p 20 -n 2
This is the output:
threadid: 140235244418816
threadid: 140235236026112
i = 11
i = 13
i = 17
i = 19
i = 11
i = 13
i = 17
i = 19
Final value: 8
As you can see, it gets the correct count for the number of relatively prime integers, but only outputs the integers detected in the range of the second thread, seemingly overriding that of the first. Both threads must have been run since there are two unique threadids. Using 1 thread results in the following output:
threadid: 140235236026112
i = 1
i = 3
i = 7
i = 9
i = 11
i = 13
i = 17
i = 19
Final value: 8
What is happening/what can I do to fix this?

for (i = 0; i < NTHREADS; i++)
{
arg = i * inp / NTHREADS + 1;
pthread_create(&thread_id[i], NULL, phi_function, (void *)&arg);
}
You pass the same parameter, &arg, to every thread. You need to pass different parameters to each thread.
A good pattern to use is this:
Call malloc to allocate an object to hold the parameters for a thread.
Fill in the structure.
Call pthread_create, passing it the value you got from malloc.
In the thread, extract the values from the structure and free it when you're done with it.
This ensures you pass a different value to each thread.

Related

how to compute sum of n/m Gregory-Leibniz terms in C language

get the two values named m & n from the command line arguments and convert them into integers. now after that create m threads and each thread computes the sum of n/m terms in Gregory-Leibniz Series.
pi = 4 * (1 - 1/3 + 1/5 - 1/7 + 1/9 - ...)
Now when thread finishes its computation, print its partial sum and atomically add it to a shared global variable.
& how to check that all of the m computational threads have done the atomic additions?
I share my source code, what I tried
#include<stdio.h>
#include<pthread.h>
#include <stdlib.h>
#include<math.h>
pthread_barrier_t barrier;
int count;
long int term;
// int* int_arr;
double total;
void *thread_function(void *vargp)
{
int thread_rank = *(int *)vargp;
// printf("waiting for barrier... \n");
pthread_barrier_wait(&barrier);
// printf("we passed the barrier... \n");
double sum = 0.0;
int n = count * term;
int start = n - term;
// printf("start %d & end %d \n\n", start, n);
for(int i = start; i < n; i++)
{
sum += pow(-1, i) / (2*i+1);
// v += 1 / i - 1 / (i + 2);
}
total += sum;
// int_arr[count] = sum;
count++;
printf("thr %d : %lf \n", thread_rank, sum);
return NULL;
}
int main(int argc,char *argv[])
{
if (argc <= 2) {
printf("missing arguments. please pass two num. in arguments\n");
exit(-1);
}
int m = atoi(argv[1]); // get value of first argument
int n = atoi(argv[2]); // get value of second argument
// int_arr = (int*) calloc(m, sizeof(int));
count = 1;
term = n / m;
pthread_t thread_id[m];
int i, ret;
double pi;
/* Initialize the barrier. */
pthread_barrier_init(&barrier, NULL, m);
for(i = 0; i < m; i++)
{
ret = pthread_create(&thread_id[i], NULL , &thread_function, (void *)&i);
if (ret) {
printf("unable to create thread! \n");
exit(-1);
}
}
for(i = 0; i < m; i++)
{
if(pthread_join(thread_id[i], NULL) != 0) {
perror("Failed to join thread");
}
}
pi = 4 * total;
printf("%lf ", pi);
pthread_barrier_destroy(&barrier);
return 0;
}
what I need :-
create M thread & each thread computes the sum of n/m terms in the Gregory-Leibniz Series.
first thread computes the sum of term 1 to n/m , the second thread computes the sum of the terms from (n/m + 1) to 2n/m etc.
when all the thread finishes its computation than print its partial sum and Value of Pi.
I tried a lot, but I can't achieve exact what I want. I got wrong output value of PI
for example : m = 16 and n = 1024
then it sometimes return 3.125969, sometimes 12.503874 , 15.629843, sometimes 6.251937 as a output of Pi value
please help me
Edited Source Code :
#include <inttypes.h>
#include <math.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct args {
uint64_t thread_id;
struct {
uint64_t start;
uint64_t end;
} range;
};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t barrier;
long double total = 0;
uint64_t total_iterations = 0;
void *partial_sum(void *arg)
{
struct args *args = arg;
long double sum = 0;
printf("waiting for barrier in thread -> %" PRId64 "\n", args->thread_id);
pthread_barrier_wait(&barrier);
// printf("we passed the barrier... \n");
for (uint64_t n = args->range.start; n < args->range.end; n++)
sum += pow(-1.0, n) / (1 + n * 2);
if (pthread_mutex_lock(&mutex)) {
perror("pthread_mutex_lock");
exit(EXIT_FAILURE);
}
total += sum;
total_iterations += args->range.end - args->range.start;
if (pthread_mutex_unlock(&mutex)) {
perror("pthread_mutex_unlock");
exit(EXIT_FAILURE);
}
printf("thr %" PRId64 " : %.20Lf\n", args->thread_id, sum);
return NULL;
}
int main(int argc,char *argv[])
{
if (argc <= 2) {
fprintf(stderr, "usage: %s THREADS TERMS.\tPlease pass two num. in arguments\n", *argv);
return EXIT_FAILURE;
}
int m = atoi(argv[1]); // get value of first argument & converted into int
int n = atoi(argv[2]); // get value of second argument & converted into int
if (!m || !n) {
fprintf(stderr, "Argument is zero.\n");
return EXIT_FAILURE;
}
uint64_t threads = m;
uint64_t terms = n;
uint64_t range = terms / threads;
uint64_t excess = terms - range * threads;
pthread_t thread_id[threads];
struct args arguments[threads];
int ret;
/* Initialize the barrier. */
ret = pthread_barrier_init(&barrier, NULL, m);
if (ret) {
perror("pthread_barrier_init");
return EXIT_FAILURE;
}
for (uint64_t i = 0; i < threads; i++) {
arguments[i].thread_id = i;
arguments[i].range.start = i * range;
arguments[i].range.end = arguments[i].range.start + range;
if (threads - 1 == i)
arguments[i].range.end += excess;
printf("In main: creating thread %ld\n", i);
ret = pthread_create(thread_id + i, NULL, partial_sum, arguments + i);
if (ret) {
perror("pthread_create");
return EXIT_FAILURE;
}
}
for (uint64_t i = 0; i < threads; i++)
if (pthread_join(thread_id[i], NULL))
perror("pthread_join");
pthread_barrier_destroy(&barrier);
printf("Pi value is : %.10Lf\n", 4 * total);
printf("COMPLETE? (%s)\n", total_iterations == terms ? "YES" : "NO");
return 0;
}
In each thread, the count variable is expected to be of a steadily increasing value in this expression
int n = count * term;
being one larger than it was in the "previous" thread, but count is only increased later on in each thread.
Even if you were to "immediately" increase count, there is nothing that guards against two or more threads attempting to read from and write to the variable at the same time.
The same issue exists for total.
The unpredictability of these reads and writes will lead to indeterminate results.
When sharing resources between threads, you must take care to avoid these race conditions. The POSIX threads library does not contain any atomics for fundamental integral operations.
You should protect your critical data against a read/write race condition by using a lock to restrict access to a single thread at a time.
The POSIX threads library includes a pthread_mutex_t type for this purpose. See:
pthread_mutex_init / pthread_mutex_destroy
pthread_mutex_lock / pthread_mutex_unlock
Additionally, as pointed out by #Craig Estey, using (void *) &i as the argument to the thread functions introduces a race condition where the value of i may change before any given thread executes *(int *) vargp;.
The suggestion is to pass the value of i directly, storing it intermediately as a pointer, but you should use the appropriate type of intptr_t or uintptr_t, which are well defined for this purpose.
pthread_create(&thread_id[i], NULL , thread_function, (intptr_t) i)
int thread_rank = (intptr_t) vargp;
How to check that all of the m computational threads have done the atomic additions?
Sum up the number of terms processed by each thread, and ensure it is equal to the expected number of terms. This can also naturally be assumed to be the case if all possible errors are accounted for (ensuring all threads run to completion and assuming the algorithm used is correct).
A moderately complete example program:
#define _POSIX_C_SOURCE 200809L
#include <inttypes.h>
#include <math.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
struct args {
uint64_t thread_id;
struct {
uint64_t start;
uint64_t end;
} range;
};
pthread_mutex_t mutex;
long double total = 0;
uint64_t total_iterations = 0;
void *partial_sum(void *arg)
{
struct args *args = arg;
long double sum = 0;
for (uint64_t n = args->range.start; n < args->range.end; n++)
sum += pow(-1.0, n) / (1 + n * 2);
if (pthread_mutex_lock(&mutex)) {
perror("pthread_mutex_lock");
exit(EXIT_FAILURE);
}
total += sum;
total_iterations += args->range.end - args->range.start;
if (pthread_mutex_unlock(&mutex)) {
perror("pthread_mutex_unlock");
exit(EXIT_FAILURE);
}
printf("thread(%" PRId64 ") Partial sum: %.20Lf\n", args->thread_id, sum);
return NULL;
}
int main(int argc,char **argv)
{
if (argc < 3) {
fprintf(stderr, "usage: %s THREADS TERMS\n", *argv);
return EXIT_FAILURE;
}
uint64_t threads = strtoull(argv[1], NULL, 10);
uint64_t terms = strtoull(argv[2], NULL, 10);
if (!threads || !terms) {
fprintf(stderr, "Argument is zero.\n");
return EXIT_FAILURE;
}
uint64_t range = terms / threads;
uint64_t excess = terms - range * threads;
pthread_t thread_id[threads];
struct args arguments[threads];
if (pthread_mutex_init(&mutex, NULL)) {
perror("pthread_mutex_init");
return EXIT_FAILURE;
}
for (uint64_t i = 0; i < threads; i++) {
arguments[i].thread_id = i;
arguments[i].range.start = i * range;
arguments[i].range.end = arguments[i].range.start + range;
if (threads - 1 == i)
arguments[i].range.end += excess;
int ret = pthread_create(thread_id + i, NULL , partial_sum, arguments + i);
if (ret) {
perror("pthread_create");
return EXIT_FAILURE;
}
}
for (uint64_t i = 0; i < threads; i++)
if (pthread_join(thread_id[i], NULL))
perror("pthread_join");
pthread_mutex_destroy(&mutex);
printf("%.10Lf\n", 4 * total);
printf("COMPLETE? (%s)\n", total_iterations == terms ? "YES" : "NO");
}
Using 16 threads to process 1 billion terms:
$ ./a.out 16 10000000000
thread(14) Partial sum: 0.00000000000190476190
thread(10) Partial sum: 0.00000000000363636364
thread(2) Partial sum: 0.00000000006666666667
thread(1) Partial sum: 0.00000000020000000000
thread(8) Partial sum: 0.00000000000555555556
thread(15) Partial sum: 0.00000000000166666667
thread(0) Partial sum: 0.78539816299744868408
thread(3) Partial sum: 0.00000000003333333333
thread(13) Partial sum: 0.00000000000219780220
thread(11) Partial sum: 0.00000000000303030303
thread(4) Partial sum: 0.00000000002000000000
thread(5) Partial sum: 0.00000000001333333333
thread(7) Partial sum: 0.00000000000714285714
thread(6) Partial sum: 0.00000000000952380952
thread(12) Partial sum: 0.00000000000256410256
thread(9) Partial sum: 0.00000000000444444444
3.1415926535
COMPLETE? (YES)

Cast to Pointer Error Multithread Program

This is a multi-threaded program that outputs prime numbers. The user runs the program and enters a number into the command line. It creates a separate thread that outputs all the prime numbers less than or equal to the number entered by the user.
I have an error: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] I'm so close but I've been staring at this for awhile now. I thought I would get some feedback.
How can I fix this? It is referring to the void here:
(void *)count);
Here is all the code:
#include <stdio.h>
#include <pthread.h>
int N = 100; //number of promes to be generated
int prime_arr[100000] = {0}; //prime arrray
void *printprime(void *ptr) //thread function
{
int j, flag;
int i = (int)(long long int)ptr; //getting thread number
//for thread 0, we check for all primes 0,4,8,12
//for thread 1, we check for all primes 1,5,9,13
while (i < N) { //while number in range
flag = 0; //check if i has factor
for (j = 2; j <= i / 2; j++) //factor can be at max i/2 value
{
if (i % j == 0) //factor found
{
flag = 1;
break;
}
}
if (flag == 0 && (i > 1)) //prime found, no factor
{
prime_arr[i] = 1;
}
i += 4; //increase by interval of 4
}
}
int main()
{
printf("Enter N: ");
scanf("%d", &N); //input N
pthread_t tid[4] = {0}; //create an array of 4 threads
int count = 0;
for (count = 0; count < 4; count++) //initialize threads and start
{
printf("\r\n CREATING THREADS %d", count);
pthread_create(&tid[count], NULL, printprime,(void *)count); //count is passed as argument, target = printprime
}
printf("\n");
for (count = 0; count < 4; count++)
{
pthread_join(tid[count], NULL); //while all thread havent finished
}
int c = 0;
for (count = 0; count < N; count++) //print primes
if (prime_arr[count] == 1)
printf("%d ", count);
printf("\n");
return 0;
}
Here you cast count to a void* which isn't a compatible type.
pthread_create(&tid[count], NULL, printprime, (void*) count);
And here you try to convert it back to an int improperly:
int i = (int)(long long int)ptr;
I suggest creating workpackages, tasks that you instead use and cast proberly to void* and back.
Example:
#include <pthread.h>
#include <stdio.h>
typedef struct {
pthread_t tid;
int count;
} task_t;
void *printprime(void *ptr) {
task_t *task = ptr;
task->count += 10; // do some work
return NULL;
}
#define TASKS (4)
int main() {
task_t tasks[TASKS] = {0}; // an array of tasks
for (int count = 0; count < TASKS; ++count) {
tasks[count].count = count; // fill the task with some job
pthread_create(&tasks[count].tid, NULL, printprime, &tasks[count]);
}
// join and take care of result from all threads
for (int count = 0; count < TASKS; ++count) {
pthread_join(tasks[count].tid, NULL);
printf("task %d value = %d\n", count, tasks[count].count);
}
}
Demo
Use a uintptr_t or a intptr_t instead of an int.
Technically, that's for storing a pointer in an integer, not for storing an integer in a pointer. So it's not exactly kosher. But it's still a common practice.
To do it properly, you would need to (statically or dynamically) allocate a variable for each thread, and pass the address of that variable to the thread.

Inner product space of arrays with posix threads

I want to read as input a table A and B from a user , and make an inner product space from them (a1b1+a2b2+……+anbn) and save it in a local_sum and then share it to an total_sum variable. I am doing the bellow code , but there is a segment fault. For some reason table A & B can't pass to function MUL. Any help would be great, thank you!
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define N 2
int p;
int A[N],B[N];
int local_sum;
void *mul(void *arg)
{
int lines, start, end, i, j;
int id = *(int*)arg;
lines = N / p;
start = id * lines;
end = start + lines;
for (i = start; i < end; i++)
local_sum = A[i] * B[i] + local_sum;
return NULL;
}
int main (int argc, char *argv[])
{
int i;
pthread_t *tid;
if (argc != 2)
{
printf("Provide number of threads.\n");
exit(1);
}
p = atoi(argv[1]);
tid = (pthread_t *)malloc(p * sizeof(pthread_t));
if (tid == NULL)
{
printf("Could not allocate memory.\n");
exit(1);
}
printf("Give Table A\n");
for (int i = 0; i < N; i++)
{
scanf("%d", &A[i]);
}
printf("Give Table B\n");
for (int i = 0; i < N; i++)
{
scanf("%d", &B[i]);
}
for (i = 0; i < p; i++)
{
int *a;
a = malloc(sizeof(int));
*a = 0;
pthread_create(&tid[i], NULL, mul, a);
}
for (i = 0; i < p; i++)
pthread_join(tid[i], NULL);
printf("%d", local_sum);
return 0;
}
Let's see:
You want to have p threads, working on the vectors A and B.
You must be aware of that threads share the same memory, and might be interrupted at any time.
You've got p threads, all trying to write to one shared variable local_sum. This leads to unpredictable results since one thread overwrites the value another thread has written there before.
You can bypass this problem by ensuring exclusive access of one single thread to this variable by using a mutex or the like, or you could have one variable per thread, have each thread produce an intermediate result and after joining all threads, collapse all your intermediate results into the final one.
To do this, your main should look something like (assuming your compiler supports a recent C standard):
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define N 2
/* these are variables shared amongst all threads */
int p;
int A[N], B[N];
/* array with one slot per thread to receive the partial result of each thread */
int* partial_sum;
/* prototype of thread function, just to be independent of the place mul will be placed in the source file... */
void *mul(void *arg);
int main (int argc, char** argv)
{
pthread_t* tid;
p = atoi(argv[1]);
const size_t n_by_p = N/p;
if(n_by_p * p != N)
{
fprintf(stderr, "Number of threads must be an integral factor of N\n");
exit(EXIT_FAILURE) ;
}
tid = calloc(p, sizeof(pthread_t));
partial_sum = calloc(p, sizeof(int)) ;
printf("Give Table A\n");
for(size_t i = 0; i < N; ++i)
{
scanf("%d",&A[i]);
}
printf("Give Table B\n");
for(size_t i = 0; i < N; ++i)
{
scanf("%d",&B[i]);
}
for (size_t i =0; i < p; ++i)
{
/* clumsy way to pass a thread it's slot number, but works as a starter... */
int *a;
a = malloc(sizeof(int));
*a = i;
pthread_create(&tid[i], 0, mul, a);
}
for (size_t i = 0; i < p; ++i)
{
pthread_join(tid[i], 0);
}
free(tid);
tid = 0;
int total_sum = 0;
for (size_t i = 0; i < p; ++i)
{
total_sum += partial_sum[i] ;
}
free(partial_sum);
partial_sum = 0;
printf("%d",total_sum);
return EXIT_SUCCESS;
}
Your threaded method mul should now write to its particular partial_sum slot only :
void *mul(void *arg)
{
int slot_num = *(int*)arg;
free(arg);
arg = 0;
const size_t lines = N/p;
const size_t start = slot_num * lines;
const size_t end = start + lines;
partial_sum[slot_num] = 0;
for(size_t i = start; i < end; ++i)
{
partial_sum[slot_num] += A[i]*B[i];
}
return 0;
}
Beware: This code runs smoothly, only if N is some integral multiple of p.
If this condition is not met, due to truncation in N/p, not all elements of the vectors will be processed.
However, fixing these cases is not the core of this question IMHO.
I spared all kinds of error-checking, which you should add, should this code become part of some operational setup...
if (tid=NULL)
-->
if (tid==NULL)
and
for (i=start;i<end;i++)
I suppose we need
for (i=0;i<end-start;i++)

Peterson's Algorithm in C for Thread concurrency (segment fault)

Hey guys I'm implementing Peterson's algorithm in C. I have two functions that will be executed by the threads created, one that adds 1 to a variable and other that subtracts 1 to that same variable.
The program receives an argument of type int, that integer is the square root of the number of threads I want to create, for example if I execute it in the terminal typing
./algorithm 10, there will be 10*10 (10 000) threads created.
The program runs ok if y type less than 170 as an argument (There would be 28900 threads created) but if I want to create more than that I got a segment fault, tried using "long long int" variables but that wasn't it.
There is a counter named "cont", the variable will be printed each time cont reaches 10 000.
There is another print for the last result of the variable, that should always be 0 because n threads added 1 and n threads subtracted 1.
I want to know why I'm getting a Segment Fault, if there is a limit of threads to be created, or if it is something in my code.
I'm running it using the next command to use only one processor cause Peterson's algorithm only work perfectly on mono-processor systems:
taskset -c 0 ./alg3 100
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
long int n;
long int var = 0;
long int cont = 1;
int flag[] = {0, 0};
int turn = 0;
void* sum(void* data) {
//int n = *((int*)data);
int i;
turn = 2;
flag[0] = 1;
while (turn == 2 && flag[1]);
cont++;
var += 1;
if (cont == 10000) {
printf("varsum=%ld\n", var);
cont = 1;
}
flag[0] = 0;
}
void* rest(void* data) {
//int n = *((int*)data);
int i;
turn = 1;
flag[1] = 1;
while (turn == 1 && flag[0]);
cont++;
var -= 1;
if (cont == 10000) {
printf("varres=%ld\n", var);
cont = 1;
}
flag[1] = 0;
}
main(int argc, char *argv[]) {
long int i;
n = atoi(argv[1]);
n *= n; //n*n is the actual number of threads that will be created
pthread_t tid[n];
for (i = 0; i < n; i++) {
pthread_create(&tid[i], NULL, sum, NULL);
//cont++;
}
for (i = 0; i < n; i++)
pthread_join(tid[i], NULL);
for (i = 0; i < n; i++) {
pthread_create(&tid[i], NULL, rest, NULL);
//cont++;
}
for (i = 0; i < n; i++)
pthread_join(tid[i], NULL);
printf("main() reporting that all %ld threads have terminated\n", i);
printf("variable=%ld\n", var);
} /* main */
First of all, of course there is limit to create threads. It is decided by the stack size of each thread and hardware, details suggest google it...
Segment fault reason:
You didn't check the return value of function pthread_create, when 'n' ls large enough, pthread_create will failed, then pthread_join may use the nonexistent thread_t as the first input parameter. The following code (change from your example) can test how many threads in you can create.
int rc = 0, thread_num = 0;
for (i = 0; i < n; i++) {
rc = pthread_create(&tid[i], NULL, sum, NULL);
if (rc)
{
printf("pthread_crate failed, thread number: %d, error code: %d\n", thread_num, rc);
}
thread_num++;
}
printf("created %d threads.\n", thread_num);
Add error checking at least to pthread_create() to avoid passing an invalid pthread_t variable to pthread_join():
int main(int arc, char ** argv)
{
...
pthread_t tid[n];
int result[n];
for (i = 0; i < n; i++) {
result[i] = errno = pthread_create(&tid[i], NULL, sum, NULL);
if (0 != errno) {
perror("pthread_create() failed");
}
}
for (i = 0; i < n; i++) {
if (0 == result(i]) {
errno = pthread_join(tid[i], NULL);
if (0 != errno) {
perror("pthread_join() failed");
}
}
}
...
Also always protect concurrent access to variables wich are written to, count here. To do so use a pthread_mutex_t variable.

Reading array from threads, c, cygwin

I'm pretty new to threads and would like some insight. I'm trying to get the percentage each thread has completed for its calculation. Each thread will report its percentage to a different element of the same array. I have this working with pthread_join immediately after pthread_create and a separate thread for reading all the values of the array and printing the percentage but when I have all threads running after each other without waiting for the previous one to finish I get some weird behavior. This is how I'm accessing the shared (global) array.
//global
int *currentProgress;
//main
currentProgress = malloc(sizeof(int)*threads);
for(i=0; i<threads; i++)
currentProgress[i] = 0;
//child threads
currentProgress[myId] = (int)percent; //myId is unique
//progress thread
for(i=0; i<threads; i++)
progressTotal += currentProgress[i];
progressTotal /= threads;
printf("Percent: %d", progressTotal);
This is essentially the code I think is not being used correctly for multi-threads. When I print out the state of the shared array, I notice that as soon as another thread starts accessing the array (different element though), the previous element immediately goes to some random number... -2147483648 and when the latter element finishes the prior element continues like normal. Should I be using semaphores for this? I thought I could access different elements of an array at the same time and I thought reading them wasn't an issue.
This is the entire code:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <stdint.h>
#include <pthread.h>
#include <string.h>
#define STDIN 0
int counter = 0;
uint64_t *factors;
void *getFactors(void *arg);
void *deleteThreads(void *arg);
void *displayProgressThread(void *arg);
int *currentProgress;
struct data
{
uint64_t num;
uint64_t incrS;
uint64_t incrF;
int threads;
int member;
} *args;
int main(int argc, char *argv[])
{
if(argc < 3) {printf("not enough arguments"); exit(1);}
int i;
int threads = atoi(argv[2]);
pthread_t thread_id[threads];
pthread_t dThread;
currentProgress = malloc(sizeof(int)*threads);
for(i=0; i<threads; i++)
currentProgress[i] = 0;
args = (struct data*)malloc(sizeof(struct data));
args->num = atoll(argv[1]);
args->threads = threads;
uint64_t increment = (uint64_t)sqrt((uint64_t)args->num)/threads;
factors = (uint64_t*)malloc(sizeof(uint64_t)*increment*threads);
pthread_create(&dThread, NULL, displayProgressThread, (void*)args);
//for the id of each thread
args->member = 0;
for(i=0; i<threads; i++)
{
args->incrS = (i)*increment +1;
args->incrF = (i+1)*increment +1;
pthread_create(&thread_id[i], NULL, getFactors, (void*)args);
usleep(5);
}
for(i=0; i<threads; i++)
{
pthread_join(thread_id[i], NULL);
}
sleep(1);
printf("done\n");
for (i=0; i<counter; i++)
printf("\n%llu : %llu", factors[++i], factors[i]);
return 0;
}
void *getFactors(void *arg)
{
uint64_t count;
int myId;
int tempCounter = 0, i;
struct data *temp = (struct data *) arg;
uint64_t number = temp->num;
float total = temp->incrF - temp->incrS, percent;
myId = temp->member++;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
for(count=temp->incrS; count<=temp->incrF; count++)
{
percent = (float)(count-temp->incrS)/total*100;
currentProgress[myId] = (int)percent;
if (number%count == 0)
{
factors[counter++] = count;
factors[counter++] = number/count;
}
usleep(1);
}
usleep(1);
pthread_exit(NULL);
}
void *displayProgressThread(void *arg)
{
struct data *temp = (struct data *) arg;
int toDelete = 0;
while(1)
{
int i;
int progressTotal = 0;
char *percent = malloc(sizeof(char)*20);
for(i=0; i<toDelete; i++)
printf("\b \b");
for(i=0; i<temp->threads; i++){
progressTotal += currentProgress[i];
}
progressTotal /= temp->threads;
printf("|");
for(i=0; i<50; i++)
if(i<progressTotal/2)
printf("#");
else
printf("_");
printf("| ");
sprintf(percent, "Percent: %d", progressTotal);
printf("%s", percent);
toDelete = 53 + strlen(percent);
usleep(1000);
fflush(stdout);
if(progressTotal >= 100)
pthread_exit(NULL);
}
}
There are some non synchronized pieces of code that are accessed by the threads which cause this problem.
One first place to be synchronized is:
myId = temp->member++;
But more importantly is that, the main thread is doing:
args->incrS = (i)*increment +1;
args->incrF = (i+1)*increment +1;
while at the same time in the threads:
for(count=temp->incrS; count<= temp->incrF; count++)
{
percent = (float)(count-temp->incrS)/total*100;
currentProgress[myId] = (int)percent;
if (number%count == 0)
{
factors[counter++] = count;
factors[counter++] = number/count;
}
usleep(1);
}
The unsynchronized accesses mentioned above affect the calculation of percent value which results in such abnormal happenings. You have to do synchronization in all these places in order to get the kind of behavior you would expect.

Resources