I originally had a global variable for my fibonacci variable array, but found out that is not allowed. I need to do elementary multithreading and handle race conditions, but I can't get past feeding an int as a void argument in pthread create. I've tried using a constant pointer with no luck. For some strange reason the void* gets past the first boolean test but not the else if:
$ gcc -o fibonacci fibonacci.c
fibonacci.c:22:16: warning: comparison between pointer and integer ('void *' and 'int')
else if (arg == 1)
~~~ ^ ~
1 warning generated.
My code is a mess and I am getting really confused because I have rewritten it so many times. If I cast all the args in my thread run function as ints I get a segmentation fault 11, which makes sense. All attempts at passing the i index by address and dereferencing it have failed, as it is a void and can't be used as an int. Can you suggest something else?
#include<stdio.h> //for printf
#include<stdlib.h> //for malloc
#include<pthread.h> //for threading
#define SIZE 25 //number of fibonaccis to be computed
int *fibResults; //array to store fibonacci results
void *run(void *arg) //executes and exits each thread
{
if (arg == 0)
{
fibResults[(int)arg] = 0;
printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);
pthread_exit(0);
}
else if (arg == 1)
{
fibResults[(int)arg] = 1;
printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);
pthread_exit(0);
}
else
{
fibResults[(int)arg] = fibResults[(int)arg -1] + fibResults[(int)arg -2];
printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);
pthread_exit(0);
}
}
//main function that drives the program.
int main()
{
pthread_attr_t a;
fibResults = (int*)malloc (SIZE * sizeof(int));
pthread_attr_init(&a);
for (int i = 0; i < SIZE; i++)
{
pthread_t thread;
pthread_create(&thread, &a, run,(void*) &i);
printf("Thread[%d] created\t", i);
fflush(stdout);
pthread_join(thread, NULL);
printf("Thread[%d] joined & exited\t", i);
}
return 0;
}
You don't need the cast in the call to pthread_create() — the conversion to void * is automatic.
In the thread function, you could use
int i = *(int *)arg;
However, you've now got a synchronization problem; all the threads are using the same (pointer to the same) integer variable, and you can't predict which value they're going to see because of scheduling issues. The per-thread data needs to be 'per thread'.
So, there are various ways around that. In this context, I'd probably use
#include <stdint.h>
and in main():
pthread_create(&thread, &a, run, (void*)(uintptr_t)i);
and then in the thread function:
int i = (uintptr_t)arg;
Now the casts — the double cast even — is necessary. The cast to uintptr_t ensures the integer value is big enough to hold a pointer; the cast to void * is needed because there isn't an implicit cast from any integer type to void *. This ensures each thread function invocation has a different value. Sharing a pointer to an int means that everything is uncontrolled.
In the run() function you should do:
void *run(void *ptrarg) //executes and exits each thread
{
int arg = *((int *)ptrarg);
if (arg == 0)
....
....
and in rest of the run(), you don't need to cast the arg. Replace (int)arg with arg.
EDIT:
The way you are passing the argument to fun() while creating threads may cause race condition because all threads will be using same pointer. Check the #Jonathan's answer to avoid this problem.
#efuddy. Instead of (int)arg you should use (int *)arg to properly cast the **void pointer* void *arg
Related
I was trying to print a thread's return value and discovered that I'm still quite confused by the notion of double void-pointers.
My understanding was that a void* is a pointer to any datatype that can be dereferenced with an appropriate cast, but otherwise the "levels" of referencing are preserved like with regular typed pointers (i.e. you can't expect to get the same value that you put into **(int **)depth2 by dereferencing it only once like *depth2. ).
In the code (below) that I have scraped together for my thread-return-print, however, it seems that I'm not dereferencing a void pointer at all when I'm just casting it to (int). Is this a case of an address being used as value? If so, is this the normal way of returning from threads? Otherwise, what am I missing??
(I am aware that the safer way to manipulate data inside the thread might be caller-level storage, but I'm quite interested in this case and what it is that I don't understand about the void pointer.)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *myThread(void *arg)
{
return (void *)42;
}
int main()
{
pthread_t tid;
void *res; // res is itself a void *
pthread_create(&tid, NULL, myThread, NULL);
pthread_join(tid, &res); // i pass its address, so void** now
printf(" %d \n", (int)res); // how come am i able to just use it as plain int?
return 0;
}
First of all, the purpose of pthread_join() is to update the void *
given through its second argument in order to obtain the result of the
thread function (a void *).
When you need to update an int as in scanf("%d", &my_var); the argument
is the address of the int to be updated: an int *.
With the same reasoning, you update a void * by providing a void **.
In the specific situation of your example, we don't use the returned
void * in a normal way: this is a trick!
Since a pointer can be thought about as a big integer counting the bytes in
a very long row, the trick is to assume that this pointer can simply store
an integer value which does no refer to any memory location.
In your example, returning (void *)42, is equivalent to saying
"you will find something interesting at address 42".
But nothing has ever been placed at this address!
Is this a problem? No, as long as nobody tries to dereference this
pointer in order to retrieve something at address 42.
Once pthread_join() has been executed, the variable res has
been updated and contains the returned void *: 42 in this case.
We perform here the reverse-trick by assuming that the information memorised
in this pointer does not refer to a memory location but is a simple integer.
It works but this is very ugly!
The main advantage is that you avoid the expensive cost of malloc()/free()
void *myThread(void *arg)
{
int *result=malloc(sizeof(int));
*result=42;
return result;
}
...
int *res;
pthread_join(tid, &res);
int result=*res; // obtain 42
free(res);
A better solution to avoid this cost would be to use the parameter
of the thread function.
void *myThread(void *arg)
{
int *result=arg;
*result=42;
return NULL;
}
...
int expected_result;
pthread_create(&tid, NULL, myThread, &expected_result);
pthread_join(tid, NULL);
// here expected_result has the value 42
I wrote this small program for understanding pthread_create and pthread_join but I dont understand why the value of the variable data gets altered after thread_join. Its printed as 0 after the call to pthread functions.
#include <pthread.h>
#include <stdio.h>
void* compute_prime (void* arg)
{
int n = *((int*) arg);
printf("Argument passed is %d\n",n);
return (void *)n;
}
int main ()
{
pthread_t thread;
int data = 5000;
int value=0;
pthread_create (&thread, NULL, &compute_prime, &data);
pthread_join (thread, (void*) &value);
printf("The number is %d and return value is %d.\n", data, value);
return 0;
}
And the output is
Argument passed is 5000
The number is 0 and return value is 5000.
This is because pthread_join has the prototype void **. It expects a pointer to an object of type void *; it modifies this void * object. Now it so happens that you're running on a 64-bit arch, where data and value are both 32 bits, and laid out in memory sequentially. Modifying a void * object that is laid out in memory starting from the address of the int object value clobbers the int object data too, as these are both 32 bits - thus you will see that the data was overwritten. However, this is undefined behaviour so anything might happen.
Don't use casts as they will only serve to hide problems. Casting to a void * is especially dangerous as a void * can be converted to any other type implicitly, even to void **, even though usually it too would be incorrect. If you remove the cast, you most probably will get a warning or an error like
thrtest.c: In function ‘main’:
thrtest.c:16:31: error: passing argument 2 of ‘pthread_join’ from
incompatible pointer type [-Werror=incompatible-pointer-types]
pthread_join (thread, &value);
if compiling with warnings enabled.
If however you really want to do this, you must do it like this:
void *value;
pthread_join(thread, &value);
intptr_t value_as_int = (intptr_t)value;
Though it is not really portable either, as the conversion is implementation-defined.
The most portable way to return an integer is to return a pointer to a mallocated object:
int *return_value = malloc(sizeof (int));
*return_value = 42;
return return_value;
...
void *value;
pthread_join(thread, &value);
int actual = *(int *)value;
free(value);
This question already has answers here:
Pass integer value through pthread_create
(4 answers)
Closed 5 years ago.
I am trying to understand following code. This code has no race conditions, but I cannot understand.
#include <stdio.h>
#include <pthread.h>
void *foo(void *vargp) {
int id;
id = (int)vargp;
printf("Thread %d\n", id);
}
int main() {
pthread_t tid[2];
int i;
for (i = 0; i < 2; i++)
pthread_create(&tid[i], NULL, foo, (void *)i);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
How does the typecasting from int to void* work?
The race condition that is avoided is illustrated by this code, which is very similar to the original code, but subtly different, and the difference makes it incorrect:
/* Incorrect code! */
#include <pthread.h>
#include <stdio.h>
static void *foo(void *vargp)
{
int id = *(int *)vargp;
printf("Thread %d\n", id);
return 0;
}
int main(void)
{
pthread_t tid[2];
int i;
for (i = 0; i < 2; i++)
pthread_create(&tid[i], NULL, foo, &i); // Bad idea!
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
Since the function foo takes a void * argument, it seems logical to pass the address of the int to it. However, this has a major problem:
There is no guarantee which order the threads will execute, nor when, so there's no way to know which values the threads will see.
Indeed, when I ran this code the first time, both threads reported 2.
The way around this is to not pass the address of i but to pass i by value. However, the argument is still supposed to be a void *, so the code casts i to a void * before calling pthread_create(), and the thread function undoes the cast to retrieve the value.
When I'm doing this, I also use <stdint.h> to make the uintptr_t type available, and I use:
int id = (uintptr_t)vargp;
and
pthread_create(&tid[i], NULL, foo, (void *)(uintptr_t)i);
That looks excessive and/or obsessive, but the uintptr_t cast ensures the integer is the same size as a pointer to avoid the 'cast to pointer from integer of different size' compiler warning (which, since I tell the compiler to treat all warnings as errors, is necessary for me to get the code to compile at all).
If you do pass a pointer-to-data to the thread function (foo in this discussion), you must ensure that each thread you create gets its own copy of the data unless that data is meant to be identical in each thread.
You can see this technique at work in POSIX threads — unique execution.
Consider the following code:
void* run(void* arg) {
int* array=(int*)arg;
printf("In run!\n");
int i;
for (i=0; i<10; i++) {
printf("%d ",array[i]);
}
printf("\n");
return (void*)15;
}
int main() {
pthread_t my_thread;
int array[10]={0};
void* ret;
int i;
for (i=0; i<10; i++) {
array[i]=i+1;
}
if (pthread_create(&my_thread, NULL, run, (void*)array)!=0) {
perror("thread creation failed");
return 1;
}
pthread_join(my_thread, &ret);
printf("thread finished and returned %d\n", *(int*)ret); // segfault. why??
return 0;
}
I'm trying to obtain the value 15, returned by the thread that was created, but for some reason, that last printf throws segmentation fault.
What is the reason for the segmentation fault, and what is the right way to obtain the returned value 15?
I also tried this:
printf("thread finished and returned %d\n", *(*(int*)ret));
Which resulted in an error:
error: invalid type argument of unary ‘*’ (have ‘int’)
and this:
printf("thread finished and returned %d\n", *(int*)(*ret));
which also resulted in an error (and a warning):
warning: dereferencing ‘void *’ pointer [enabled by default]
error: invalid use of void expression
What is the right way to do it, and most importantly, what is the reason for that segfault?
The reason for the failure is that your thread returns an integer in place of a void*, and the code in main tries to dereference it.
It is illegal to do both these things at once, but you can do each one of them separately:
If you are returning an int in a pointer, you could cast it to uintptr_t before casting to void*, and do the sequence in reverse to get back an int, or
If you wish to dereference in the main, you need to put your int in memory, and pass back a pointer to that memory so that it could be dereferenced in main.
I would use the first approach, like this:
// Inside run():
return (void*)((uintptr_t)15);
// Inside main():
printf("thread finished and returned %d\n", (int)((uintptr_t)ret));
Remember to include <stdint.h> in order to use the uintptr_t type.
Using the second approach is a bit trickier:
// Inside run():
int *ret = malloc(sizeof(int)); // You need to use dynamic allocation here
*ret = 15;
return ret;
// Inside main():
int *run_ret = ret;
printf("thread finished and returned %d\n", *run_ret);
free(run_ret); // You need to free malloc-ed memory to avoid a leak
You could potentially simplify it by allocating the buffer for the result in the caller, but either way that is going to be harder than using the uintptr_t approach.
pthread_create(&Thread,NULL,ChildThread,(void *)100);
1) Can we pass the 4th argument of pthread_create as shown above? shouldn't it be a pointer variable?
Just an example (not meant to be correct way of doing it; but to serve as example code for anyone who want to play with it):
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>
void *print_number(void *number) {
printf("Thread received parameter with value: %d\n", number);
return (void *)number;
}
int main(int argc, char *argv[]) {
pthread_t thread;
void *ret;
int pt_stat;
pt_stat = pthread_create(&thread, NULL, print_number, (void *)100);
if (pt_stat) {
printf("Error creating thread\n");
exit(0);
}
pthread_join(thread, &ret);
printf("Return value: %d\n", ret);
pthread_exit(NULL);
return 0;
}
This will lead to undefined behavior if the pointer value is greater then what an int can hold. See this quote from C99:
Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.
What (void *)100 means is take the integer value 100 and treat it as a pointer to some unspecified type of memory (i.e., (void *)). In that case, that means push the integer value 100 on the stack as an argument to pthread_create. Presumably, ChildThread casts the void * passed to it back to an int, then uses it as a number.
Fundamentally pointers are really just memory addresses. A memory address is just a number that describes a location in memory, so casting an int to a pointer of any type is legal. There are a few cases where casting an int to a pointer is absolutely the right thing to do and required, however, they tend to be rare. For example, if you are writing code for an embedded controller, and want write a driver for a memory mapped I/O device, then you might cast the device's base address as a pointer to an int or struct and then do normal C accesses through the pointer to access the device. Another example where casting ints to pointers, would be to implement the low-level virtual memory management routines to parcel out physical memory for an operating system.
The code you present is not uncommon and will work, assuming that the size of a pointer is at least big enough to hold the integer you are trying to pass. Most systems that implement pthread_create would probably have a 32-bit or 64-bit pointer, so your example is pretty likely to work. IMHO, it is a bit of an abuse, because 100 probably does not refer to a memory location in this case, and C does not guarantee that a void * is big enough to hold an int.
Taken from an excellent artice on POSIX Thread Progreamming . Must read for any newbie .
Example Code - Pthread Creation and Termination
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
Explanation :
You can pass the 100 as the 4th argument to the pthread_create() . In the function PrintHello you can typecast the void* back into the correct type .