When I run the following code it seems like the printout is not right.
void thread_Calc(int *pos) {
printf("recieved %d\n", *pos);
sig = -1;
mandel_Calc(&slices[*pos],maxIterations,&res[(*pos)*slices[*pos].imSteps*slices[*pos].reSteps]);
counter++;
array[counter] = *pos;
sig = *pos;
}
int main(int argc, char *argv[]) {
while (WinH % nofslices != 0) { nofslices++;}
slice_height = WinH/nofslices;
level = 1;
while (1) {
for (i=0; i<nofslices; i++){
array[i] = -1;
}
y=0;
sig = -1;
counter = -1;
for(i=0; i<nofslices; i++){
printf("Passing %d\n", i);
check=pthread_create(&worker[i], NULL, (void*)thread_Calc, (void*)(int *)&i);
if (check!=0) {
printf("Error in pthread_create\n");
return 0;
}
while (sig==-1||array[counter]==-1){
}
}
}
}
(This is just a part of my code, so assume that every variable is right and has a value).
The result I get is something like:
Passing 1
Passing 2
recieved 2
recieved 2
Passing 3
Passing 4
recieved 4
recieved 4
Passing 5
Passing 6
Passing 7
Passing 8
Passing 9
which seems like I can't always pass the right argument in pthread_create or something.
#Andrew is right. You pass a pointer not a value, so as soon as you change "i" in the main thread the value is changed in the parameter received by the created thread. You need to create a copy and pass it to the thread.
See pthread_create : passing an integer as the last argument
In this code:
for(i=0; i<nofslices; i++){
printf("Passing %d\n", i);
check=pthread_create(&worker[i], NULL, (void*)thread_Calc, (void*)(int *)&i);
the value of i continues to change after each thread gets started.
You pass the address of i, so when it gets dereferenced in the child thread, it holds whatever value your main thread has put into it at that time.
Related
I have this program:
void *func(void *arg) {
pthread_mutex_lock(&mutex);
int *id = (int *)arg;
printf("My ID is %d\n" , *id);
pthread_mutex_unlock(&mutex);
}
int main() {
int i;
pthread_t tid[3];
// Let us create three threads
for (i = 0; i < 3; i++) {
pthread_create(&tid[i], NULL, func, (void *)&i);
}
for (i = 0; i < 3; i++) {
pthread_join(tid[i], NULL);
}
pthread_exit(NULL);
return 0;
}
I expected it to output this:
My ID is 0
My ID is 1
My ID is 2
But instead I get random output, such as this:
My ID is 0
My ID is 0
My ID is 2
Since I already added mutex lock, I thought it would solve the problem. What else did I do wrong? Is this related to race condition?
Here id points to the same variable i in main for all the threads.
int *id = (int *)arg;
printf("My ID is %d\n" , *id);
But the variable i is constantly being update by the two for-loops in main behind the threads back. So before the thread reaches the point of printf, the value of i, and therefore also the value of *id, may have changed.
There are a few ways to solve this. The best way depends on the use case:
Wait in main until the thread signals that it has made a copy of *id before modifying i or letting it go out of scope.
Declare and initialize an array, int thread_id[], and create the threads like this:
pthread_create(&tid[i], NULL, func, &thread_id[i]);
malloc some memory and and initialize it with a copy of i:
int *thread_id = malloc(sizeof(*thread_id));
*thread_id = i
pthread_create(&tid[i], NULL, func, thread_id);
Just don't forget to free your memory int the thread when you are finished using it. Or in main if the thread fails to start.
If i fits in a void * can pass its content directly as a parameter to the thread. To make sure it fits, you can declare it as intptr_t rather than int
(We basicly abuse the fact that pointers are nothing more than magic integers) :
void *func(void *arg) {
pthread_mutex_lock(&mutex);
// Here we interpret a pointer value as an integer value
intptr_t id = (intptr_t )arg;
printf("My ID is %d\n" , (int)id);
pthread_mutex_unlock(&mutex);
}
int main() {
intptr_t i;
pthread_t tid[3];
// Let us create three threads
for (i = 0; i < 3; i++) {
// Here we squeeze the integer value of `i` into something that is
// supposed to hold a pointer
pthread_create(&tid[i], NULL, func, (void *)i);
}
for (i = 0; i < 3; i++) {
pthread_join(tid[i], NULL);
}
// This does not belong here !!
// pthread_exit(NULL);
return 0;
}
Nope, no race conditions involved. (my b) There can be a race condition on i because all threads access it. Each thread gets started with a pointer to i. However, the main problem is that there is no guarantee that the thread will start and run the critical section while i holds the value you expect, in an order that you expect.
I'm assuming you declared the variable mutex globally and called pthread_mutex_init() somewhere to initialize it.
Mutexes are great to allow only one thread to access a critical section of code at a time. So the code as you've written creates all three threads to run in parallel, but only lets one thread at a time run the following code.
int *id = (int *)arg;
printf("My ID is %d\n" , *id);
I am currently creating threads and I would like to print out the "thread number" of each thread I make. For example:
void* thread_function(void* arg){
printf("This is thread # %d\n", *(int*)arg);
return NULL;
}
pthread_t id;
int main()
for(int i = 0; i< 5; i++){
pthread_create(&id, NULL, thread_function, &i);
}
//do some other stuff
return 0;
}
So basically, for the first thread, I want it to say:
This is thread # 0
However, for some reason it gives me random numbers like
This is thread # -56465645645
How do I fix this problem?
You pased pointer to i that will vanish after exiting the for loop instead of value of i.
Try using (void*)i instead of &i in function main() and
passing (int)arg instead of *(int*)arg in function thread_function().
(conversion between pointers and intergers is implementation-defined)
So a foreword, I am new to C, so please forgive any horrifying mistakes my program has.
I am trying to write a program that will take a list of numbers passed in as arguments to the program or contained in a file whose path is passed in.
It stores the numbers into an array, and stores how many numbers there are into the first element of the array. It will only store up to 100 numbers.
It then creates a pthread and passes the pointer to the array to the thread.
The thread is then suppose to sum up the numbers and return the sum back to the main function.
I am experiencing the following issues:
1. It doesn't always happen, but sometimes I get a segmentation fault right before the line of code that says:
printf("Begining to create the thread");
2. My attempts to return the sum isn't working, and after hours of research online, I can't figure out why.
3. When I compile the program, I get the following errors:
gcc -g -o assn3 assn3.c -pthread
assn3.c: In function ‘AddUpNumbers’:
assn3.c:34:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
return (void*)total;
^
assn3.c: In function ‘main’:
assn3.c:96:3: warning: passing argument 1 of ‘pthread_join’ makes integer from pointer without a cast [enabled by default]
pthread_join(&functionThread, &total);
^
In file included from assn3.c:12:0:
/usr/include/pthread.h:261:12: note: expected ‘pthread_t’ but argument is of type ‘pthread_t *’
extern int pthread_join (pthread_t __th, void **__thread_return);
^
assn3.c:97:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘void *’ [-Wformat=]
printf("The total returned by the thread is %d", total);
^
Here's my code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NO_ARGS 1
#define ONLY_SINGLE_ARG 2
#define PATH_TO_READ_FROM 1
#define MAX_NUMBERS 101
#define MAX_CHAR_INPUT 255
#define COUNT_LOCATION 0
void* AddUpNumbers(void* arrayPointer) {
printf("Created the pthread!");
int* numbersArray = (int*)arrayPointer;
int count = numbersArray[COUNT_LOCATION];
int total = 0;
int i = 1;
while (i < count) {
total = total + numbersArray[i];
}
printf("The total to be returned is %d", total);
return (void*)total;
}
int main(int argc, char* argv[]) {
FILE * numbersFile = NULL;
int count = 0;
int numberArray[MAX_NUMBERS];
//Initialize the Array
int i = 0;
while (i < MAX_NUMBERS) {
numberArray[i] = 0;
i = i + 1;
}
if (argc == NO_ARGS) {
printf("Usage: # or file path, #, #, ..., #\n");
} else if (argc == ONLY_SINGLE_ARG) {
numbersFile = fopen(argv[PATH_TO_READ_FROM], "r");
if (numbersFile != NULL) {
char buff[MAX_CHAR_INPUT];
i = 1;
count = 0;
while (i < MAX_NUMBERS) {
if (fscanf(numbersFile, "%s", buff) != EOF) {
numberArray[i] = atoi(buff);
printf("%d\n", numberArray[i]);
i = i + 1;
count = count + 1;
} else {
break;
}
}
numberArray[COUNT_LOCATION] = count;
printf("Count Total: %d\n", numberArray[COUNT_LOCATION]);
} else {
printf("Error: Could not open file!\n");
return -1;
}
} else if (argc < MAX_NUMBERS + 1) {
i = 1;
count = 0;
while (i < argc) {
numberArray[i] = atoi(argv[i]);
printf("%d\n", numberArray[i]);
i = i + 1;
count = count + 1;
}
printf("See if error happens after this");
numberArray[COUNT_LOCATION] = count;
printf("Count Total: %d\n", numberArray[COUNT_LOCATION]);
} else {
printf("Too many numbers! This program can only add up to: %d numbers.\n", MAX_NUMBERS);
return -1;
}
printf("Begining to create the thread");
pthread_t functionThread;
int creationSuccess = 0;
void* total;
creationSuccess = pthread_create(&functionThread, NULL, AddUpNumbers, (void*)numberArray);
if (creationSuccess == 0) {
pthread_join(&functionThread, total);
printf("The total returned by the thread is %d", *((int)total));
} else {
printf("Something went wrong.\n");
}
if (numbersFile != NULL) {
fclose(numbersFile);
}
return 0;
}
My Makefile looks like this:
assn3: assn3.c
gcc -g -o assn3 assn3.c -pthread
You should be very wary of compiler warnings. Either clean them up or understand very well why they are ok. Pay special attention to warnings about data type mismatches.
In this case this warning probably explains the main problem:
In file included from assn3.c:12:0:
/usr/include/pthread.h:261:12: note: expected ‘pthread_t’ but argument is of type ‘pthread_t *’
extern int pthread_join (pthread_t __th, void **__thread_return);
^
You are (creating and) passing a pointer to your pthread_t object as the first argument of pthread_join(), but unlike pthread_create(), pthread_join() expects you to pass the pthread_t itself, not a pointer to it. All manner of havoc (technically, "undefined behavior") will ensue.
UPDATE: Additionally, the second argument you are passing to pthread_join() is an uninitialized pointer to void. If pthread_create() tries to write anything where it points then who knows what happens (undefined behavior again). You are expected to pass a valid pointer to the location where the result is to be written. In this case, that would be &total.
The syntax of pthread_create is:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, *(*start_routine) (void *), void *arg);
pthread_t - is id of thread. So create variable pthread_t id, or array of values if you have a lot of threads, like pthread_t id[THREAD_NUM];
Then your func will looks like:
pthread_create(&id[i], NULL, &functionThread, (void*)numberArray);
With pthread_join(&functionThread, total);
The same thing.
int pthread_join(pthread_t thread, void **value_ptr);
So you join must look like:
pthread_join(&id[i], total);
This is my main function, where NO_RECIEVERS = 3. I am trying to differentiate between the writer and reader threads using the value of i that i send.
int main() {
int status, i;
pthread_t tr[NO_RECIEVERS], tw[NO_SENDERS], bd;
i=1;
for(i=1; i<=NO_SENDERS; i++) {
pthread_create(&tw[i-1], NULL, writer, &i);
}
for(i=1; i<=NO_RECIEVERS; i++) {
printf("%d\n", i);
pthread_create(&tr[i-1], NULL, reader, &i);
}
pthread_create(&bd, NULL ,daemon_thread, NULL);
for(i=1; i<=NO_SENDERS; i++) {
pthread_join(tw[i-1], NULL);
}
for(i=1; i<=NO_RECIEVERS; i++) {
pthread_join(tr[i-1], NULL);
}
pthread_join(bd, NULL);
return 0;
}
My reader function is as follows
void* reader(void *val) {
int ret, fd, id;
struct mssg data;
id = *(int*)val;
printf("id: %d %d\n", id, *(int*)val);
while(1) {
But this function seems to be creating threads with id some random values.. i get a log like this
...
id: 1 1
...
id: 2 2
...
id: 1 1
Next time i get.. its kind of random
...
id: 1 1
...
2
id: 2 2
...
id: 4 4
But the values i am assigning are limited to 1,2,3
You passed &i to all the threads you created... so each one has a pointer to i, and when they dereference that to read the value of i, and what they read is whatever i happens to be at the time.
If you want to pass the value of i at the time of the pthread_create, I suggest malloc() a small piece of memory, copy i to it and pass the malloced thing to the thread (which can read it and the free() the memory. Or any other method that provides a copy of i in a different location for each thread created.
I have the following code:
for(i = 0 ; i < max_thread; i++)
{
struct arg_struct args;
args.arg1 = file;
args.arg2 = word;
args.arg3 = repl;
if(pthread_create(&thread_id[i],NULL,&do_process,&args) != 0)
{
i--;
fprintf(stderr,RED "\nError in creating thread\n" NONE);
}
}
for(i = 0 ; i < max_thread; i++)
if(pthread_join(thread_id[i],NULL) != 0)
{
fprintf(stderr,RED "\nError in joining thread\n" NONE);
}
int do_process(void *arguments)
{
//code missing
}
*How can I transform (void *)do_process into (int) do_process ?*
That function returns very important info and without those returns I don't know how to read the replies
I get the following error: warning: passing arg 3 of `pthread_create' makes pointer from integer without a cast
The thread function returns a pointer. At minimum, you can allocate an integer dynamically and return it.
void * do_process (void *arg) {
/* ... */
int *result = malloc(sizeof(int));
*result = the_result_code;
return result;
}
Then, you can recover this pointer from the thread_join() call;
void *join_result;
if(pthread_join(thread_id[i],&join_result) != 0)
{
fprintf(stderr,RED "\nError in joining thread\n" NONE);
} else {
int result = *(int *)join_result;
free(join_result);
/* ... */
}
Just write a helper function that is of the correct type, but all it does is take the void * input parameter, get all the right parameters out of it, call your function, take the return of that, and package it up as a void * for pthread_join to get.
To your specific question, you can't/shouldn't. Just do what I outlined above and you'll be golden.
The pthread_join() is a simple way to communicate between the two threads. It has two limitations. First, it can pass only one value from the pointer (you can make it a pointer and store multiple values). Second, you can return it only when the thread is all done -- after returning this value, the thread goes in terminated state. So, if you want the threads to communicate in a more granular fashion, you will be better served in using a common shared data. Of course, at teh very least, you would to use Pthread mutex to synchronize access to the common data. And, if you want the threads to communicate with each other, then you would also need to use Pthread condvars.