Scope of 4th argument for pthread_create function in C threading - c

#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.

Related

Why are my threads I created not printed in order?

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);

Can't synchronize my threads in C

I've a problem when I try to sychronize my threads. I have the next code:
static void* CarProcess(void *str);
int main()
{
thread_t *pthreadsArray;
pthreadsArray = (thread_t*)malloc(sizeof(thread_t) * 10);
for (int i = 0; i < 10; i++)
{
int pthread = mythread_create(&pthreadsArray[i], NULL, CarProcess, i);
}
for (int i = 0; i < 10; i++)
{
mythread_join(pthreadsArray[i], NULL);
}
}
static void* CarProcess(void *str)
{
while(1){
printf("Thread ID: %i\n", str);
}
}
When I execute the program, I have this output:
Thread ID: 0
Thread ID: 0
Thread ID: 0
Thread ID: 0
...
But never appears "Thread ID: 1", "Thread ID: 2", "Thread ID: 3"....or "Thread ID: 9". I think that it could be solved using Mutex, locking and unloking Mutex.. Does any body have idea how to solve that? Thanks
One possible source of the problem is that str is not really an int variable. You need to do some casting (both when creating the thread and when getting the argument).
To create a the thread and to properly pass the integer to ity ou first need to cast the value to an intptr_t, which is a standard integer type big enough to fit both an integer or a pointer. Then you should cast it to a generic pointer (i.e. void *):
pthread_create(&pthreadsArray[i], NULL, CarProcess, (void *) (intptr_t) i);
Then to get the integer value inside the thread function you need to do the opposite casting:
static void* CarProcess(void *str)
{
int i = (int) (intptr_t) str;
printf("Thread ID: %i\n", i);
}

Creating threads and providing argument to the function in C

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)

Compute the summation of a given interval using multiple threads

For my homework, I need to compute the squares of integers in the interval (0,N) (e.g. (0,50) in a way that the load is distributed equally among threads (e.g. 5 threads). I have been advised to use small chunks from the interval and assign it to the thread. For that, I am using a queue. Here's my code:
#include <stdio.h>
#include <pthread.h>
#define QUEUE_SIZE 50
typedef struct {
int q[QUEUE_SIZE];
int first,last;
int count;
} queue;
void init_queue(queue *q)
{
q->first = 0;
q->last = QUEUE_SIZE - 1;
q->count = 0;
}
void enqueue(queue *q,int x)
{
q->last = (q->last + 1) % QUEUE_SIZE;
q->q[ q->last ] = x;
q->count = q->count + 1;
}
int dequeue(queue *q)
{
int x = q->q[ q->first ];
q->first = (q->first + 1) % QUEUE_SIZE;
q->count = q->count - 1;
return x;
}
queue q; //declare the queue data structure
void* threadFunc(void* data)
{
int my_data = (int)data; /* data received by thread */
int sum=0, tmp;
while (q.count)
{
tmp = dequeue(&q);
sum = sum + tmp*tmp;
usleep(1);
}
printf("SUM = %d\n", sum);
printf("Hello from new thread %u - I was created in iteration %d\n",pthread_self(), my_data);
pthread_exit(NULL); /* terminate the thread */
}
int main(int argc, char* argv[])
{
init_queue(&q);
int i;
for (i=0; i<50; i++)
{
enqueue(&q, i);
}
pthread_t *tid = malloc(5 * sizeof(pthread_t) );
int rc; //return value
for(i=0; i<5; i++)
{
rc = pthread_create(&tid[i], NULL, threadFunc, (void*)i);
if(rc) /* could not create thread */
{
printf("\n ERROR: return code from pthread_create is %u \n", rc);
return(-1);
}
}
for(i=0; i<5; i++)
{
pthread_join(tid[i], NULL);
}
}
The output is not always correct. Most of the time it is correct, 40425, but sometimes, the value is bigger. Is it because of the threads are running in parallel and accessing the queue at the same time (the processor on my laptop is is intel i7)? I would appreciate the feedback on my concerns.
I think contrary to what some of the other people here suggested, you don't need any synchronization primitives like semaphores or mutexes at all. Something like this:
Given some array like
int values[50];
I'd create a couple of threads (say: 5), each of which getting a pointer to a struct with the offset into the values array and a number of squares to compute, like
typedef struct ThreadArgs {
int *values;
size_t numSquares;
} ThreadArgs;
You can then start your threads, each of which being told to process 10 numbers:
for ( i = 0; i < 5; ++i ) {
ThreadArgs *args = malloc( sizeof( ThreadArgs ) );
args->values = values + 10 * i;
args->numSquares = 10;
pthread_create( ...., threadFunc, args );
}
Each thread then simply computes the squares it was assigned, like:
void *threadFunc( void *data )
{
ThreadArgs *args = data;
int i;
for ( i = 0; i < args->numSquares; ++i ) {
args->values[i] = args->values[i] * args->values[i];
}
free( args );
}
At the end, you'd just use a pthread_join to wait for all threads to finish, after which you have your squares in the values array.
All your threads read from the same queue. This leads to a race condition. For instance, if the number 10 was read simultaneously by two threads, your result will be offset by 100. You should protect your queue with a mutex. Put the following print in deque function to know which numbers are repeated:
printf("Dequeing %d in thread %d\n", x, pthread_self());
Your code doesn't show where the results are accumulated to a single variable. You should protect that variable with a mutex as well.
Alternatively, you can pass the start number as the input parameter to each thread from the loop so that each thread can work on its set of numbers. First thread will work on 1-10, the second one on 11-20 and so on. In this approach, you have to use mutex only the part where the threads update the global sum variable at the end of their execution.
First you need to define what it means to be "distributed equally among threads." If you mean that each thread does the same amount of work as the other threads, then I would create a single queue, put all the numbers in the queue, and start all threads (which are the same code.) Each thread tries to get a value from the queue which must be protected by a mutex unless it is thread safe, calculates the partial answer from the value taken from the thread, and adds the result to the total which must also be protected by a mutex. If you mean that each thread will execute an equal amount of times as each of the other threads, then you need to make a priority queue and put all the numbers in the queue along with the thread number that should compute on it. Each thread then tries to get a value from the queue that matches its thread number. From the thread point of view, it should try to get a value from the queue, do the work, then try to get another value. If there are no more values to get, then the thread should exit. The main program does a join on all threads and the program exits when all threads have exited.

Concurrency with pthreads, a typical misbehaviour

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;
...
}

Resources