Main() thread id is different after creating another thread - c

I've been reading and learning about POSIX threads, and tried to write some simple codes to understand it better.
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
/* function to be executed by the new thread */
void* PrintHello(void* data)
{
pthread_t tid = (pthread_t)data;
printf("Hello from new thread %d - got %d\n", pthread_self(), tid);
pthread_exit(NULL); /* terminate the thread */
}
int main(int argc, char* argv[])
{
int rc; /* return value */
pthread_t thread_id;
int tid;
thread_id = pthread_self();
printf("FLAG = %d ", thread_id);
/* create a new thread that will execute 'PrintHello' */
rc = pthread_create(&thread_id, NULL, PrintHello, (void*)thread_id);
if(rc) /* could not create thread */
{
printf("\n ERROR: return code from pthread_create is %u \n", rc);
exit(1);
}
printf("\n Created new thread (%d) ... \n", thread_id);
pthread_exit(NULL); /* terminate the thread */
}
For this code I get the following output:
FLAG = 363480832
Created new thread (355198720) ...
Hello from new thread 355198720 - got 363480832
What is bothering me is why thread_id which is 363480832, becomes 355198720, same as thread_id of a function that was called from main (PrintHello()). I assumed that thread id doesn't change throughout the program execution. Or is it something inside the function that changes it?

If you're doing anything with a pthread_t other than passing it to a function that takes one, you're doing something wrong. Only the pthreads API knows how to use a pthread_t correctly. They can have any internal structure that's convenient for the implementation.
Being a C language construct, pthread_t behaves more like char *. The necessary language constructs to make it behave like std::string don't exist. So you have to treat it like char *.
A char * contains a string somehow, but you have to understand its implementation to get that value out. Consider:
char *j = "hello";
char *k = strdup (j);
if (j == k)
printf ("This won't happen\n");
printf ("%d\n", j);
printf ("%d\n", k); // these won't be equal
You can't compare char *'s with == to see if they refer to the same string. And if you print out j and k, you'll get different values.
Similarly, a pthread_t refers to one particular thread somehow. But you have to understand how to get the value out. Two pthread_ts can have different apparent values but still refer to the same thread just as two char *s can have different apparent values but still refer to the same string.
Just as you compare two char *'s with strcmp if you want to tell if they refer to the same string value, you compare two pthread_ts with pthread_equal to tell if they refer to the same thread.
So this line of code makes no sense:
printf("FLAG = %d ", thread_id);
A pthread_t is not an integer and you can't print it with a %d format specifier. POSIX has no printable thread IDs. If you want one, you need to code one (perhaps using pthread_getspecific).

In C, arguments are passed by value. In particular, the argument (void *)thread_id is an expression that's evaluated before calling pthread_create, so the fact that pthread_create writes to thread_id as a result of &thread_id being passed as the first argument is irrelevant. If you were instead passing &thread_id rather than (void *)thread_id as the argument to the new thread start function, and dereferencing it there, then you may see the effects you want; however, it's not clear to me that pthread_create's writing of the new thread id via its first argument is required to take place before the new thread starts, so there is probably a data race if you do it that way.
Further, note that David's answer is also correct. It's invalid to print thread ids this way since they are formally an opaque type.

In this line:
rc = pthread_create(&thread_id, NULL, PrintHello, (void*)thread_id);
as the manual says, pthread_create() shall store the ID of the created thread in the location referenced by thread_id. In this example, it would be modified to 355198720, which is the tid of new thread PrintHello().
Besides, it may be better to change the argument for PrintHello to:
rc = pthread_create(&thread_id, NULL, PrintHello, (void*)&thread_id);
and in PrintHello(), it would be:
void* PrintHello(void* data)
{
pthread_t tid = (pthread_t)(*data);
...
}

Related

How to use Multithreading in C? [duplicate]

This question already has answers here:
How to "multithread" C code
(13 answers)
Closed 3 years ago.
This is my first contact with c and Multithreading.
I look for an example how to use it in Basic.
This is what I want to to parallel:
PseudoCode that should run on different Threads
Code1
int main(){
int i =1000;
while(i>0){
i--;
}
}
Code2
int main(){
int x =0;
if(i%5){
x++;
}
}
I also didn't know how to pass Objects, maybe someone can explaine this too.
Please use only lowercase in C to declaring variables and functions
as struct,typeof,sizeof,int,char,void,for,while,etc....
EDIT:
Sorry for not to understand "I thought you need help to do that code in C"
Now i know that you want multi-threading functions to do two jobs or more at the same time without waiting for other to finish.
Okay, to do that you have to
include pthread.h which means POSIX Thread
Note: you should notice from this name that this library for Linux OS only
and you compile it with gcc compiler
declare variable pthread to for example: tid in your main() as the most popular name
Create your function in void *() and type stuff whatever it does then create your thread in main() and assign it your function through that code:
pthread_create(&tid, NULL, MyThread, NULL);
pthread_create() arguments:
A pointer to a pthread_t structure that we created to fill it with the upcoming arguments.
A pointer to a pthread_attr_t with parameters for the thread. You can safely just pass NULL most of the time.
Note: The pthread_attr_t > "arg 2" should be treated as opaque: any access to
the object other than via pthreads functions is nonportable and
produces undefined results.
Take the function that you created as thread and shall be with no return and
points to >> void, that's why we created void *()
Note: Type only the name of function without (), you will know why in the next argument
Here you passing your arguments to your function!, if there's no arguments just pass NULL
Example Code:
#include <stdio.h>
#include <pthread.h>
int i=0,x=0; //Initialize our variables
void *MyThread(void *ANYarg) //arguments must be a pointers to point from `pthread_create` with `NULL` if no need
{
while(1) //background thread
{
i++;
x++;
}
return NULL;
}
int main()
{
char *input;
pthread_t tid; //Declare a thread
pthread_create(&tid, NULL, MyThread, NULL); //Create the thread
while(1) //Printing thread , Uncover increamting of variables
{
scanf("%s",&input); //whenever you input a value
printf("i: %d, x: %d\n",i,x);//will print the i,x values now
}
return 0;
}
Note: You should at least create one pointer variable specifically to your thread function cause fourth argument of pthread_create() need at least one to pass the NULL value
You can wait for an thread to finish instead of doing work at the same time through that code line:
pthread_join(tid, NULL);
Should return 0 when success
An Example:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *MyCoolthread(void *vargp)
{
printf("Yes..see me printing success after 3 seconds \n");
sleep(3);
printf("Success! \n");
return NULL;
}
int main()
{
pthread_t tid;
printf("Hello, are you there? \n");
sleep(1);
pthread_create(&tid, NULL, MyCoolthread, NULL);
pthread_join(tid, NULL);
printf("Yup i see!\n");
return 0;
}
Try to comment pthread_join(tid, NULL); with // to see what happens
and to terminate your thread is through code line:
pthread_exit(&tid);
Doesn't return to its caller any value
Edit: I noticed now that you use windows so i advice you to dual boot with Ubuntu instead if you really interested in C
otherwise you can use multi-threading in windows.h header that called winapi library but i'm not expert in so you can find an simple example here and you should mentioned in your post that you want for windows by the way you can edit to improve it
I tried my best to get it clear, hope it helps.

C: is pthread_self() and pthread_t variable one and the same?

This is what I am wondering:
If I create a thread with pthread_create() and then call pthread_self() from that thread, will that value match the pthread_t value that I pass to pthread_create in the main thread?
//pthread_t variable
pthread_t producer_thread = (pthread_t*)malloc(sizeof(pthread_t));;
//create the thread
pthread_create(producer_thread, NULL, producer, NULL);
printf("Pthread_t variable after creating thread says %d\n", producer_thread);
....
//function passed to thread
void producer(void *p){
printf("Pthread self says: %d\n", pthread_self());
}
Return type of pthread_self is pthread_t which is basically a pointer not of integer type.
So, it is printing its address(typecasted to int), not pthread_t structure.
You can use pthread_equal function to check if these pthread_t are same or not. Means, in another thread, use
printf("%d\n", pthread_equal(mythreadId, pthread_self()));
It should print a non-zero number indicating that they correspond to the same thread.
If they are not same, then it is a problem.
Print mythreadId in the thread what is spawns. It must match with main's pthread_t. If they are different, then there is a problem.

POSIX parent/child threads not sharing data

One final question for the evening. I have a homework question that I cannot seem to solve, and after spending the better part of the night on it, I'll ask it here.
The problem is a program that is to calculate the Fibonacci sequence given an integer input at the command line (./foo.out 15, for example, and it will calculate the first 15 Fibonacci numbers). The additional parameters are as follows:
1.) It must use two POSIX threads, a parent thread and a child thread.
2.) It must share data (an array) between them.
Currently, the function is breaking when program control passes back to the parent thread. All I am getting is a completely non-descriptive segfault. As can be seen below, I have it outputting at every possible change in control.
Code:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
void *fibonacci(void *param, int numbers[]);
void *runner(void *param);
int main(int argc, char *argv[])
{
pthread_t tid;
pthread_attr_t attr;
if ( argc != 2)
{
fprintf(stderr, "Usage: 426.out <integer value> \n");
return -1;
}
if (atoi(argv[1]) < 0)
{
fprintf(stderr, "Argument must be non-negative\n");
return -2;
}
pthread_attr_init(&attr);
pthread_create(&tid, &attr, runner, argv[1]);
pthread_join(tid,NULL);
return 0;
}
void *fibonacci(void *param, int numbers[])
{
int it, IT_MAX;
printf("Entering Child Thread:\n");
IT_MAX = atoi(param);
numbers[0] = 0;
numbers[1] = 1;
for (it = 2; it < IT_MAX; ++it)
{
numbers[it] = (numbers[it - 1] + numbers[it - 2]);
}
for (it = 0; it < IT_MAX; ++it)
{
printf("%d\n", numbers[it]);
}
printf("Exiting Child Function.\n");
}
void *runner(void *param)
{
int it, IT_MAX;
int numbers[IT_MAX];
pthread_t tid;
pthread_attr_t attr;
printf("Entering Parent Thread:\n");
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fibonacci(param, numbers), NULL);
pthread_join(tid, NULL);
IT_MAX = atoi(param);
for (it = 0; it < IT_MAX; it++)
{
printf("%d\n", numbers[it]); // I suspect the program breaks here
// It produces a segfault rather than this
}
printf("Leaving Parent Thread\n");
}
The question I have, if it is not clear from above, is what am I doing wrong. I am using gcc, and have been using the -Wall -Werror and -lpthread. -Werror keeps throwing "Control Structure going to end of non-void function", but nothing has anything to say about what can be causing the segfault. As before, I looked for the last hour for a question or article that addresses this, so if this is a dupe, please point me to the question or article in which it is addressed. Thanks to anyone in advance for their help.
One of your problems is in this line:
pthread_create(&tid, &attr, fibonacci(param, numbers), NULL);
Instead of starting a thread with the fibonacci() function, this calls the fibbonacci() function in the current thread and passes the result to pthread_create() as the thread start function. fibonacci() doesn't return a function pointer, so this new thread will crash the program.
You need to just pass fibonacci as the third parameter.
Futhermore, fibonacci() must be declared as void *fibonacci(void *) in order to be used as a thread start function. If you want to pass two parameters, you'll need to place them into a struct and pass a pointer to that.
This pair of lines is also problematic:
int it, IT_MAX;
int numbers[IT_MAX];
IT_MAX is an uninitialised variable, and you use it here to define the size of the numbers[] array. That could also be leading to your crash.
This line
pthread_create(&tid, &attr, fibonacci(param, numbers), NULL);
does not pass the address of fibonacci() to pthread_create() but calls fibonacci(param, numbers)and passes the result returned to pthread_create() as 3rd argument.

How to pass one or multiple variables to a newly created thread?

I'm learning about threads now. I'm wondering if it is possible to pass a variable to my thread. My assignement is to create a thread and assign a number (a name if you will) to each thread and print the number every 100ms. my current program is as below :
#define PCHECK(sts,msg) if((sts)!=0){printf("error : %s\n",msg); exit(EXIT_FAILURE)}
#define NB_THREAD 5
void* do_nothing(void* data)
{
int i;
//printf("creation thread %d",(int)data);
while(1)
{
usleep(100000);
printf("thread number : %d \n",data);
}
i = 0;
pthread_exit(NULL);
//exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
{
int pid, j, status;
pthread_t thread;
int * res;
int stat;
for (j = 0; j < NB_THREAD; j++)
{
stat = pthread_create(&thread, NULL, do_nothing, (void *) j );
if (stat !=0)
{
perror ("pthread_create()");
}
}
for (j = 0; j < NB_THREAD; j++)
{
pthread_join(thread, (void **) &res );
}
return EXIT_SUCCESS;
}
for the moment the only number getting printed is 0 (the value of data). Can someone point out where did i went wrong thanks :)
Here are some good examples of how to pass arguments to pthreads
[1] https://computing.llnl.gov/tutorials/pthreads/#PassingArguments
I suspect that your problem might be that your running this on a 64-bit system that uses 32-bit int types. So data is a 64-bit void* type but in your thread function you're printing it out as a 32-bit int:
// example assumes that this thread instance was started by
// pthread_create(&thread, NULL, do_nothing, (void *) j ) when
// j == 1
printf("thread number : %d \n",data);
^ ^
| +-------- passing a 64-bit pointer 0x00000000.00000001
|
+---------------- treats the pointer argument as a 32-bit int and
happens to only see the all-zero 32-bits
I suspect that you'll get the output you expect if you change the printf() to:
printf("thread number : %d \n", (int) data);
As a general rule, when writing thread functions I think it's a good idea to have the first actions of the thread function be to convert the data item passed to the thread function to the type that was actually passed to pthread_create():
void* do_nothing(void* data)
{
int id = (int) data; // `pthread_create()` was passed an `int`
// `data` is not used again after this point
// ...
}
A few other points
if you pass an actual pointer to data to the thread function, make sure that each thread gets their own separate copy (unless the data is supposed to be the same instance for each thread, which is possible but uncommon).
if you're spinning up multiple threads you either need to keep each pthread_t object returned by pthread_create() (in an array, maybe) so you can join on them later, or you need to call pthread_join()/pthread_detach() before reusing the pthread_t object so that the system can clean up any resources it has allocated for that thread when the thread finished running. In the example as posted that might not matter much because the threads will run forever (or until something kills the process). The pthread_join() call you have will never complete successfully.
But the following code is destined to break when you change things so the thread function stops after some amount of time:
for (j = 0; j < NB_THREAD; j++)
{
pthread_join(thread, (void **) &res );
}
Because thread only has the pthread_t for the last thread created, once it successfully joins it's not valid to use any more. The next loop iteration will try to join a thread that's already been joined and is no longer valid.

Can threads write to different elements of same array of structures without locking?

I'm trying to use threads (for the first time!) in a GCC C application which works fine in non-threaded mode. When I run it some threads give results which are all zero instead of the required answers (which I know for checking purposes), but the threads giving zeroes are not the same each time I run it. The ones which give non-zero answers are correct, so the code appears to run ok as such. I wonder if anyone can point out areas where I might have something which is not thread-safe.
My own thoughts are it may be due to how I collect results or maybe memory allocation - I use malloc and free but elsewhere in StackOverflow I see that GCC malloc is considered thread-safe if linked with -lpthread (which I am doing). Nothing uses global/static variables - everything is passed as function arguments.
In order to pass results back to main, my threaded routine uses an array of structures. Each thread writes to a distinct element of this array, so they are not trying to write to the same memory. Maybe I need to use some form of locking when writing results even though they don't go to the same element of the structure array?
I followed the recipe for threaded code here:
https://computing.llnl.gov/tutorials/pthreads/#Abstract
I attach (simplified) code extracts in case this gives any clues (I may have omitted/modified something incorrectly but I am not asking for anyone to spot bugs, just the general methodology).
typedef struct p_struct { /* used for communicating results back to main */
int given[CELLS];
int type;
int status;
/*... etc */
} puzstru;
typedef struct params_struct { /* used for calling generate function using threads */
long seed;
char *text;
puzzle *puzzp;
bool unique;
int required;
} paramstru;
/* ========================================================================================== */
void *myfunc(void *spv) /* calling routine for use by threads */
{
paramstru *sp=(paramstru *)spv;
generate(sp->seed, sp->text, sp->puzzp, sp->unique, sp->required);
pthread_exit((void*) spv);
}
/* ========================================================================================== */
int generate(long seed, char *text, puzstru *puzzp, bool unique, int required)
{
/* working code , also uses malloc and free,
puts results in the element of a structure array pointed to by "puzzp",
which is different for each thread
(see calling routine below : params->puzzp=puz+thr; )
extract as follows: */
puzzp->given[ix]=calcgiven[ix];
puzzp->type=1;
puzzp->status=1;
/* ... etc */
}
/* ========================================================================================== */
int main(int argc, char* argv[])
{
pthread_t thread[NUM_THREADS];
pthread_attr_t threadattr;
int thr,threadretcode;
void *threadstatus;
paramstru params[1];
/* ....... ETC */
/* set up params structure for function calling parameters */
params->text=mytext;
params->unique=TRUE;
params->required=1;
/* Initialize and set thread detached attribute */
pthread_attr_init(&threadattr);
pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_JOINABLE);
for(thr=0; thr<NUM_THREADS; thr++)
{
printf("Main: creating thread %d\n", thr);
params->seed=ran_arr_next(startingseeds);
params->puzzp=puz+thr;
threadretcode = pthread_create(&thread[thr], &threadattr, myfunc, (void *)params);
if (threadretcode)
{
printf("ERROR; return code from pthread_create() is %d\n", threadretcode);
exit(-1);
}
}
/* Free thread attribute and wait for the other threads */
pthread_attr_destroy(&threadattr);
for(thr=0; thr<NUM_THREADS; thr++)
{
threadretcode = pthread_join(thread[thr], &threadstatus);
if (threadretcode)
{
printf("ERROR; return code from pthread_join() is %d\n", threadretcode);
exit(-1);
}
printf("Main: completed join with thread %d having a status of %ld\n",thr,(long)threadstatus);
}
/* non-threaded code, print results etc ............. */
free(startingseeds);
free(puz);
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
For the benefit of others reading this - all the answers were correct, and the answer to the question in the heading is YES, threads can write safely to different elements of the same array of structures, my problem was in the calling routine - the following is the amended code snippet (now works fine):
paramstru params[NUM_THREADS];
for(thr=0; thr<NUM_THREADS; thr++)
{
printf("Main: creating thread %d\n", thr);
/* set up params structure for function calling parameters */
params[thr].text=mytext;
params[thr].unique=TRUE;
params[thr].required=1;
params[thr].seed=ran_arr_next(startingseeds);
params[thr].puzzp=puz+thr;
threadretcode = pthread_create(&thread[thr], &threadattr, myfunc, (void *)&params[thr]);
if (threadretcode)
{
printf("ERROR; return code from pthread_create() is %d\n", threadretcode);
exit(-1);
}
}
To answer your question, it is perfectly fine to write to different elements of the same array from different threads without locking. There will only ever be a data race if two threads write to the same byte without synchronizing (e.g., locking).
As other answers point out, the reason your code as-written breaks is because you pass a pointer to the same params object to each of your threads, an then you modify that object. You probably want to create a new param for each thread.
paramstru params[1];
The code is passing the same structure to all threads. Just the thread initialization loop is overwriting the data that a thread should work on:
for(thr=0; thr<NUM_THREADS; thr++)
{
printf("Main: creating thread %d\n", thr);
params->seed=ran_arr_next(startingseeds); /* OVERWRITE */
params->puzzp=puz+thr; /* OVERWRITE */
The reason the non-threaded code works is because each call to myfunc() terminates before the params structure is changed.
You only created one copy of your parameter structure and are overwriting it and passing the same address to each thread. Dont' you want paramstru params[NUM_THREADS];?

Resources