calling method from a new thread C - c

I'm working on a project (NOT HOMEWORK), building a multi-thread sudoku solution validator in C. I'm new to C so excuse the bad code quality as I'm still improving.
I want to call the method row_check 9 times from 9 separate threads. For the method as parameters I pass the row number (arg) and array name (arr). I have created the thread but I'm unsure how to pass the parameters properly to the method. Can anyone help me with this?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void* row_check(void* arg, int *arr)
{
int i = *((int *)arg); //trying to convert row number to int
int j, flag;
while(i < 9)
{
flag=0x0000;
for(j = 0; j < 9; j++)
flag |= 1 << (arr[i][j]-1);
if (flag != 0x01FF)
report("row", i, j-1);
}
}
void report(char *s, int i, int j)
{
printf("\nThe sudoku is INCORRECT");
printf("\nin %s. Row:%d,Column:%d", s, i+1, j+1);
getch();
exit(0);
}
int main(int argc, char* argv[])
{
int i,j;
char arr1[9][9];
FILE *file = fopen(argv[1], "r");
if (file == 0)
{
fprintf(stderr, "failed");
exit(1);
}
int col=0, row=0;
int num;
while(fscanf(file, "%d ", &num) == 1)
{
arr1[row][col] = num;
col++;
if(col == 9)
{
row++;
col = 0;
}
}
fclose(file);
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
int n;
for(n=0; n < 9; n++) //creating 9 threads
{
pthread_create(&tid, &attr, row_check, n);
pthread_join(tid, NULL);
}
return 0;
}

The thread entry function has to be of the format void *(*start_routine) (void *), which means it receives only one parameter - pointer to anything you like.
The most used technique is to define a struct with the values you want to pass to the thread entry function. Create a variable of that type, initialize it and pass its address to the thread entry function.
Example:
typedef thread_data_s
{
char *ptr;
int row_num; // I would prefer to define it as `unsigned int` but I stick to your example
// + any other data you want to pass to the thread
} thread_data_t;
....
thread_data_t data[NUM_OF_THREADS];
....
for(n=0; n < NUM_OF_THREADS; n++) //creating 9 threads
{
data[n].ptr = &arr1[n][0];
data[n].row_num = n;
pthread_create(&tid, &attr, row_check, &data[n]);
}
...
for(n=0; n < NUM_OF_THREADS; n++) // waiting for all the threads here
{
pthread_join(tid, NULL);
}
And your entry function should look something like this:
void* row_check(void* data)
{
//int i = *((int *)arg); //trying to convert row number to int
thread_data_t *my_data_ptr = data;
int j, flag;
while(i < 9)
{
flag=0x0000;
for(j = 0; j < 9; j++)
flag |= 1u << ( (my_data_ptr->ptr)[my_data_ptr->row_num][j] - 1 );
// Shouldn't it be under the `for` loop block? If so, please add `{}` to the `for` loop
if (flag != 0x01FF)
report("row", my_data_ptr->row_num, j-1);
}
return NULL;
}

Related

Sieve of Eratosthenes with multithreading in C/Linux

I am currently working on the calculation of the Eratosthenes Sieve using C multithreading.
The goal is to first create a main thread that uses a split function to divide the exploration of the numbers on a number of threads.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *creat_thread(int *nbThreads);
void *SieveEratosthenes(int *tailleTab);
int* tab;
int sizeTab;
int nbTachesParThread=0;
int main(void)
{
int nbThreads;
int n;
do{
printf("Enter an integer > 1 : ");
scanf("%d", &n);
} while(n<2);
sizeTab = n+1;
tab = (int*)malloc(tailleTab*sizeof(int));
for (unsigned int i=0; i<tailleTab; i++)
{
tab[i] = 1;
}
do{
printf("Enter a number positive number of threads : ");
scanf("%d", &nbThreads);
} while(nbThreads<1);
pthread_t threadPrincipal;
if (pthread_create(&threadPrincipal, NULL, creat_thread, NULL)) {
perror("pthread_create");
return EXIT_FAILURE;
}
if (pthread_join(threadPrincipal, NULL)) {
perror("pthread_join");
return EXIT_FAILURE;
}
printf("The Prime numbers are : \n");
for(unsigned int i=0; i<sizeTab; i++)
{
if(tab[i]==1)
{
printf("%d\n", (i));
}
}
}
void *creat_thread(int *nbThreads)
{
int nbTachesParThread = (int) sqrt(sizeTab) / nbThreads;
pthread_t* threads = (pthread_t*)malloc(nbThreads*sizeof(pthread_t));
int plageThreadi = nbTachesParThread;
for(int i = 0; i < nbThreads; ++i)
pthread_create (&threads[i], NULL, SieveEratosthenes, plageThreadi);
plageThreadi += nbTachesParThread;
}
void *SieveEratosthenes(int *plageThread)
{
for( int i=(plageThread - nbTachesParThread); i<=plageThread; i++)
{
if (tab[i] == 1)
{
for (int j = i*i; j<sizeTab; j += i)
{
tab[j]=0;
}
}
}
}
I tried to implement a code but I have an error at runtime:
segmentation error (core dumped)
On top of the issue mention in my comment here there is more to fix:
1st of all a PThread function needs to be of type void *(*)(void*). The ones used by the code are of type void *(*)(int*). Not good.
2ndly the code misses to join the work-threads, therefore the distributing thread ends after having created all workers, then it gets joined in main(), which then accesses the variables the workers are most likely are still working on causing undefined behaviour be doing so and then ends, ending the process. Ending the process cancels all worker-threads.
I followed your advice and created a structure to contain the variables that will be used by all threads.
However I noticed that sometimes it works (it displays the prime numbers well) but sometimes it doesn't work and it displays either only 0 or all the numbers from 0 to i.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *creat_thread(void* arg);
void *SieveEratosthenes(void* arg);
struct param
{
int* tab;
int sizeTab;
int nbTachesParThread;
int nbThreads;
int plageThreadi;
int plageThreadPrecedent;
};
int main(void)
{
struct param p;
int n;
do{
printf("Enter an integer > 1 : ");
scanf("%d", &n);
} while(n<2);
p.sizeTab = n+1;
p.tab = (int*)malloc(p.sizeTab*sizeof(int));
for (unsigned int i=0; i<p.sizeTab; i++)
{
p.tab[i] = 1;
}
do{
printf("Enter a number positive number of threads : ");
scanf("%d", &p.nbThreads);
} while(p.nbThreads<1);
pthread_t threadPrincipal;
if (pthread_create(&threadPrincipal, NULL, (void*)creat_thread, &p)) {
perror("pthread_create");
return EXIT_FAILURE;
}
if (pthread_join(threadPrincipal, NULL)) {
perror("pthread_join");
return EXIT_FAILURE;
}
printf("The Prime numbers are : \n");
for(unsigned int i=0; i<p.sizeTab; i++)
{
if(p.tab[i]==1)
{
printf("%d\n", i);
}
}
}
void *creat_thread(void* arg)
{
struct param *args = (void*)arg;
args->nbTachesParThread = (int) sqrt(args->sizeTab) / args->nbThreads;
pthread_t* threads = (pthread_t*)malloc(args->nbThreads*sizeof(pthread_t));
args->plageThreadi = args->nbTachesParThread;
for(int i = 0; i < args->nbThreads; ++i)
{
pthread_create (&threads[i], NULL, (void*)SieveEratosthenes, &(*args));
args->plageThreadPrecedent = args->plageThreadi;
args->plageThreadi += args->nbTachesParThread;
}
for(int i = 0; i < args->nbThreads; ++i)
{
pthread_join(threads[i], NULL);
}
pthread_exit(NULL);
}
void *SieveEratosthenes(void* arg)
{
struct param *args = (void *)arg;
for(int i=(args->plageThreadPrecedent); i<=args->plageThreadi; i++)
{
if (args->tab[i] == 1)
{
for (int j = i*i; j<args->sizeTab; j += i)
{
args->tab[j]=0;
}
}
}
pthread_exit(NULL);
}
In the main() function, move the calls to pthread_create() and pthread_join() outside of the if statement. These calls should be made regardless of whether or not the pthread_create() call succeeds.
In the SieveEratosthenes() function, the loop that marks composite numbers as 0 should start from i * i, not i. This is because any composite number can be written as the product of two prime numbers, and one of those prime numbers must be less than or equal to the square root of the composite number. Therefore, if a number i is composite, it must have a prime factor less than or equal to the square root of i.
In the creat_thread() function, move the call to pthread_join() inside the loop that creates the threads. This will ensure that each thread has completed before the next one is created.
In the creat_thread() function, initialize the plageThreadPrecedent variable to 2, since this is the first prime number.
I've modified my code so actually I have no more error code but once I have entered the 2 variables (number to calculate + number of threads), the program runs but displays nothing.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *creat_thread();
void *SieveEratosthenes();
int* tab;
int sizeTab = 0;
int nbTachesParThread=0;
int nbThreads = 0;
int plageThreadi = 0;
int plageThreadPrecedent = 0;
int main(void)
{
int n;
do{
printf("Enter an integer > 1 : ");
scanf("%d", &n);
} while(n<2);
sizeTab = n+1;
tab = (int*)malloc(sizeTab*sizeof(int));
for (unsigned int i=0; i<sizeTab; i++)
{
tab[i] = 1;
}
do{
printf("Enter a number positive number of threads : ");
scanf("%d", &nbThreads);
} while(nbThreads<1);
pthread_t threadPrincipal;
if (pthread_create(&threadPrincipal, NULL, creat_thread, NULL)) {
perror("pthread_create");
return EXIT_FAILURE;
}
if (pthread_join(threadPrincipal, NULL)) {
perror("pthread_join");
return EXIT_FAILURE;
}
printf("The Prime numbers are : \n");
for(unsigned int i=0; i<sizeTab; i++)
{
if(tab[i]==1)
{
printf("%d\n", (i));
}
}
}
void *creat_thread()
{
int nbTachesParThread = (int) sqrt(sizeTab) / nbThreads;
pthread_t* threads = (pthread_t*)malloc(nbThreads*sizeof(pthread_t));
int plageThreadi = nbTachesParThread;
for(int i = 0; i < nbThreads; ++i)
{
pthread_create (&threads[i], NULL, SieveEratosthenes, NULL);
pthread_join(threads[i], NULL);
plageThreadPrecedent = plageThreadi;
plageThreadi += nbTachesParThread;
}
for(int i = 0; i < nbThreads; ++i)
{
pthread_join(threads[i], NULL);
}
pthread_exit(NULL);
}
void *SieveEratosthenes()
{
for(int i=(plageThreadPrecedent); i<=plageThreadi; i++)
{
if (tab[i] == 1)
{
for (int j = i*i; j<sizeTab; j += i)
{
tab[j]=0;
}
}
}
pthread_exit(NULL);
}

How to make a code for critical section in c for n processes(Bakery algorithm)

I have got a project from my university for critical section problem of n processes. I have made a code for 2 processes in c But I could not figure out how to get it working for n process . The code is in C for linux threads.
Here is code for 2 Processes.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int flag[2];
int turn;
const int MAX = 1e9;
int ans = 0;
void lock_init(){
flag[0]=flag[1]=0;
turn = 0;
}
void lock(int self){
flag[self]=1;
turn = 1-self;
while(flag[1-self]==1 && turn == 1-self);
}
void unlock(int self){
flag[self]=0;
}
void* func(void *s){
int i=0;
int *limitptr = (int*) s;
int self = *limitptr;
printf("Thread %d in queue for critical section\n",self);
lock(self);
printf("Thread %d in critical section\n",self);
for(i=0;i<MAX;i++){
ans++;
}
printf("Thread %d done counting\n",self);
printf("Thread %d is exiting critical section\n",self);
unlock(self);
}
int main(){
pthread_t p1, p2;
int a=0,b=1;
lock_init();
pthread_create(&p1, NULL, func, &a);
pthread_create(&p2, NULL, func, &b);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
printf("Exiting Main\n");
return 0;
}
Any help would be appreciated.
Thank You. :)
use a mutex
#include <pthread.h>
declare the mutex like so:
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
then at the beginning of a critical section call:
pthread_mutex_lock( &myMutex );
and at the end of the critical section call:
pthread_mutex_unlock( &myMutex );
it does not matter how many threads are using that critical section, only one thread will be able to access it at a time
Thank You for your valuable time and answers.
I Found A solution for My problem and thought of sharing it.I Implemented Bakery Algorithm In C.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
int N;
int global = 10;
int entering[100];
int number[100];
int max(int number[100]) {
int i = 0;
int maximum = number[0];
for (i = 0; i < N; i++) {
if (maximum < number[i])
maximum = number[i];
}
return maximum;
}
void lock(int i) {
int j = 0;
entering[i] = TRUE;
number[i] = 1 + max(number);
entering[i] = FALSE;
for (j = 0; j < N; j++) {
while (entering[j]);
while (number[j] != 0 && (number[j] < number[i] || (number[i] == number[j]) && j < i)) {}
}
}
void unlock(int i) {
number[i] = 0;
}
void *fn(void *integer) {
int i = (int) integer;
lock(i);
printf("\n\n-----------Process %d---------",i);
printf("\nProcess %d is Entering Critical Section\n",i);
global++;
printf("%d is the value of global \n",global);
printf("Process %d is leaving Critical Section\n",i);
printf("----------------------------------\n\n");
unlock(i);
}
int main()
{
printf("Enter Number of Process\n");
scanf("%d",&N);
int th[N];
void *fn(void *);
pthread_t thread[N];
int i = 0;
for (i = 0; i < N; i++) {
th[i] = pthread_create(&thread[i], NULL, fn, (void *)i);
pthread_join(thread[i], NULL);
}
return EXIT_SUCCESS;
}
Again Thank You :)

reading in a file c small error big problems

I am trying to fill 2 matrices from 2 data text files but the compiler is telling me I have conflicting types for the "infiles" (1&2) but if I take out FILE I get a casting error and if I take out infile =fopen i get no output at all for matrices but it does compile. nothing seems to work right
the problem code:
FILE *infile1;
FILE *infile2;
*infile1 = (int)fopen("m1.dat","r");
*infile2 = (int)fopen("m2.dat","r");
full code:
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <pthread.h>
#define M 4
#define K 4
#define N 4
void *runner(void *param); /* the thread */
int A [M][K];
int B [K][N];
int C [M][N];
struct v {
int i; // row
int j; // column
};
int main(int argc, char *argv[]) {
//using namespace std;
//ifstream infile1 ("m1.dat");
//ifstream infile2 ("m2.dat");
int infile1 = (int)fopen("m1.dat","r");
int infile2 = (int)fopen("m2.dat","r");
FILE *infile1;
FILE *infile2;
//if (!infile1) //testing files
// cerr << "Error: could not open input file 1\n";
//if (!infile2) //testing files
//cerr << "Error: could not open input file 2\n";
if (!infile1) //testing files
fprintf(stderr, "file 1 missing\n");
exit(1);
if (!infile2) //testing files
fprintf(stderr, "file 2 missing\n");
exit(1);
int i, j, size1, size2 =0;
//infile1 >> size1;
//infile2 >> size2;
fscanf(infile1,"%d",&size1);
fscanf(infile2,"%d",&size2);
float s = (float)size1;
int dim = (int)sqrt(s);
for(i=0;i<M;i++){
for(j=0;j<N;j++){
//infile1 >> A[i][j];
// infile2 >> B[i][j];
fscanf(infile1,"%d",&A[i][j]);
fscanf(infile2,"%d",&B[i][j]);
}
}
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");
printf("%d \t",A[i][j]);
}
}
printf("\n\n");
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");;
printf("%d \t",B[i][j]);
}
}
printf("\n\n");
int count = 0;
for(i = 0; i < M; i++) { //column
for(j = 0; j < N; j++) { //row
//Assign a row and column for each thread
struct v *data = (struct v *) malloc(sizeof(struct v));
data->i = i;
data->j = j;
// Now create the thread passing it data as a parameter
pthread_t tid; //Thread ID
pthread_attr_t attr; //Set of thread attributes
//Get the default attributes
pthread_attr_init(&attr);
//Create the thread
pthread_create(&tid,&attr,runner,data);
//Make sure the parent waits for all thread to complete
pthread_join(tid, NULL);
count++;
}
}
//Print out the resulting matrix
for(i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
printf("\n \n");
fclose(infile1);
fclose(infile2);
return 0;
}
//The thread will begin control in this function
void *runner(void *param) {
struct v *data = (struct v*)param; // the structure that holds our data
int n, sum = 0; //the counter and sum
//Row multiplied by column
for(n = 0; n< K; n++){
sum += A[data->i][n] * B[n][data->j];
}
//assign the sum to its coordinate
C[data->i][data->j] = sum;
pthread_exit(0);
}
Edit: Latest version of code. Still just outputs nothing to the screen. Even have a printf that should run right before it closes and that doesnt even work. The only thing I did change from a working versiion(it used to do it correctly) was that the things related to the opening of the file were in C++ and I changed it to C. No idea why I don't get any errors though. Here is my latest full code. the output looks like this http://tinypic.com/r/21185u9/9
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <pthread.h>
#define M 4
#define K 4
#define N 4
void *runner(void *param); /* the thread */
int A [M][K];
int B [K][N];
int C [M][N];
struct v {
int i; // row
int j; // column
};
int main(int argc, char *argv[]) {
FILE *infile1 = fopen("m1.dat","r");
FILE *infile2 = fopen("m2.dat","r");
if (infile1 == NULL) //testing files
//if (!infile1) //testing files
//fprintf(stderr, "file 1 missing\n");
perror("File 1 Missing");
exit(1);
if (infile2 == NULL) //testing files
//if (!infile1) //testing files
//fprintf(stderr, "file 1 missing\n");
perror("File 2 Missing");
exit(1);
int i, j, size1, size2 =0;
fscanf(infile1,"%d",&size1);
fscanf(infile2,"%d",&size2);
float s = (float)size1;
int dim = (int)sqrt(s);
for(i=0;i<M;i++){
for(j=0;j<N;j++){
fscanf(infile1,"%d",&A[i][j]);
fscanf(infile2,"%d",&B[i][j]);
}
}
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");
printf("%d \t",A[i][j]);
}
}
printf("\n\n");
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");;
printf("%d \t",B[i][j]);
}
}
printf("\n\n");
int count = 0;
for(i = 0; i < M; i++) { //column
for(j = 0; j < N; j++) { //row
//Assign a row and column for each thread
struct v *data = (struct v *) malloc(sizeof(struct v));
data->i = i;
data->j = j;
// Now create the thread passing it data as a parameter
pthread_t tid; //Thread ID
pthread_attr_t attr; //Set of thread attributes
//Get the default attributes
pthread_attr_init(&attr);
//Create the thread
pthread_create(&tid,&attr,runner,data);
//Make sure the parent waits for all thread to complete
pthread_join(tid, NULL);
count++;
}
}
//Print out the resulting matrix
for(i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
printf("\n \n");
printf("program ran");
fclose(infile1);
fclose(infile2);
return 0;
}
//The thread will begin control in this function
void *runner(void *param) {
struct v *data = (struct v*)param; // the structure that holds our data
int n, sum = 0; //the counter and sum
//Row multiplied by column
for(n = 0; n< K; n++){
sum += A[data->i][n] * B[n][data->j];
}
//assign the sum to its coordinate
C[data->i][data->j] = sum;
pthread_exit(0);
}
Your error comes from declaring the return value from the file open function incorrectly.
Instead of using your problem code, use:
FILE *infile1 = fopen("m1.dat","r");
FILE *infile2 = fopen("m2.dat","r");
It declares infile1 and infile2 as pointers to the FILE type with the values properly set depending on how successful the file can be opened. In simple terms, call infile1 and infile2 as file handles.
If you want an integer value as the return value, you can look into the open() function instead of fopen(), but fopen() works well in your case.
If you check the exit status of your edited code, you will find that it is 1 due to exiting after the first file check. In your code you have:
if (infile1 == NULL) //testing files
//if (!infile1) //testing files
//fprintf(stderr, "file 1 missing\n");
perror("File 1 Missing");
exit(1);
Which will run the exit(1) function every time (even if infile1 is OK). You need to properly contain exit within the scope of your check with {...}. e.g.:
if (infile1 == NULL) { //testing files
perror ("File 1 Missing");
exit (1);
}
and the same for infile2. I have not checked the remainder of your code.

Segmentation fault without altering my program

I was trying to write a program that calculates prime numbers using threads and the program was working but not giving the desired results (it was telling all numbers were prime numbers). Today I tried to run the program again and I'm getting a segmentation fault even though I didn't alter my program. I tried using gdb to find when it was happening and I think it's happening on the pthread_join function.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int n_threads; // number of threads
int* numbers; // array of numbers
int elements_per_thread;
int isPrime(int n){
int i = 0;
for(i=0; i < n; i++)
if(n%i == 0)
return 0;
return 1;
}
void * threadPrime(void * arg){
int* idxp = (int*)arg;
int idx = *idxp;
int start = idx* elements_per_thread;
int finish = (idx+1)*elements_per_thread-1;
int i;
for(i=start; i<finish; i++)
if(!isPrime(i))
numbers[i]=0;
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("usage: %s largest_number number_threads\n", argv[0]);
return 1;
}
int largest_number = atoi(argv[1]); // value of the largest number to test for primality
int n_numbers = largest_number-1; // number of numbers to test
n_threads = atoi(argv[2]);
// create and fill vector of numbers to test
numbers = (int *)malloc(n_numbers*sizeof(int)) ; // allocate a vector for n_numbers integers
int i;
for (i = 2; i <= largest_number; i++)
numbers[i-2] = i;
int* id = (int *)malloc(n_threads*sizeof(int));
// compute primes
pthread_t* thid = (pthread_t *)malloc(n_threads*sizeof(int));
for(i=0;i<n_threads;i++){
id[i] = i;
if(pthread_create(&thid[i],NULL,threadPrime,(void*)(id+i)) != 0){
printf("Erro\n");
exit(0);
}
}
for(i=0;i<n_threads;i++){
if(pthread_join(thid[i],NULL) != 0){
printf("Erro\n");
exit(0);
}
}
// print result
printf("Primes:");
int n_primes = 0;
for (i = 0; i < n_numbers; i++)
if (numbers[i]) {
n_primes++;
printf (" %d", numbers[i]);
}
printf("\nTotal: %d primes\n", n_primes);
return 0;
}
Problem solved. Correct code below.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int n_threads; // number of threads
int* numbers; // array of numbers
int elements_per_thread;
int isPrime(int n){
int i = 0;
for(i=2; i < n; i++)
if(n%i == 0)
return 0;
return 1;
}
void * threadPrime(void * arg){
int* idxp = (int*) arg;
int idx = *idxp;
int start = idx*elements_per_thread;
int finish = (idx+1)*elements_per_thread;
int i;
for(i=start; i<=finish; i++)
if(!isPrime(numbers[i]))
numbers[i]=0;
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("usage: %s largest_number number_threads\n", argv[0]);
return 1;
}
int largest_number = atoi(argv[1]); // value of the largest number to test for primality
int n_numbers = largest_number-1; // number of numbers to test
n_threads = atoi(argv[2]);
// create and fill vector of numbers to test
numbers = (int *)malloc(n_numbers*sizeof(int)) ; // allocate a vector for n_numbers integers
int i;
for (i = 2; i <= largest_number; i++)
numbers[i-2] = i;
int* id;
id = (int *)malloc(n_threads*sizeof(int));
// compute primeselements_per_thread = n_numbers/n_threads;
elements_per_thread = (n_numbers/n_threads)+1;
pthread_t* thid = malloc(n_threads*sizeof(*thid));
for(i=0;i<n_threads;i++){
id[i] = i;
if(pthread_create(&thid[i],NULL,threadPrime,(void*)(id+i)) != 0){
printf("Erro\n");
exit(0);
}
}
for(i=0;i<n_threads;i++){
if(pthread_join(thid[i],NULL) != 0){
printf("Erro\n");
exit(0);
}
}
// print result
printf("Primes:");
int n_primes = 0;
for (i = 0; i < n_numbers; i++)
if (numbers[i]) {
n_primes++;
printf (" %d", numbers[i]);
}
printf("\nTotal: %d primes\n", n_primes);
return 0;
}
There are a number of issues:
1) The starting index for the loop should be 2. Otherwise, you are going to have divide by zero error here:
for(i=0; i < n; i++) // should be i=2
if(n%i == 0)
return 0;
2) elements_per_thread is not set at all. So it's going to be 0 (since it's a global variable) and the loops in thread function will never be called. Set it in main():
elements_per_thread = n_numbers/n_threads;
3) When you call isPrime() you are passing i. But you really wanted to pass numbers[i]. You also want to include the finish in the primality test. So it should be
for(i=start; i<=finish; i++)
if(!isPrime(numbers[i]))
numbers[i]=0;
4) The allocation for thread array is wrong. It should be
pthread_t* thid = malloc(n_threads * sizeof *thid);
There are more efficient ways to test primes (e.g. you only need to check upto n/2 to see if it's prime). But once you fix the above issues, you'll have a working code and think about improving it later.
You didn't allocate the right amount of memory for thid. This is the main reason for your segmentation fault.
pthread_t* thid = (pthread_t *)malloc(n_threads*sizeof(int));
should be
pthread_t* thid = malloc(n_threads*sizeof(p_thread));
(you don't need to cast malloc in C)
This is why I don't usually use an explicit type as the operand of sizeof, and instead just use the variable name so that the compiler can deduce the type itself.
pthread_t* thid = malloc(n_threads*sizeof(*thid));

threads to perform statistical calculations on list of numbers input on commad line?

I am trying to write a multi threaded program that takes a list of numbers from the command line and calculates various statistical values eg average, sum etc using separate worker threads. i have created three threads in this program and it compiles but i get errors. I am new to C and thread programming, please guide me in passing data to the thread for calculations?
This is my code:
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#define NUM_THREAD 3
int average, min, max;
void *
doSomeThing(void *param)
{
//int *id_ptr, taskid;
int *argv = (int *) param;
sleep(1);
//id_ptr=(int *) threadid;
//taskid= *id_ptr;
int j;
int sum = 0;
int upper = atoi(param);
sleep(1);
pthread_t id = pthread_self();
unsigned long i = 0;
if (id = 1) {
int i;
for (i = 0; i < upper; i++) {
sum += argv[i];
}
printf("sum of no's is :\n", sum);
}
if (id = 2) {
printf("\n Second thread processing\n");
}
if (id = 3) {
printf("\n Third thread processing\n");
}
for (i = 0; i < -1; i++);
{
pthread_exit(NULL);
}
}
int
main(int argc, char *argv[])
{
pthread_t threads[NUM_THREAD];
pthread_attr_t attr;
int *taskid[NUM_THREAD];
int i = 0;
int t;
int err;
//int input,a;
if (argc != 2) {
fprintf(stderr, "usage: a.out <integer value>\n");
return -1;
}
/*
printf("how many no's do u want to evaluate?:\n");
scanf("%d", &input);
printf("Enter the no's:\n");
for (a = 0; a < input; a++) {
arr[a] = (int) malloc(sizeof(int));
scanf("%d", &arr[a]);
printf("data:", &arr[a]);
}
*/
pthread_attr_init(&attr);
for (t = 0; t < NUM_THREAD; t++) {
taskid[t] = (int *) malloc(sizeof(int));
*taskid[t] = t;
printf("In main: creating thread %d\n", t);
err = pthread_create(&threads[t], &attr, doSomeThing, argv[1]);
if (err) {
printf("Error; return code from pthread_create() is %d\n",
err);
exit(-1);
}
}
for (t = 0; t < NUM_THREAD; t++) {
pthread_join(threads[t], NULL);
printf("Joining thread %d\n", t);
}
pthread_exit(NULL);
}
What makes you think pthread_create assigns a nice little number like 1, 2, 3 as a thread_id? When you call pthread_self(), it is unlikely that you will get 1, 2, or 3. Also you should eventually free the memory you obtained from malloc.
My suggestion is that you write a separate function for average, max, and min and call pthread_create explicitly 3 times passing in the 3 separate functions instead of using one function to do all.

Resources