Given this code:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
void *findPrimes(void *arg)
{
int val = *(int *)arg;
for (int i = val * 1000; i < val * 1000 + 1000; i++)
{
int isPrime = 1;
for (int j = 2; j < i; j++)
{
if (i % j == 0)
{
isPrime = 0;
break;
}
}
if (isPrime)
{
printf("%d\n", i);
}
}
pthread_exit(NULL);
}
int main()
{
pthread_t p[3];
int val[3] = {0, 1, 2};
for (int i = 0; i < 3; i++)
{
pthread_create(&p[i], NULL, findPrimes, &val[i]);
}
for (int i = 0; i < 3; i++)
{
pthread_join(p[i], NULL);
}
return 0;
}
Who prints in 3 threads all the prime number between 0 and 3000.
I want to print them in order, how can i do it?
My professor suggest to use an array of semaphore.
In order to synchronize the actions of all the threads I suggest using a pthread_mutex_t and a pthread_cond_t (a condition variable). You also need a way to share data between threads, so I'd create a struct for that:
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
typedef struct {
unsigned whos_turn;
pthread_mutex_t mtx;
pthread_cond_t cv;
} shared_data;
whos_turn will here be used to tell the threads whos turn it is to print the primes found.
Each thread also needs some thread-unique information. You called it val so I'll call it val here too. We can compare val with whos_turn to decide which thread it is that should print its result. In order to pass both the shared data and val to a thread, you can package that in a struct too:
typedef struct {
unsigned val;
shared_data *sd; // will point to the one and only instance of `shared_data`
} work_order;
Now, findPrimes need somewhere to store the primes it calculates before it's time to print them. Since the range to search is hardcoded, I'd just add an array for that:
#define SEARCH_RANGE (1000ULL)
void *findPrimes(void *arg) {
work_order *wo = arg;
uintmax_t primes[SEARCH_RANGE]; // to store the found primes
int found_count = 0;
for (uintmax_t i = wo->val*SEARCH_RANGE+1; i <= (wo->val+1)*SEARCH_RANGE; i += 2) {
bool isPrime = true;
for (uintmax_t j = 3; j < i; j += 2) {
if (i % j == 0) { // note: both i and j are odd
isPrime = false;
break;
}
}
if (isPrime) {
primes[found_count++] = i;
}
}
if(wo->val == 0) { // special case for the first range
primes[0] = 2; // 1 is not a prime, but 2 is.
}
// ... to be continued below ...
So far, nothing spectacular. The thread has now found all primes in its range and has come to the synchronizing part. The thread must
lock the mutex
wait for its turn (called "the predicate")
let other threads do the same
Here's one common pattern:
// ... continued from above ...
// synchronize
pthread_mutex_lock(&wo->sd->mtx); // lock the mutex
// only 1 thread at a time reaches here
// check the predicate: That is's this thread's turn to print
while(wo->val != wo->sd->whos_turn) { // <- the predicate
// if control enters here, it was not this thread's turn
// cond_wait internally "unlocks" the mutex to let other threads
// reach here and wait for the condition variable to get signalled
pthread_cond_wait(&wo->sd->cv, &wo->sd->mtx);
// and here the lock is only held by one thread at a time again
}
// only the thread whos turn it is reaches here
Now, the thread has reached the point where it is its time to print. It has the mutex lock so no other threads can reach this point at the same time.
// print the collected primes
for(int i = 0; i < found_count; ++i)
printf("%ju\n", primes[i]);
And hand over to the next thread in line to print the primes it has found:
// step the "whos_turn" indicator
wo->sd->whos_turn++;
pthread_mutex_unlock(&wo->sd->mtx); // release the mutex
pthread_cond_broadcast(&wo->sd->cv); // signal all threads to check the predicate
pthread_exit(NULL);
}
And it can be tied together quite neatly in main:
#define Size(x) (sizeof (x) / sizeof *(x))
int main() {
shared_data sd = {.whos_turn = 0,
.mtx = PTHREAD_MUTEX_INITIALIZER,
.cv = PTHREAD_COND_INITIALIZER};
pthread_t p[3];
work_order wos[Size(p)];
for (unsigned i = 0; i < Size(p); i++) {
wos[i].val = i; // the thread-unique information
wos[i].sd = &sd; // all threads will point at the same `shared_data`
pthread_create(&p[i], NULL, findPrimes, &wos[i]);
}
for (unsigned i = 0; i < Size(p); i++) {
pthread_join(p[i], NULL);
}
}
Demo
Related
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.
For a prime factorization project, I need to pass a struct and a number (from the command line) to a thread. The below code is what I have so far. The factorization works fine, the problem is that the index passed to the thread isn't being passed in order, so the results vary, often storing data in the same index in a subsequent thread. Anyone know how to guarantee which index the thread will access, or a better way of implementing this? Each thread has to store their data in a struct so that the main thread can print all the data at the end, once all threads have closed.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
// Initialize Constants
#define MAX_ARGS 25
#define MAX_PRIMES 10
#define SMALLEST_ARG 2
// Define Struct
struct PrimeData {
int index;
int num_to_fact[MAX_ARGS];
int primes[MAX_ARGS][MAX_PRIMES];
};
// Declare Functions
void* factor (void*);
// Main
int main(int argc, char* argv[])
{
// Initialize Struct Variables
struct PrimeData data;
struct PrimeData* data_addr = &data;
data.index = 0;
for (int i = 0; i < MAX_ARGS; i++)
data.num_to_fact[i] = -1;
for (int i = 0; i < MAX_ARGS; i++) {
for (int j = 0; j < MAX_PRIMES; j++)
data.primes[i][j] = -1;
}
// Check for arguments
if (argc <= 1)
printf("Usage: ./p3 <number to factor>...\n");
else {
// Initialize Thread Handler list
pthread_t threads[argc - 1];
// Create a Thread per Argument
for (int i = 1; i < argc; i++) {
// Update shares structure
data.index = i - 1;
data.num_to_fact[i - 1] = atoi(argv[i]);
// Create thread
pthread_create(&threads[i - 1], NULL, factor, (void*)data_addr);
}
// Tell main to wait for threads to terminate
for (int i = 1; i < argc; i++)
pthread_join(threads[i - 1], NULL);
}
// Iterate through struct
for (int i = 0; i < MAX_ARGS; i++) {
if (data.num_to_fact[i] == -1)
break;
printf("%d: ", data.num_to_fact[i]);
for (int j = 0; j < MAX_PRIMES; j++) {
if (data.primes[i][j] == -1)
break;
printf("%d ", data.primes[i][j]);
}
printf("\n");
}
// Terminate
return 0;
}
// The factor() function
void* factor(void* data)
{
struct PrimeData* d = (struct PrimeData*)data;
int index = d->index;
int n = d->num_to_fact[index];
int counter = 0;
int i = 2;
while (n != 1) {
if (n % i == 0) {
while (n % i == 0) {
d->primes[index][counter] = i;
n = n / i;
counter++;
}
}
i++;
}
return NULL;
}
You have only one 'struct PrimeData data;', so there is no point in signaling the address of it in the pthread_create call. The messy way would be to globalize 'PrimeData' so the threads have access to it, array-ize the index: 'int index[MAX_ARGS];', load it with 0,1,2,3.. etc and then pass the address of the required index to each thread, eg '&data_addr[i-1]'.
It might be clearer if you accepted that C arrays are indexed from zero and so get rid of a lot of those [i-1] things.
I got it working using a mutex. Kind of odd, we do not cover mutexes until the next chapter. I eventually stumbled upon an article explaining that when you use multithreading where each thread is accessing a shared memory location (my struct in this case) then you have to use a mutex control the index:
// At the start of the program, before main
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int _index = -1;
// first three lines of the factor function
pthread_mutex_lock(&mutex1);
_index++;
pthread_mutex_unlock(&mutex1);
// Define Struct
struct PrimeData {
int num_to_fact[MAX_ARGS];
int primes[MAX_ARGS][MAX_PRIMES];
};
typedef struct Wrapper {
int index;
struct PrimeData *data;
} Wrapper;
...
int main(int argc, char *argv)
{
// ...
// Define wrappers
Wrapper wrappers[argc-1];
for (int i = 1; i < argc; i++)
{
wrappers[i-1].index = i;
wrappers[i-1].data = &data;
//...
pthread_create(&threads[i - 1], NULL, factor, wrappers + i - 1);
}
// ...
}
void *factor(void *wrapper)
{
Wrapper *w = (Wrapper *) wrapper;
struct PrimeData* d = w->data;
int index = w->index;
// ...
}
I'm using pthreads in C in order to perform two operations on an int array: one operation doubles the value of a cell, the other operation halves the value of the cell. If after doubling a cell its value will become greater than the max allowed value the thread needs to wait until another thread will halve the value of that cell. The way I initialized the array is that the first 5 cells have value that is very close to max allowed and the other five have a value far from the max.
I decided to use a global mutex and condition variable for this. In the main first spawn 10 doubler threads then another 10 halver threads. But then my program freezes. I can't understand what the problem is, any help is appreciated.
My motivation is to better understand pthreads and condition variables.
This is the code:
#include <stdio.h>
#include <stdlib.h>
#include <ntsid.h>
#include <pthread.h>
#include <unistd.h>
#define MAX 20
#define THREADS_NUM 10
#define OFFSET 10
typedef struct myStruct {
int cellId;
} myStruct;
int * cells;
pthread_mutex_t globalMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t globalCond = PTHREAD_COND_INITIALIZER;
pthread_t threads[THREADS_NUM * 2];
void * DoublerThread(void * arg) {
myStruct * myStr = (myStruct *) arg;
int id = myStr->cellId;
pthread_mutex_t mutex = globalMutex;
pthread_cond_t condition = globalCond;
pthread_mutex_lock(&mutex);
while((cells[id] * 2) > MAX) {
printf("Waiting... id = %d\n", id);
pthread_cond_wait(&condition, &mutex);
}
cells[id] *= 2;
printf("new val = %d, id = %d\n", cells[id], id);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void * HalverThread(void * arg) {
myStruct * myStr = (myStruct *) arg;
int id = myStr->cellId;
pthread_mutex_t mutex = globalMutex;
pthread_cond_t condition = globalCond;
sleep(1);
pthread_mutex_lock(&mutex);
cells[id] /= 2;
pthread_cond_broadcast(&condition);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
void initMyStructs(myStruct ** myStructs) {
int i;
for(i = 0; i < THREADS_NUM * 2; i++) {
myStructs[i] = (myStruct *) malloc(sizeof(myStruct) * 2);
if(!myStructs[i]) {
printf("malloc error\n");
exit(EXIT_FAILURE);
}
myStructs[i]->cellId = i % THREADS_NUM;
}
}
void initCells() {
int i, tmp;
cells =(int *) malloc(sizeof(int));
if(!cells) {
printf("malloc error\n");
exit(EXIT_FAILURE);
}
for(i = 0; i <= THREADS_NUM; i++) {
if(i < THREADS_NUM / 2) {
cells[i] = MAX - 1;
} else {
tmp = cells[i] = 1;
}
}
}
int main() {
int i;
myStruct ** myStructs;
initMyStructs(myStructs);
initCells();
//create 10 Doubler threads
for(i = 0; i < THREADS_NUM; i++) {
pthread_create(&threads[i], NULL, DoublerThread, (void *) myStructs[i]);
}
//create 10 Halver threads
for(i = 0; i < THREADS_NUM; i++) {
pthread_create(&threads[i + OFFSET], NULL, HalverThread, (void *) myStructs[i + OFFSET]);
}
for(i = 0; i < THREADS_NUM + OFFSET; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
You have made “private” mutexes and condition variables for each thread, so they are not synchronizing in any (meaningful) way. Rather than this:
pthread_mutex_t mutex = globalMutex;
pthread_cond_t condition = globalCond;
Just use the globalMutex, and globalCond -- that is what you actually want.
[
I moved this in here, because I think we are supposed to. I can't intuit SO-iquette.
]
By the way, just to make sure I understand this, the mutex is per
cell, so that multiple threads can work on multiple cells
simultaneously, right? Just not two threads on the same cell. –
So, what you probably want is something more like:
typedef struct myStruct {
int cellId;
pthread_mutex_t lock;
pthread_cond_t wait;
} myStruct;
and in InitMyStruct():
myStructs[i]->cellId = i % THREADS_NUM;
pthread_mutex_init(&myStructs[i]->lock, NULL);
pthread_cond_init(&myStructs[i]->wait, NULL);
and in Halvers:
pthread_mutex_lock(&myStr->lock);
cells[id] /= 2;
pthread_cond_broadcast(&myStr->wait);
pthread_mutex_unlock(&myStr->lock);
and Doubler:
...
pthread_mutex_lock(&myStr->lock);
while((cells[id] * 2) > MAX) {
printf("Waiting... id = %d\n", id);
pthread_cond_wait(&myStr->wait, &myStr->lock);
}
cells[id] *= 2;
printf("new val = %d, id = %d\n", cells[id], id);
pthread_mutex_unlock(&myStr->lock);
So currently, only one thread can make changes to the array at a time?
But then the program exits after about a second, if threads couldn't
be making changes to the array simultaneously then wouldn't the
program take 10 seconds to finish, because each HalverThread sleeps
for 1 second. – Yos 6 hours
The Halvers sleep before grabbing the mutex, thus all sleep near simultaneously, wake up, fight for mutex and continue.
Need help how to prevent the deadlock for the code in blow i have written. or any suggestion i need to fix the code in order to get rid of deadlock?
also when i run in Linux i got a Segmentation fault (core dumped).
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#include <semaphore.h>
int cnt;
int *bites;
int *old_bites;
sem_t *sticks;
void *roger(void *arg) {
int rog = *(int*)arg;
for(;;) {
sem_wait(&(sticks[rog])); // left
sem_wait(&(sticks[(rog + 1) % cnt])); // right
bites[rog]++;
sem_post(&(sticks[(rog + 1) % cnt])); // right
sem_post(&(sticks[rog])); // left
}
pthread_exit(NULL);
return NULL;
}
int main(int argc, char *argv[]) {
int i;
pthread_t *rogers;
int *pos;
cnt = (int)strtol(argv[1], NULL, 10);
rogers = (pthread_t *)calloc(cnt, sizeof(pthread_t));
pos = (int *)malloc(cnt * sizeof(int));
bites = (int *)calloc(cnt, sizeof(int));
old_bites = (int *)calloc(cnt, sizeof(int));
sticks = (sem_t *)calloc(cnt, sizeof(sem_t));
for(i = 0; i < cnt; i++) {
sem_init(&(sticks[i]), 0, 1);
}
for(i = 0; i < cnt; i++) {
pos[i] = i;
pthread_create(&(rogers[i]), NULL, roger, (void *)&pos[i]);
}
for(;;) {
bool dead = true;
usleep(50000);
for(i = 0; i < cnt; i++) {
if(bites[i] != old_bites[i]) {
dead = false;
}
}
if(dead) {
exit(EXIT_SUCCESS);
}
for(i = 0; i < cnt; i++) {
printf("%8X", bites[i]);
}
printf("\n");
for(i = 0; i < cnt; i++) {
old_bites[i] = bites[i];
}
}
for(i = 0; i < cnt; i++) {
pthread_join(rogers[i], NULL);
}
for(i = 0; i < cnt; i++) {
sem_destroy(&(sticks[i]));
}
exit(EXIT_SUCCESS);
}
yes I would expect this to deadlock. I don't know what you're using for cnt, but let's pretend it's 1. In this case, only 1 thread will get created. This thread will sem_wait(&(sticks[0]));. Then in the very next line it will sem_wait(&(sticks[(0+1) % 1 == 0]));. Since the initial value of your semaphores are 1, you can't wait on the same semaphore twice without a sem_post first. Thus, this thread will wait forever for a sem_post that it can't reach because it's sem_waiting.
Now consider the case where cnt > 1 (let's just say cnt == 2 to make it simpler). This will spawn thread0 and thread1 with 0 and 1 passed as arguments to their functions. This situation could happen:
Thread0 executes sem_wait(&(sticks[0]));
Context switch: thread1 executes sem_wait(&(sticks[1]));
thread1 executes sem_wait(&(sticks[(1+1) % 2 == 0])); // this blocks because thread0 has already sem_wait'ed this semaphore to 0
Context switch: thread0 executes sem_wait(&(sticks[(0+1) % 2 == 1])); // this blocks because thread1 has already sem_wait'ed this semaphore to 0
Now you have each thread waiting for a sem_post from the other before you can continue ==> deadlock. I would expect this scenario to scale for increasing values of cnt, although the situations that would lead to deadlocks would become more complex.
Why are you using 2 semaphores to protect a single resource? This theory sounds wrong to me. You lose your atomicity with that approach (correct me if I'm wrong obviously).
Also, you have a race condition with your bites array. The main thread isn't observing synchronization before it reads from it. This may be related to the seg fault.
i hope i will put my question very clear, i am programming pthread,Briefly i calculate the number of threads needed, and pass created threads to a function and back, the function does transpose on different blocks; so each thread has its own block.
To check that im sending different threads, i run pthread_t self_t, but face two problems:
that seems only one same thread is used, and that i always have warning message about the type output of selt_t, below code simplified showing main pints.
any ideas where i went wrong ?
First here struct and main:
pthread_mutex_t mutexZ; // Mutex initialize
int array[nn][nn];
struct v
{
int i, j; // threaded Row,Col
int n, y; //
int iMAX; //
};
void *transposeM(void *arg);
int main(int argc, char *argv[])
{
int Thread_Num = 10;
pthread_t t_ID[Thread_Num]; // the number of threads depending on # blocks
printf("Thread_Num %d\n", Thread_Num);
struct v *data = (struct v *) malloc(sizeof(struct v));
int i, j; //loop varables
//#############################################################
printf("Matrix Initial before Transpose Done\n");
// printing the Matrix Before any transpose if needed testing
for (i = 0; i < nn; i++){
for(j = 0; j< nn; j++){
array[i][j] = i*nn + j;
printf("%d ", array[i][j]);
}
printf("\n");}
//************************************************************/
// Initialize the mutex
pthread_mutex_init(&mutexZ, NULL);
pthread_attr_t attr; //Set of thread attributes
pthread_attr_init(&attr);
int n, y; // Loop Variables for tiling
//************************************************************/
//Start of loop transpose:
int start = 0;
for (n = 0; n < nn; n += TILE)
{
data->n = n; // row
for (y = 0; y <= n; y += TILE) {
data->y = y; // column
printf("y Tile:%d \n", y);
printf("Start before:%d \n", start);
//Transpose the other blocks, thread created for each Block transposed
pthread_create(&(t_ID[start]), NULL, transposeM, (void*) data); // Send the thread to the function
pthread_join(t_ID[start], NULL);
if (start < Thread_Num)
{
start = start + 1;
}
printf("Start after:%d \n", start);
} // End the Y column TileJump loop
} // End of n Row TileJump loop
}
Modified according to the notes,
void *transposeM(void *arg)
{
// Transposing the tiles
struct v *data = arg;
int i, j; //loop row and column
int temp = 0;
pthread_mutex_lock(&mutexZ); //lock the running thread here,so keeps block until thread that holds mutex releases it
pthread_t self_t; // To check the thread id - my check not Mandetory to use
self_t = pthread_self();
printf("Thread number Main = %u \n ", self_t); //here we used u% coz seems the pthread_t is unsigned long data type
//*******************************************************
//here some function to work
//########################################################
pthread_mutex_unlock(&mutexZ);
pthread_exit(NULL);
return (NULL);
} // End
There are two conceptual issues with your code:
You pass the same reference/addrerss to each thread, making each thread work on the same data.
You join the thread immediately after having created it. As joining block until the thread to be joined ended, this sequentialises the running of all threads.
To get around 1. created a unique instance of what data points to for each thread.
To fix 2. move the call to pthread_join() out of the loop creating the threads and put it in a 2nd loop run after creation-loop.
...
printf("Thread_Num %d\n", Thread_Num);
pthread_t t_ID[Thread_Num]; // the number of threads depending on # blocks
struct v data_ID[Thread_Num] = {0}; // define an instance of data for ech thread
...
for (n = 0; n < nn; n += TILE) //limit of row
{
struct v * data = data_ID + start; // assign thread specific instance
data->n = n; // row
for (y = 0; y <= n; y += TILE) // limit of column -here removd the =n, then diagonal tile is not transposed
{
...
pthread_create(&(t_ID[start]), NULL, transposeM, (void*) data); // Send the thread to the function
...
}
} // End the Y column TileJump loop
for (;start >= 0; --start)
{
pthread_join(t_ID[start], NULL);
}
...
Modifications to the thread function:
void *transposeM(void *arg)
{
struct v *data = arg;
...
pthread_t self = pthread_self(); // better naming
...
pthread_exit(NULL); // the thread functions exits here.
return NULL; // this is never reached, but is necessary to calm down thr compiler.
} // End