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);
}
Related
During this lockdown period, you are playing Ludo with your n number of family members where, n<=4. Assume that all the tokens are in the starting square and consider following scenarios: If the outcome of the dice is 6(six), then you can move your one token and get the chance to play dice again; otherwise, you can move your one token and give the dice to the next
player. Think of the players as processes which should be synchronized. You are
required to write a code for it using semaphore.
What I've tried is:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
sem_t *S;
pthread_mutex_t mutex;
int *play, n;
void check(int pid) {
six:
int num = (rand() % 6) + 1;
printf("Player %d rolled and got %d\n", pid + 1, num);
if(num == 6) goto six;
sem_post(&S[pid]); //only for next()
}
void roll(int pid) {
pthread_mutex_lock(&mutex);
check(pid);
pthread_mutex_unlock(&mutex);
sem_wait(&S[pid]);
}
void next(int pid) {
pthread_mutex_lock(&mutex);
int next = (pid+1)%n;
printf("Player %d passed the die to %d\n", pid + 1, next + 1);
check(next);
pthread_mutex_unlock(&mutex);
}
void *player(void *num) {
for (int i = 0; i < n; i++) {
roll(*((int *)num));
next(*((int *)num));
}
}
int main() {
printf("Enter No. of players : ");
scanf("%d",&n);
pthread_t pid[n];
pthread_mutex_init(&mutex, NULL);
S = malloc(n*sizeof(sem_t));
play = malloc(n*sizeof(int));
for(int i = 0; i < n; i++){
play[i] = i;
sem_init(&S[i], 0, 0);
}
for (int i = 0; i < n; i++)
pthread_create(&pid[i], NULL, player, &play[i]);
for (int i = 0; i < n; i++)
pthread_join(pid[i], NULL);
pthread_mutex_destroy(&mutex);
for (int i = 0; i < n; i++)
sem_destroy(&S[i]);
return 0;
}```
This is the output : https://i.stack.imgur.com/ZaNUC.png
I want to rectify the sequence by making the one rolling person is the one whom the die is passed.
What I need to do is calculate the square sum of an array. The array and the number of threads must be given by the user, and we assume the number of elements and the number of threads are integrally divided.
My code doesn't even compile.. I know I have issues with the pointers, and I should place mutexes but I don't know where exactly. Can you point me to the right direction? I will appreciate it a lot.
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
int part = 0;
int local_elements = 0;
void* square_sum(void* arg)
{
int local_sum = 0;
int *element_array[] = (int *)arg;
//Each thread computes its part
int thread_part = part++;
for (int i = thread_part * loc_elements; i < (thread_part + 1)*loc_elements; i++) {
local_sum += element_array[i] * element_array[i];
}
return (void*)&local_sum;
}
main()
{
int threads, total_elements;
int i;
int total_sum = 0;
printf("Give the number of threads: ");
scanf("%d", &threads);
printf("Give the number of the elements you want: ");
scanf("%d", &total_elements;)
int element_array[total_elements];
//How many elements each thread gets
local_elements = total_elements / threads;
printf("Give the %d elements \n", total_elements);
for (i = 0; i < total_elements; i++) {
printf("No. %d:", i);
scanf("%d", &element_array[i]);
}
pthread_t newthread[threads];
//Creating the threads
for (int i = 0; i < threads; i++) {
//The start routine gets the whole element_array
pthread_create(&newthread[i], NULL, square_sum, &element_array);
}
int loc_sum;
//Waiting for each thread to finish and creating the total_sum
for (int i = 0; i < threads; i++) {
pthread_join(newthread[i], &loc_sum);
total_sum += loc_sum;
}
printf("The total sum is: %d", &total_sum);
}
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 :)
I'm working on a small program of multithreaded matrix multiplication. My first job is to fill the entry of matrices with a random integer. I met some segment faults after I tried to pass a function pointer to pthread_create. And I think the problem is in function pthread_join.
But there are two issues in general.
The first one is the segment fault does not happen every time. Sometimes the code works, but most of the times it doesn't. So it really confuses me.
The other one is when the code is working, there are always several entries still not initialized, especially for matrix[0][0], it is never initialized. And I don't quite know where to debug that one.
Here's my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#define N 5
#define MAX 10
int A[N][N];
int B[N][N];
int C[N][N];
pthread_t pid[N][N];
typedef struct {
int row, col;
} Pos;
typedef void* (*thread_func)(void*);
void print_matrix(int M[][N]) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
printf("%3d", M[i][j]);
if (j < N - 1) {
printf(", ");
}
}
printf("\n");
}
}
void join_threads(void) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
pthread_join(pid[i][j], NULL);
}
}
}
void* fill_entry(void* arg) {
Pos* pos = (Pos*)arg;
A[pos->row][pos->col] = rand() % MAX;
B[pos->row][pos->col] = rand() % MAX;
return NULL;
}
void dispatch_jobs(thread_func job_func) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
Pos pos;
pos.row = i;
pos.col = j;
if (pthread_create(&pid[i][j], NULL, job_func, (void*)&pos)) {
perror("pthread_create");
exit(-1);
}
}
}
}
int main(void) {
srand(time(NULL));
dispatch_jobs(&fill_entry);
join_threads();
printf("Matrix A:\n");
print_matrix(A);
printf("Matrix B:\n");
print_matrix(B);
return 0;
}
Pos pos;
pos.row = i;
pos.col = j;
if (pthread_create(&pid[i][j], NULL, job_func, (void*)&pos)) {
perror("pthread_create");
exit(-1);
}
You are passing a pointer to a local variable to the threads. Once the thread tries to access the data, i.e. dereferences the pointer, the variable is long gone, reused, and contains garbage data.
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));