void * consumer_child(void *arguments){
Range rng = *((Range *) arguments);
//prinnting with the range to easily identify each thread
printf("consumer_child[%d-%d] started\n", rng.start, rng.end );
pthread_exit(0);
}
When I print it, it prints memory location, not the value. I need to print the value.
In main thread start and end values are set properly. I have checked them.
in main I have set the argument as following
Range *rng = malloc(sizeof(*rng));
rng->start = i * numbersPerChild;
rng->end = (numbersPerChild * (i + 1)) -1 ;
printf("Range for thread %d is %d to %d\n", i, rng->start, rng->end );
printf("test print %d\n",rng->start);
pthread_create(&tid[i], NULL, consumer_child, (void *)&rng );
Range is a struct
typedef struct
{
int start;
int end;
} Range;
You need to change:
pthread_create(&tid[i], NULL, consumer_child, (void *)&rng );
to:
pthread_create(&tid[i], NULL, consumer_child, rng);
since rng is already a pointer, and you want to pass that, not its address. You don't need to cast an object pointer to void * in C, unless you have a variadic function that expects one and you're trying to pass it a different kind of object pointer.
Related
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// Let us create a global variable to change it in threads
int g = 0;
// The function to be executed by all threads
void *myThreadFun(void *vargp)
{
// Store the value argument passed to this thread
int *myid = (int *)vargp;
// Let us create a static variable to observe its changes
static int s = 0;
// Change static and global variables
++s; ++g;
// Print the argument, static and global variables
printf("Thread ID: %d, Static: %d, Global: %d\n", *myid, ++s, ++g);
}
int main()
{
int i;
pthread_t tid;
// Let us create three threads
for (i = 0; i < 3; i++)
pthread_create(&tid, NULL, myThreadFun, (void *)&i);
pthread_exit(NULL);
return 0;
}
I was just playing with aforementioned example in multithreading in C, and I got the same thread id for 2 threads and it shouldn't be because myid is a local pointer and should print different with each one.
I got the output as following:
Thread ID: 3, Static: 2, Global: 2
Thread ID: 3, Static: 4, Global: 4
Thread ID: 3, Static: 6, Global: 6
Can someone please explain me in brief?
You pass the very same pointer to all three threads. All threads will dereference the same pointer, getting the same value.
And because you call pthread_exit, the data the pointer is pointing to will not be alive anymore. And that means the dereference will lead to undefined behavior.
Furthermore since you access and modify shared data without synchronization you have data-races leading yet again to undefined behavior.
The first two problems can be easily solved by passing the value of i instead of a pointer to it. This is one of the very few cases where most people think it's okay to pretend that an integer is a pointer. You have to do some casting to make it work though:
pthread_create(&tid, NULL, myThreadFun, (void *) (intptr_t) i);
Then you have to do the opposite casting when getting the value:
int myid = (int) (intptr_t) vargp;
I got the same thread id for 2 threads and it shouldn't be because myid is a local pointer and should print different with each one.
myid is a local pointer, but it's actually pointing at an address from another thread. myid in all 3 threads you created pointed to the same address of i in main. So when you dereference myid, all threads read from the same location.
There are few issues.
Since main calls, pthread_exit, once the main thread exits and you can no longer access i from other threads. This is undefined behaviour.
All the threads actually read i (through myid). This is a data race - more than one thread accessing i without any
synchronisation.
Note that scope of an object doesn't determine the lifetime of an object. They are related but not the same.
the following proposed code:
cleanly compiles
performs the desired functionality
corrects the problems found in the OPs posted code
checks for (most) error conditions
uses a proper signature for the main() function
And now the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 3
// Let us create a global variable to change it in threads
int g = 0;
pthread_mutex_t myMutex;
// The function to be executed by all threads
void *myThreadFun( void *vargp )
{
// Store the value argument passed to this thread
int myid = (int) (intptr_t) vargp;
// Let us create a static variable to observe its changes
static int s = 0;
pthread_mutex_lock( &myMutex );
// Change static and global variables
++s;
++g;
// Print the argument, static and global variables
printf("Thread ID: %d, Static: %d, Global: %d\n", myid, s, g);
pthread_mutex_unlock( &myMutex );
pthread_exit( NULL );
}
int main( void )
{
pthread_t tid[ NUM_THREADS ] = {0};
if (pthread_mutex_init(&myMutex, NULL) != 0)
{
perror( "pthread_mutex_init failed" );
exit( EXIT_FAILURE );
}
// implied else, init successful
// Let us create three threads
for ( int i = 0; i < NUM_THREADS; i++)
{
if(pthread_create(&tid[i], NULL, myThreadFun, (void *) (intptr_t) i) != 0 )
{
perror( "pthread_create failed" );
exit( EXIT_FAILURE );
}
}
// collect the threads
for( int i=0; i< NUM_THREADS; i++ )
{
if( pthread_join( tid[i], NULL ) != 0 )
{
perror( "pthread_join failed" );
}
}
pthread_mutex_destroy( &myMutex );
return 0;
}
A typical run of the program results in the following output:
Thread ID: 0, Static: 1, Global: 1
Thread ID: 2, Static: 2, Global: 2
Thread ID: 1, Static: 3, Global: 3
Note: the field claiming to be the thread ID is only the order that the threads were created, not the actual thread 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)
I am writing a unit test that involves running multiple threads and I ran into a memory access issue that I can't seem to understand.
Here is the original (pseudo) code:
void thread_func(void * err) {
/*foo will return an allocated error_type if error occurs else NULL*/
err = (void *) foo(...)
pthread_exit(NULL);
}
void unit_test() {
int i = 0;
err_type *err_array[10];
pthread_t threads[10];
for (i = 0; i < 10; i++) {
pthread_create(&(threads[i]), NULL, thread_func, (void *) err_array[i]);
}
for(i = 0; i < 10; i++) {
pthread_join(threads[i], NULL);
ASSERT_NULL(err_array[i]);
}
}
What I am confused about is that all the threads will return NULL (checked with a gdb), however err_array[1] and err_array[5] will be NOT NULL. And instead of a valid err_type, they will contain garbage. In the case of err_array[1] will contain a string of the unit_test file path, and err_array[5] will contain a bunch of access out of bounds addresses.
A work-around I've found is to use a global err_array, and pass in the index for each element to the thread. As well as initializing all the elements of the array to NULL.
My question is why does the above 2 methods work, and not the original code?
The err variable is local to thread_func. It goes out of scope when thread_func returns. You need to pass the thread a pointer to the thing you want it to modify, not the current value of the thing you want it to modify.
So:
void thread_func(void ** err) {
/*foo will return an allocated error_type if error occurs else NULL*/
*err = (void *) foo(...)
pthread_exit(NULL);
}
And:
pthread_create(&(threads[i]), NULL, thread_func, (void **) &err_array[i]);
I need help returning integer value from thread. I have tried several things and can't get it to work. I am new to C and yes this is homework, but I am stuck and need some help on this. I have created the pointer in the thread but when I pass it back to main, it does not show the right value. I have tried malloc and that does not work either. Any tips would be appreciated.
Here is the Code:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<pthread.h>
#include "FindNextHigher.h"
#include "SortNumber.h"
void *thread_next(void *arg)
{
/* Call FindNextHigher */
int *num =(int *)arg;
int next = FindNextHigher(*num);
printf("next= %d\n", next);
/* Convert int to pointer to pass and print to check*/
int *next_ptr=&next;
printf("nextptr= %d\n", *next_ptr);
return (void *)next_ptr;
}
int main(int argc, char *argv[])
{
FILE* f = fopen(argv[1], "r");
int i, num, *next_ptr;
printf("next_ptr = %d\n", *next_ptr);
pthread_t thread1, thread2, thread3, thread4;
void *exit_status;
for(i=1; i<=20; i++)
{
fscanf(f, "%d", &num);
if (i==1 || i<=60){
pthread_create(&thread1, NULL, thread_next, &num);
pthread_join(thread1, &exit_status);
printf("Threadid 1 processes number %d which is %d and the next higher number is %d\n", i, num, *next_ptr);
if (i==60){
printf("--------------Process finished for Thread 1----------");
}
}
else {
if (i==61 || i<=120){
pthread_create(&thread2, NULL, thread_next, &num);
pthread_join(thread2, &exit_status);
printf("Threadid 2 processes number %d which is %d and the next higher number is %d\n", i, num, *next_ptr);
if (i==120){
printf("--------------Process finished for Thread 2----------");
}
}
else{
if (i==121 || i<=180){
pthread_create(&thread3, NULL, thread_next, &num);
pthread_join(thread3, &exit_status);
printf("Threadid 3 processes number %d which is %d and the next higher number is %d\n", i, num, *next_ptr);
if (i==180){
printf("--------------Process finished for Thread 3----------");
}
}
else{
if (i==181 || i<=240){
pthread_create(&thread4, NULL, thread_next, &num);
pthread_join(thread4, &exit_status);
printf("Threadid 4 processes number %d which is %d and the next higher number is %d\n", i, num, *next_ptr);
if (i==240){
printf("--------------Process finished for Thread 4----------");
}
}
}
}
}
}
return 0;
}
There are some bugs. First of all, you don't initialize next_ptr before printing it.
Next, you share a pointer to the same instance of a variable between 4 threads, without any synchronization mechanism to protect the access to it. You will need to use a critical section or a mutex/semaphore.
First, there are somethings you'd want to watch out for:
int i, num, *next_ptr;
...
for(i=1; i<=20; i++)
{
fscanf(f, "%d", &num);
...
pthread_create(&thread1, NULL, thread_next, &num);
You are sending the same address (&num) to all threads, while reading the number for each thread separately. Since all of them have a pointer to the same number, most likely they are all going to take the last value (or arbitrarily any of their assigned or later values). So as argument, you would need to have as many nums as you have threads.
To return the integer, you can either return the integer cast to a void *, which would work, but it's not entirely standard. One solution would be to provide a place for the return value by the argument:
struct arg_and_return
{
int num;
int ret;
};
struct arg_and_return ar;
fscanf(f, "%d", &ar.num);
pthread_create(&thread, NULL, thread_func, &ar);
And within thread, fill in ((struct arg_and_return *)arg)->ret. Of course, still you need as many ars as you have threads.
You should not return a pointer to a variable that is local to your thread function, as next is in your code. The reason is pretty much the same as for any other function -- the variable's lifetime is over when the function exits (when the thread terminates), so a pointer to it is unreliable. Instead, try one of the following:
Use a variable from main and pass its address to your thread function when you start it, then modify it from the thread (but don't touch it from outside the thread while the thread is still running, unless you use a mutex).
Or, dynamically allocate the int in the thread and return a pointer to it; you would then free it from your main thread when you're done with it.
Or, if you're sure the representations are compatible, you can cast the int to be returned to a pointer type and return it, then cast back to int in your main thread. This is a common approach, but you need to be sure that it works on your system (it usually does if pointers are at least as large as ints, but you shouldn't take for granted that it will).
I'm not sure whats wrong with the program below, but it doesn't print each and every language once, but randomly some more often, some more less and some wont print
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char *messages[] = {
"English: Hello World!",
"French: Bonjour, le monde!",
"Spanish: Hola al mundo",
"Klingon: Nuq neH!",
"German: Guten Tag, Welt!",
"Russian: Zdravstvytye, mir!",
"Japan: Sekai e konnichiwa!",
"Latin: Orbis, te saluto!"
};
#define NUM_MESSAGES (sizeof( messages ) / sizeof( char* ))
void *PrintHello( void *messageid )
{
pthread_t taskid;
int *id_ptr, message_num;
taskid = pthread_self();
printf( "This is thread with ID %lu.\n", taskid );
message_num = *((int *) messageid);
printf( "%s \n", messages[message_num] );
pthread_exit( NULL );
}
int main( int argc, char *argv[] )
{
pthread_t threads[NUM_MESSAGES];
int rc, i;
for( i = 0; i < NUM_MESSAGES; i++ ) {
void * argument = (void*) &i;
rc = pthread_create( &threads[i], NULL, PrintHello, argument );
if( rc ) {
printf( "ERROR; return code from pthread_create() is %d\n", rc );
exit( -1 );
}
}
for( i = 0; i < NUM_MESSAGES; i++ ) {
pthread_join( threads[i], NULL );
}
pthread_exit( NULL );
}
I guess the problem is somehow connected with the argument pointer. I tried to lock different parts but with no success.
You're passing the address of the variable i, which the main thread keeps changing. So you're at the mercy of scheduling: will anyone change i before your thread has a chance to run ?
Instead, you could try directly passing the string, greatly simplifying the code:
rc = pthread_create( &threads[i], NULL, PrintHello, messages[i]);
void *PrintHello(void *arg)
{
char *msg = arg;
printf("%s\n", msg);
return NULL;
}
There's another, poorer alternative where you pass the actual value of i as the argument (not its address).
This is a typical race condition.
To be exact, after a new thread is created, the executing order of the threads determines the program outcome. There are two situations:
When the thread function PrintHello is executed before the next increments i++ and the assignment void * argument = (void*) &i; in main thread, it outputs what you expect.
When the new thread PrintHello has been created but does not get scheduled until the next i++ executed in main thread. In this situation, your reference of argument in the thread function, namely message_num = *((int *) messageid); is not what you expect.
A solution for this is to dynamically allocate (using malloc)argument, and free them in the thread function after using it.
One way to pass scalar integer arguments to thread functions is to (ab-)use the following text from ยง6.3.2.3 of the C99 standard:
(5) An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation.
Except for the last part of the second sentence, the following code should work on most systems:
int int_val;
...
pthread_create(..., ..., thread_func, (void *)int_val);
and then in thread_func cast it back to integer:
void *thread_func (void *data)
{
int int_arg = (int)data;
...
}