This had a previous question regarding multi thread issues Here. Now the issue is that the program exits without any input. The program gets the input from a text file given as arguments with executing. It should only contain numbers separated by spaces and if theres any other character it should give an error as done in row_check functions. Can anyone suggest why it would exit without any error ?.
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<ncurses.h>
const unsigned int NUM_OF_THREADS = 9;
typedef struct thread_data_s {
char *ptr;
int row_num;
} thread_data_t;
void report(const char *s,int w,int q);
void* row_check(void* data)
{
thread_data_t *my_data_ptr = data;
int j, flag;
flag=0x0000;
for(j = 0; j < 9; j++)
{
flag |= 1u << ( (my_data_ptr->ptr)[j] - 1 );
if (flag != 0x01FF){
report("row", my_data_ptr->row_num, j-1);
}
}
return NULL;
}
void report(const char *s,int w,int q)
{
printf("\nThe sudoku is INCORRECT");
printf("\nin %s. Row:%d,Column:%d",s,w+1,q+1);
getchar();
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, "%c ", &num) ==1) {
arr1[row][col] = num;
col++;
if(col ==9)
{
row++;
col = 0;
}
}
fclose(file);
int n;
thread_data_t data[NUM_OF_THREADS];
pthread_t tid;
pthread_attr_t attr;
for(n=0; n < NUM_OF_THREADS; n++)
{
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++)
{
pthread_join(tid, NULL);
}
return 0;
}
The following in one of the issues in the code and it would explain why the application exists so soon...
The following code doesn't join all the threads it creates (so the application exits and terminates the threads before they finished running):
thread_data_t data[NUM_OF_THREADS];
pthread_t tid;
pthread_attr_t attr;
for(n=0; n < NUM_OF_THREADS; n++)
{
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++)
{
pthread_join(tid, NULL);
}
As you can see, the code is only saving the pointer to one of the threads (the value in tid is always replaced, overwriting the existing data) and joining that thread (instead of all of them).
This might be better constructed as:
thread_data_t data[NUM_OF_THREADS];
pthread_t tid[NUM_OF_THREADS];
for(n=0; n < NUM_OF_THREADS; n++)
{
data[n].ptr = &arr1[n][0];
data[n].row_num = n;
pthread_create(tid + n, NULL, row_check, &data[n]);
}
for(n=0; n < NUM_OF_THREADS; n++)
{
pthread_join(tid[n], NULL);
}
This way the application will wait for all the threads to complete their tasks (and report any errors) before returning.
Can anyone suggest why it would exit without any error ?.
Yes,
the posted code has no action when all 9 rows of the puzzle result are correct, it just gracefully exits.
and to further muddy the logic.
The posted code only checks the last thread created, and when that thread exits, the program exits, That does not mean the other threads have exited
One further serious detail. the call to pthread_create() is passing the address of the attr variable, but that variable contains what ever trash is/was on the stack where that variable was declared. Since the code is not setting any specific attributes for the threads, strongly suggest eliminate the variable and simply use NULL in the second parameter to pthread_create()
Related
Im trying to make a mini threads game, should be a manager thread that create amount of thread as the user want, and for every round (the user choose the amount of rounds) the threads need to random number, and after all the threads finished to random number the managerGame thread should print the thread that random the greatest number and add point to this thread.
At the end of the game the ManagerGame thread should print who is the winner.
Now i wrote the next code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
struct Player{
int isFinished;
int id;
int number;
};
struct GameManager{
struct Player *Players;
int *WinnersTable;
int Rounds;
};
struct GameDetails{
int PlayersCount;
int RoundsCount;
};
struct GameManager game_manager;
pthread_mutex_t lock;
pthread_cond_t cond;
int IsGameActive;
void* ManagerGameFunc(void* gameDetails);
void* PlayerFunc(void* playerDetails);
void SetWinnerToRound(int roundNumber, int playersCount);
void StartNewRound(int playersCount);
void printWinnerToGame(int playersCount);
int IsRoundEnded(int playersCount);
int main(){
srand(time(NULL));
pthread_t ManagerThread;
pthread_mutex_init(&lock, NULL);
pthread_cond_init(&cond, NULL);
struct GameDetails gameDetails;
printf("----GAME----\n");
printf("Enter amount of players\n");
fflush(stdin);
scanf("%d\n", &gameDetails.PlayersCount);
printf("Enter amount of rounds\n");
fflush(stdin);
scanf("%d\n", &gameDetails.RoundsCount);
printf("----GAME STARTED----\n");
pthread_create(&ManagerThread, NULL, ManagerGameFunc, &gameDetails);
pthread_join(ManagerThread, NULL);
printf("Game finished\n");
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
}
void* ManagerGameFunc(void* gameDetails){
struct GameDetails game_details = *((struct GameDetails *)gameDetails);
pthread_t *threads = (pthread_t *)malloc(game_details.PlayersCount * sizeof(pthread_t));
game_manager.Players = (struct Player *)malloc(game_details.PlayersCount * sizeof(struct Player));
game_manager.WinnersTable = (int *)malloc(game_details.PlayersCount * sizeof(int));
game_manager.Rounds = game_details.RoundsCount;
IsGameActive = 1;
for(int i = 0; i < game_details.PlayersCount; i++){
game_manager.Players[i].isFinished = 0;
game_manager.Players[i].id = i;
pthread_create(&threads[i], NULL, PlayerFunc, &game_manager.Players[i]);
}
for(int i = 0; i < game_manager.Rounds; i++){
pthread_mutex_lock(&lock);
while(!IsRoundEnded(game_details.PlayersCount)){
pthread_cond_wait(&cond, &lock);
}
SetWinnerToRound(i + 1, game_details.PlayersCount);
StartNewRound(game_details.PlayersCount);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
IsGameActive = 0;
printf("\nGame end ! The winner of the game is ...\n");
printWinnerToGame(game_details.PlayersCount);
}
void* PlayerFunc(void* playerDetails){
struct Player player = *((struct Player *)playerDetails);
while(IsGameActive){
pthread_mutex_lock(&lock);
while(player.isFinished){
pthread_cond_wait(&cond, &lock);
}
player.number = (rand() % (100 - 1 + 1)) + 1;
printf("%d", player.number);
player.isFinished = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
void SetWinnerToRound(int roundNumber, int playersCount){
int max = game_manager.Players[0].number;
int id = 0;
for(int i = 1; i < playersCount; i++){
if(game_manager.Players[i].number > max){
max = game_manager.Players[i].number;
id = i;
}
}
printf("--Round %d: winner is player number %d--\n", roundNumber, id + 1);
game_manager.WinnersTable[id]++;
}
void StartNewRound(int playersCount){
for(int i = 1; i < playersCount; i++){
game_manager.Players[i].isFinished = 0;
}
}
void printWinnerToGame(int playersCount){
int max = game_manager.Players[0].number;
int id = 0;
for(int i = 1; i < playersCount; i++){
if(game_manager.Players[i].number > max){
max = game_manager.Players[i].number;
id = i;
}
}
printf("Player number %d is the winner of the game !!\n", id + 1);
}
int IsRoundEnded(int playersCount){
for(int i = 0; i < playersCount; i++)
if(!game_manager.Players[i].isFinished)
return 0;
return 1;
}
But the problem is that when i run it the output is
the image is in the link
and the terminal is stuck like it show in the image.
I think that maybe the threads is in deadlock mode, isnt it?
Thank you for your help!
UPDATE
So I heard to #n.m. and to #pilcrow, and in PlayerFunc i changed the Player object to pointer to the argument cause before the change the function made a copy of the argument and every time i tried to change something in the object it didnt change in the PlayerThread. In addition i changed the pthread_cond_signal to pthread_cond_broadcast and now it work. Thank you all!
void* PlayerFunc(void* playerDetails){
struct Player player = *((struct Player *)playerDetails);
....
PlayerFunc creates a copy of its argument representing that thread/player's state. ManagerGameFunc will never see modifications to that copy, in particular whether it isFinished or not.
All your threads follow the same pattern:
pthread_mutex_lock(&lock);
while(!predicate(....)){
pthread_cond_wait(&cond, &lock);
}
....
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
First time through the loop all predicates are false. All threads therefore peacefully sleep in pthread_cond_wait. It is never signalled, because neither thread has a chance to progress and signal it. So they wait forever.
I am attempting to create threads and pass each thread the value from a for loop. Here is the code segment
pthread_t *threadIDs;
int i = 0;
if(impl == 1)
{
threadIDs = (pthread_t *)malloc(sizeof(pthread_t)*reduces);
for(;i < reduces; i++)
{
pthread_create(&threadIDs[i], NULL, reduce,&i);
}
}
It is not passing the correct values of the loop, which makes sense since I am creating a race condition. What is the simplest way to pass the correct value of i from my loop?
Another question, will each thread finish executing before the next one is created and called?
You've already dynamically created an array of thread IDs. Do the same for the values you want to pass in.
pthread_t *threadIDs;
int *values;
int i = 0;
if(impl == 1)
{
threadIDs = malloc(sizeof(pthread_t)*reduces);
values = malloc(sizeof(int)*reduces);
for(;i < reduces; i++)
{
values[i] = i;
pthread_create(&threadIDs[i], NULL, reduce, &values[i]);
}
}
Each thread will be working with a different array member, so there's no race condition.
You can define a structure and assign i to the variable of the object.
#include <stdio.h>
#include <pthread.h>
typedef struct Param_ {
int index;
}Param;
static void* thread(void* p) {
Param* param = p;
printf("index: %d\n", param->index);
}
int main() {
int i = 0;
int reduces = 10;
pthread_t *threadIDs;
threadIDs = (pthread_t *)malloc(sizeof(pthread_t)*reduces);
for(; i < reduces; i++)
{
Param* p;
p = (Param*)malloc(sizeof(*p));
p->index = i;
pthread_create(&threadIDs[i], NULL, thread, p);
}
return 0;
}
What is the simplest way to pass the correct value of i from my loop?
What is to be considered "simple" depends on the use case, so here another approach to solve the issues you present:
#include <pthread.h>
pthread_mutex_t m_init;
pthread_cond_t c_init;
int init_done = 1;
void* thread_function(void * pv)
{
pthread_mutex_lock(&m_init);
size_t i = *((size_t*) pv);
init_done = 1;
pthread_cond_signal(&c_init);
pthread_mutex_unlock(&m_init);
...
}
#define THREADS_MAX (42)
int main(void)
{
pthread_t thread[THREADS_MAX];
pthread_mutex_init(&m_init, NULL);
pthread_cond_init(&c_init, NULL);
for(size_t i = 0; i < THREADS_MAX; ++i)
{
pthread_mutex_lock(&m_init);
init_done = 0;
pthread_create(&thread[i], NULL, thread_function, &i);
while (!init_done)
{
pthread_cond_wait(&c_init);
}
pthread_mutex_unlock(&m_init);
}
...
}
(error checking omitted for the sake of legibility)
What is the best way to have multiple threads read a file at the same time ?
For example, if I tell my program to run with 4 threads and the file is 12 characters long, I want each thread to read 3 chars at the same time.
This is what I have so far :
thread function :
void *thread(void *arg) {
// can't seem to find the right solution to make it work here...
}
main function (thread_count is the number of threads and text_size the size of text) :
// Number of characters each thread should read
uint16_t thread_chars_num = (text_size / thread_count);
pthread_t threads[thread_count];
for (int i = 0; i < thread_count; i++) {
if(i == thread_count - 1) { // last thread might have more work
thread_chars_num += (text_size % thread_count )
}
if (pthread_create(&threads[i], NULL, thread, &thread_chars_num) != 0) {
fprintf(stderr, "pthread_create failed!\n");
return EXIT_FAILURE;
}
}
I was thinking of giving to the thread function a struct with index to start reading and index to stop reading, but it's really confusing and I can't seem to find the right solution.
Assuming you have a struct like:
struct ft
{
char* file_name;
int start_index;
int end_index;
};
Then in your thread:
void *thread(void *arg) {
int i;
int c;
struct ft* fi = (struct ft*)arg;
FILE* file = fopen(fi->file_name);
fseek (file , fi->start_index, SEEK_SET);
for(i = 0; i < fi->end_index - fi->start_index; i++)
{
c = getc(file);
//do something
}
}
Also, don't forget to do pthread_join in your main thread, which will make it wait for the other threads to finish.
I have realized that my code was too lengthy and rather hard to read.
Can you check over the way I pass in the arguments and constructing the arguments in the main body?
Essentially, provided that I have correct implementation of "produce" and "consume" functions, I want to pass in a shared circular queue and semaphores and mutexes to each produce/consume threads.
typedef struct circularQueue
{
int *items;
int *head;
int *tail;
int numProduced;
int numConsumed;
} circularQueue;
typedef struct threadArg
{
int id;
circularQueue *queue;
pthread_mutex_t *mutex;
sem_t *spaces;
sem_t *itemAvail;
int numItems;
int bufferSize;
int numProducer;
int numConsumer;
} threadArg;
pthread_t *producerThd;
pthread_t *consumerThd;
int main(int argc, char* argv[])
{
pthread_attr_t attr;
// In fo to pass to thread arg
circularQueue *myQueue;
pthread_mutex_t useSharedMem;
sem_t spaces;
sem_t itemAvail;
int numItems;
int bufferSize;
int numProducer;
int numConsumer;
int i, j, k, l;
if(argc != 5)
{
printf("Enter in 4 arguments - N B P C\n");
return -1;
}
numItems = atoi(argv[1]);
bufferSize = atoi(argv[2]);
numProducer = atoi(argv[3]);
numConsumer = atoi(argv[4]);
if(numItems == 0 || bufferSize == 0 || numProducer == 0 || numConsumer == 0)
{
printf("Parameters should not be 0\n");
return -1;
}
// Initialize list of threads
producerThd = malloc(sizeof(pthread_t) * numProducer);
consumerThd = malloc(sizeof(pthread_t) * numConsumer);
// Initialize semaphores
sem_init(&spaces, 0, bufferSize);
sem_init(&itemAvail, 0, 0);
// Initialize mutex
pthread_mutex_init(&useSharedMem, NULL);
// Initialzie thread attributes
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// Initialize queue
myQueue = (circularQueue*)malloc(sizeof(circularQueue));
myQueue->items = (int*)malloc(sizeof(int)*bufferSize);
myQueue->head = myQueue->items;
myQueue->tail = myQueue->items;
myQueue->numProduced = 0;
myQueue->numConsumed = 0;
// thread arguments
for(i = 0; i < numProducer; i++)
{
// Initialize thraed args
threadArg *args = (threadArg*)malloc(sizeof(threadArg));
args->queue = (circularQueue*)malloc(sizeof(circularQueue));
args->mutex = &useSharedMem;
args->spaces = &spaces;
args->itemAvail = &itemAvail;
args->numItems = numItems;
args->bufferSize = bufferSize;
args->numProducer = numProducer;
args->numConsumer = numConsumer;
args->id = i;
pthread_t thisThread = *(producerThd + i);
pthread_create(&thisThread, &attr, produce, args);
}
for(j = 0; j < numConsumer; j++)
{
// Initialize thraed args
threadArg *args = (threadArg*)malloc(sizeof(threadArg));
args->queue = (circularQueue*)malloc(sizeof(circularQueue));
args->mutex = &useSharedMem;
args->spaces = &spaces;
args->itemAvail = &itemAvail;
args->numItems = numItems;
args->bufferSize = bufferSize;
args->numProducer = numProducer;
args->numConsumer = numConsumer;
args->id = j;
pthread_t thisThread = *(consumerThd + i);
pthread_create(&thisThread, &attr, consume, args);
}
for(k = 0; k < numProducer; k++)
{
pthread_join(*(producerThd+k), NULL);
}
printf("Finished waiting for producers\n");
for(l = 0; l < numConsumer; l++)
{
pthread_join(*(consumerThd+l), NULL);
}
printf("Finished waiting for consumers\n");
free(producerThd);
free(consumerThd);
free(myQueue->items);
free(myQueue);
sem_destroy(&spaces);
sem_destroy(&itemAvail);
fflush(stdout);
return 0;
}
Thank you
There are multiple sources of undefined behavior in your code, you are either compiling without enabling compilation warnings, or what I consider worst you ignore them.
You have the wrong printf() specifier in
printf("cid %d found this item %d as valid item %d\n", myArgs->id, thisItem, validItem);
because validItem is a double, so the last specifier should be %f.
Your thread functions never return a value, but you declare them to return void * which is the signature required for such functions.
You are freeing and dereferencing myQueue in the main() function but you have not initialized it because that code is commented.
Your code is also too hard to read because you have no consistent style and you mix declarations with statements, which make everything very confusing, e.g. determining the scope of a variable is very difficult.
Fixing the code will not only help others read it, but will also help you fix it and find issues quickly.
I'm trying to do a simple multi-threaded consumer/producer, where multiple reader and writer thread, read from a file to the buffer and then from buffer back into a file. It should be thread safe. however, it is not performing as i expected. It halts half way but everytime on a different line?
Please help me understand what I am doing wrong?!?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
//TODO Define global data structures to be used
#define BUF_SIZE 5
FILE *fr;
FILE *to; /* declare the file pointer */
struct _data {
pthread_mutex_t mutex;
pthread_cond_t cond_read;
pthread_cond_t cond_write;
int condition;
char buffer[BUF_SIZE];
int datainbuffer;
}dc1 = {
PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER,0,{0},0
};
void *reader_thread(void *arg) {
//TODO: Define set-up required
struct _data *d = (struct _data *)arg;
int killreaders = 0;
while(1) {
//TODO: Define data extraction (queue) and processing
pthread_mutex_lock(&d->mutex);
while (d->condition == 0 || d->datainbuffer<=0){
pthread_cond_wait( &d->cond_read, &d->mutex );
if(killreaders == 1){
pthread_mutex_unlock(&d->mutex);
pthread_cond_signal(&d->cond_read);
pthread_cond_signal(&d->cond_write);
return NULL;
}
}
d->condition = 0;
int i;
char res;
//if the buffer is not full, that means the end of file is reached and it time to kill the threads remaining.
if(d->datainbuffer!=BUF_SIZE)
killreaders = 1;
for (i=0; i<(sizeof d->datainbuffer); i++) {
res = d->buffer[i];
printf("to file:%c",res);
fputc(res, to);
}
d->datainbuffer = 0;
pthread_mutex_unlock(&d->mutex);
pthread_cond_signal( &d->cond_write );
}
return NULL;
}
void *writer_thread(void *arg) {
//TODO: Define set-up required
struct _data *d = (struct _data *)arg;
char * pChar;
int killwriters = 0;
while(1){
pthread_mutex_lock(&d->mutex);
while( d->condition == 1 || d->datainbuffer>0){
pthread_cond_wait( &d->cond_write, &d->mutex );
if(killwriters==1){
pthread_mutex_unlock(&d->mutex);
pthread_cond_signal(&d->cond_write);
pthread_cond_signal(&d->cond_read);
return NULL;
}
}
d->condition = 1;
int i;
char rc;
for (i = 0; i < BUF_SIZE; i++){
if((rc = getc(fr)) == EOF){
killwriters = 1;
pthread_mutex_unlock(&d->mutex);
pthread_cond_signal(&d->cond_read);
return NULL;
}
d->datainbuffer = i+1;
d->buffer[i] = rc;
printf("%c",rc);
}
int m = 0;
pthread_mutex_unlock(&d->mutex);
pthread_cond_signal(&d->cond_read);
}
return NULL;
}
#define M 10
#define N 20
int main(int argc, char **argv) {
struct _data dc=dc1;
fr = fopen ("from.txt", "rt"); /* open the file for reading */
if (fr == NULL)
{
printf("Could not open file!");
return 1;
}
to = fopen("to.txt", "wt");
int i;
pthread_t readers[N];
pthread_t writers[M];
for(i = 0; i < N; i++) {
pthread_create(&readers[i], NULL, reader_thread, (void*)&dc);
}
for(i = 0; i < M; i++) {
pthread_create(&writers[i], NULL, writer_thread, (void*)&dc);
}
fclose(fr);
fclose(to);
return 0;
}
any suggestion is appreciated!
Your threads are reading from and writing to files, which you open & close in main. But main doesn't explicitly wait for the threads to finish before closing those files.
In addition to the problem pointed out by Scott Hunter, your readers and writers do all their "real work" while holding the mutex, defeating the point of having more than one thread in the first place.
Readers should operate as follows:
1) Acquire mutex.
2) Block on the condition variable until work is available.
3) Remove work from queue, possibly signal condition variable.
4) Release mutex.
5) Process the work.
6) Go to step 1.
Writers should operate as follows:
1) Get the information we need to write.
2) Acquire the mutex.
3) Block on the condition variable until there is space on the queue.
4) Place information in the queue, possibly signal condition variable.
5) Release the mutex.
6) Go to step 1.
Notice both threads do the "real work" without holding the mutex? Otherwise, why have multiple threads if only one of them can do work at a time?
I'm not sure whether my answer is going to help you or not.. but I'm going to give my best by giving you some reference code.
I have written a similar program (except that it does not write to the file, instead display the queue-/produced-/consumed- items in the stdout). It can be found here - https://github.com/sangeeths/pc . I have separated the command-line processing and queue logic into a separate files.
Hope this helps!