I am not sure I understand semaphores and threads so I decided to try a relatively simple example. I am trying to have 2 threads that will alternate printing, one printing "ping" the other printing "pong" each notifying the other that it is done by use of a semaphore. But when I implement the code below, it prints ping several hundred times followed by pong several hundred times with a slight pause.
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
sem_t pingsem;
void ping(){
printf("Ping started\n");
while(1){
sem_wait(&pingsem);
printf("ping\n");
sem_post(&pingsem);
}
}
void pong(){
printf("Pong started\n");
while(1){
sem_wait(&pingsem);
printf("pong\n");
sleep(1);
sem_post(&pingsem);
}
}
int main(){
sem_destroy(&pingsem); //make sure the semaphore starts dead
sem_init(&pingsem, 0, 1); //initialize semaphore
pthread_t ping_thread, pong_thread; //start the threading
pthread_create(&ping_thread, NULL, ping, NULL);
pthread_create(&pong_thread, NULL, pong, NULL);
pthread_join(ping_thread,NULL);
pthread_join(pong_thread,NULL);
return 0;
}
I compile using:
gcc stest.c -o stest -lpthread -lrt
with no errors or warnings, but when I run it I get:
$ ./stest
Ping started
ping
ping
ping
ping
Pong started
ping
ping
.
. hundreds of pings
.
ping
ping
ping
pong
pong
pong
pong
.
. hundreds of pongs
.
It will eventually switch off but why are the threads not alternating printing every other one?
The problem shown in your example is, it's a race because neither read effectively blocks the other. Both threads run as the scheduler allows. The way it's coded, each thread can free-run (loop) multiple times during its time slice, and satisfies its own semaphore test. On a multi-core/multi-CPU system with a typical schedule, both threads can both run simultaneously and step all over each other somewhat arbitrarily.
Here's a working ping-ponging threads example that uses complimentary semaphores to create the ping-pong interlock you want.
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
sem_t pingsem, pongsem;
void *
ping(void *arg)
{
for (;;) {
sem_wait(&pingsem);
printf("ping\n");
sem_post(&pongsem);
}
}
void *
pong(void *arg)
{
for (;;) {
sem_wait(&pongsem);
printf("pong\n");
sem_post(&pingsem);
}
}
int
main(void)
{
sem_init(&pingsem, 0, 0);
sem_init(&pongsem, 0, 1);
pthread_t ping_thread, pong_thread;
pthread_create(&ping_thread, NULL, ping, NULL);
pthread_create(&pong_thread, NULL, pong, NULL);
pthread_join(ping_thread, NULL);
pthread_join(pong_thread, NULL);
return 0;
}
Because when you create a thread it will execute as soon as the OS says it can!
So you created two threads like so:
pthread_create(&ping_thread, NULL, ping, NULL);
// scheduler interrupt from OS
pthread_create(&pong_thread, NULL, pong, NULL);
Which was fine, but the OS saw the first new thread and ran it until its timeslice was exhausted. Only then did the main thread get back control long enough to create the next thread.
As for why they're not alternating is a different issue! You see how difficult thread synchronization can be? You have this code:
while(1){
sem_wait(&pingsem);
printf("ping\n");
sem_post(&pingsem);
}
But you initialized the semaphore to the value of 1. So sem_wait decrements to 0, then prints a message, then increments back to 1. No problem, right?
Well the delay between the sem_post and the subsequent(next loop) sem_wait is only 1 instruction, a jump back to the beginning of the loop. So unless, by chance, the OS interrupts the thread after the sem_post, but before the sem_wait, the single thread will continue printing on its own.
You need two semaphores, 'pingsem' and 'pongsem', say. Initialize one to 1 and the other to zero. Then:
ping_thread:
while(true){
wait(pingsem);
doWork();
send(pongsem);
}
pong_thread:
while(true){
wait(pongsem);
doWork();
send(pingsem);
}
The one unit that was initialized into one semaphore then acts as a work token and is signaled back-and-forth between the threads. Only the thread with the token can do the work, the other has to wait until it gets the token.
James T. Smith has the right answer.. that since you didn't schedule out before grabbing your lock again, you would expect just about every time it would be able to re-grab the lock before the thread finished it's time slice.
If you want to force scheduling out so that the other one can run, you can try sleep(0) or sched_yield(). This will force a scheduling out so that if another thread was waiting to run it would. This would be more likely to see your ping,pong,ping,pong. But still not a guarantee and completely dependent on your OS scheduler (and probably only works on a single core system with both threads at the same priority).
Try this: (like I said.. no guarantees.. but a good possibility it will work)
void ping(){
printf("Ping started\n");
while(1){
sem_wait(&pingsem);
printf("ping\n");
sem_post(&pingsem);
sched_yield(); // Schedule out.
}
}
void pong(){
printf("Pong started\n");
while(1){
sem_wait(&pingsem);
printf("pong\n");
sleep(1);
sem_post(&pingsem);
sched_yield(); // Schedule out.
}
}
edit: changed to sched_yield()
The other answers are correct, I'm just posting code that will run as you desire (on OSX 10.10.3 anyway)
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
sem_t pingsem;
void ping(){
printf("Ping started\n");
while (1) {
sem_wait(&pingsem);
printf("ping\n");
sem_post(&pingsem);
}
}
void pong(){
printf("Pong started\n");
while (1) {
sem_wait(&pingsem);
printf("pong\n");
sem_post(&pingsem);
}
}
int main(){
sem_destroy(&pingsem); //make sure the semaphore starts dead
sem_init(&pingsem, 0, 1); //initialize semaphore
pthread_t ping_thread, pong_thread; //start the threading
pthread_create(&ping_thread, NULL, ping, (void *)0);
pthread_create(&pong_thread, NULL, pong, (void *)1);
pthread_exit(NULL);
return 0;
}
Related
Value of Global variable var in main() function sometimes comes -1 and sometimes 1 .How to write a robust code without using sleep function so that thread get time to get started and running .
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int var = -1; // GLobal Variable
void *myThreadFun(void *vargp)
{
var = 1;
return NULL;
}
int main()
{
pthread_t thread_id;
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThreadFun, NULL);
printf("var=%d",var);
pthread_join(thread_id, NULL);
printf("After Thread\n");
exit(0);
}
Value of Global variable var in main() function sometimes comes -1 and
sometimes 1 .How to write a robust code without using sleep function
so that thread get time to get started and running .
It is a distressingly common misconception among those new to multithreaded programming that problems such as yours are a matter of timing. That is not the case, at least not from the perspective of the threading and memory models of most modern high-level programming languages. No amount of delay alone ensures that one thread will see the effects on memory produced by another, therefore robust code does not use timing functions such as sleep() for that purpose.
Rather, the issue is one of synchronization. This is the area that contains rules about what writes to memory by one thread must be visible to other threads. It also covers special kinds of objects and functions that serve to enable threads to affect the execution of other threads, generally by temporarily blocking them from proceeding. These two facets are closely linked.
The pthread_create() and pthread_join() functions have synchronization effects. Among other things, all writes to memory by a thread T1 before it calls pthread_create() to start a thread T2 are visible to T2 (modulo subsequent rewrites of the same memory). All writes to memory by T2 are visible to T1 after it successfully joins T2 via pthread_join(). Therefore, one solution to the question as posed is to wait until after joining the second thread before attempting to read var, as #Robert's answer suggests.
If that is undesirable, then you'll need to engage some other kind of synchronization mechanism to make the main thread wait for the second to update var. Such a wait on a synchronization object will also have the effect of making the second thread's write visible to the main thread.
The most general-purpose synchronization technique offered by pthreads is the condition variable which must be used in conjunction with a mutex. You will find many explanations here on SO and elsewhere about how properly to use a CV.
For your particular case, however, you might find a semaphore easier to set up and use. Semaphores are technically separate from the pthreads library proper, but they have suitable synchronization semantics, both for making threads wait and for making memory operations of one thread visible to another. That might look like this:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
int var = -1; // GLobal Variable
sem_t semaphore;
void *myThreadFun(void *vargp)
{
var = 1;
// increment the semaphore's value
sem_post(&semaphore);
return NULL;
}
int main()
{
pthread_t thread_id;
// initialize the semaphore with value 0
sem_init(&semaphore, 0, 0);
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThreadFun, NULL);
// Wait until the semaphore's value can be decremented by one without
// it becoming negative (and then perform the decrement before proceeding).
sem_wait(&semaphore);
printf("var=%d",var);
pthread_join(thread_id, NULL);
printf("After Thread\n");
exit(0);
}
I think your code is robust, it's just where you print the result which is incorrect. You need to ensure your thread has finished his work before printing the result.
If you print the result before calling pthread_join, there are two possibilities:
myThreadFun has already changed var, in such case var will contain the value 1
myThreadFun hasn't been completely executed, in such case, var will have its initial value -1.
If you print the result after calling pthread_join, the function myThreadFun will be fully executed and it will print 1.
int main()
{
pthread_t thread_id;
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThreadFun, NULL);
pthread_join(thread_id, NULL);
printf("After Thread\n");
printf("var=%d",var); /* Here, the thread has completed */
exit(0);
}
Robert's solution is sensible, but I believe you don't actually want to wait for the thread to complete.
If you want the main thread to wait for the variable to be set by the thread without waiting for the thread to end, you will need some kind of synchronization. I'll use a semaphore, but there are a number of other solutions.
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
static sem_t started_threads_sem;
static int var;
static void *myThreadFun(void *vargp) {
sleep(3); // This is the thread doing some initialization.
var = 1;
sem_post(&started_threads_sem);
sleep(3); // This is the thread doing stuff.
return NULL;
}
int main() {
printf("Before Thread\n");
sem_init(&started_threads_sem, 0, 0);
pthread_t thread_id;
pthread_create(&thread_id, NULL, myThreadFun, NULL);
// Wait for the thread to have started.
sem_wait(&started_threads_sem);
printf("var=%d\n", var);
pthread_join(thread_id, NULL);
printf("After Thread\n");
exit(0);
}
Before Thread
<3 s pause>
var=1
<3 s pause>
After Thread
I'm working on a application that has specific timing restraints such that an event should occur (ideally exactly) every 200us. I'm trying to do this with a timer and signal.
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
timer_t timer_id;
void start_timer(void)
{
struct itimerspec value;
value.it_value.tv_sec = 0;
value.it_value.tv_nsec = 20000;
value.it_interval.tv_sec = 0;
value.it_interval.tv_nsec = 200000;
timer_create(CLOCK_REALTIME, NULL, &timer_id);
timer_settime(timer_id, 0, &value, NULL);
}
void handler(int sig) {
printf("in handler\n");
}
void *my_thread(void *ignore)
{
(void)ignore;
start_timer();
// Sleep forever
while(1) sleep(1000);
}
int main()
{
pthread_t thread_id;
(void) signal(SIGALRM, handler);
pthread_create(&thread_id, NULL, my_thread, NULL);
// sleep is a placeholder for this SO question. I want to do
// other processing here
sleep(5000);
printf("sleep finished\n");
}
After 200us the signal handler is called. It appears to be called when the sleep(5000) line is running because the "sleep finished" message is displayed early. I want the timer to disrupt the thread that started the timer, not the main process. This is why I created a thread to start it. Is there a way to have the signal only abort the current instruction on the thread instead of on the main process? I know that the other threads/processes will be blocked when the handler runs, but I wanted them to continue afterwards as if nothing happened. For example, in this case I want to sleep at least 5000 seconds.
Yes, you can block the signal (pthread_sigmask) in the main thread before starting any other threads, and only unblock it in the thread intended to handle it. This will ensure that it arrives in the thread you want it in.
However, if you already have threads, are you sure you actually need a timer generating a signal for this? clock_nanosleep should allow sleep with wakeup at a precise time, and avoids all the awfulness of signals.
I am doing a project with pthreads and I can not go further. I have 3 threads, one thread shall read some sensor values via I2C (SMBUS), one shall calculate something by using the data porvided by the first thread, and finally last thread shall print the data on screen. A mutex shall be responsible for the synchronisation between threads. How can I use infinite while loop in threads, since my threads don't just "do the job and finish"? They shall continue forever (or untill Ctrl+C key is pressed).
And where should I put the pthread_join functions?
My first approach is below but it is not working properly:
Thanks for your help.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
typedef struct vector {
double x;
double y;
double z;
} vector_t;
typedef struct all_vectors {
vector_t *gyro;
vector_t *accel;
vector_t *magnet;
} vectors_t;
vectors_t *vectors;
pthread_t th1, th2, th3;
pthread_mutex_t mutex;
int main()
{
initSensors(); //defined in another .c file
pthread_mutex_init(&mutex, NULL);
pthread_create(&th1, NULL, (void *) &readSensors, (void *) vectors);
pthread_create(&th2, NULL, (void *) &calculateAngle, NULL);
pthread_create(&th3, NULL, (void *) &printData, NULL);
while(1)
{
sleep(1);
}
/* The program never reaches the following codes ? */
pthread_mutex_destroy(&mutex);
pthread_exit(NULL);
}
void readSensors(void *vectors)
{
vectors_t *vecs = (vectors_t *)vectors;
while(1)
{
pthread_mutex_trylock(&mutex);
readGyro(vecs->gyro); //defined in another .c file
readAccel(vecs->accel); //defined in another .c file
readMagnet(vecs->magnet); //defined in another .c file
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
void calculateAngle()
{
while(1)
{
pthread_mutex_trylock(&mutex);
doSomeCalculation(vectors); //defined in another .c file
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
void printData()
{
while(1)
{
pthread_mutex_trylock(&mutex);
printf("%lf, %lf, %lf, lf, %lf, %lf, lf, %lf, %lf", \
vectors->accel->x, vectors->accel->y, vectors->accel->z, \
vectors->gyro->x, vectors->gyro->y, vectors->gyro->z, \
vectors->magnet->x, vectors->magnet->y, vectors->magnet->z );
pthread_mutex_unlock(&mutex);
fflush(stdout);
}
pthread_exit(NULL);
}
You seem surprised that code after this infinite loop
while(1)
{
sleep(1);
}
is not executed. Even if the code could reach this line
pthread_mutex_destroy(&mutex);
you would have problems because the threads are still using the mutex. If you want a graceful shutdown of your code I would add a global boolean that you loop over while true in your threads, then add a SIGINT handler to set this to false so that the threads can exit. Then in main, remove that infinite while loop and make calls to pthread_join on each thread before finally destroying the mutex and finally exiting main().
The pthread_join calls will block until the threads exit so your main() loop is not needed. The threads will exit gracefully on SIGINT and the program should run and terminate in a clean fashion.
One final observation: since vectors is a global variable you don't need to pass it to the thread via the void* argument since it is already visible.
You could have infinite loops, but as you have detected that would mean that the only way to exit the program would be via an interrupt, which would not allow the program to clean up properly.
If you want it to clean up (including joining the threads etc) then you need to provide a way that the loops can exit. One way could be a shared variable which would be set in response to some event and be in the condition for each loop so that once set all of the threads will exit.
You could set a signal handler for SIGINT to catch the ctrl-c and set the shared variable.
You call pthread_join from your main () to wait for the threads to exit. You do not need a loop in main, it will wait until the threads you are joining are done.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#define WORK_SIZE 1024
pthread_mutex_t work_mutex;
char work_area[WORK_SIZE];
void *thread_start(void *);
int main() {
pthread_t a_thread;
pthread_mutex_init(&work_mutex,NULL);
pthread_create(&a_thread,NULL,thread_start,NULL);
while(1)
{
pthread_mutex_lock(&work_mutex);
printf("Enter some text\n");
fgets(work_area, WORK_SIZE, stdin);
pthread_mutex_unlock(&work_mutex);
}
return 0;
}
void *thread_start(void *arg)
{
sleep(1);
while(1)
{
pthread_mutex_lock(&work_mutex);
printf("You enetered %d char",strlen(work_area));
pthread_mutex_unlock(&work_mutex);
}
}
When I execute the program, after releasing of the mutex lock in main thread, it again aquires the lock, everytime, before the second thread could aquire the lock. I was expecting that once the main thread would release the lock, the second thread which is already blocked would aquire the lock and start execution before the main.
To be more clear, I am getting such type of output :-
Enter some text
qwerty
Enter some text
asdaf
Enter some text
jkdf
Enter some text
It just seems that way to you. You lock before doing data entry in main which is going to be orders of magnitude greater than what it take to output the line. In all that time the other thread will do nothing but block. Your main is going to release the lock and microseconds later acquire it again.
If you do this long enough - maybe thousands of times - you will see it work. But it would be better to just copy the input line in main to a queue or some other piece of memory protect by the lock. Then the other thread would have a chance to get at it.
EDIT:
The general idea is this. My code additions are terrible but should work well enough for illustration.
int main()
{
pthread_t a_thread;
pthread_mutex_init(&work_mutex, NULL);
pthread_create(&a_thread, NULL, thread_start, NULL);
memset(work_area, '\0', sizeof(work_area));
char input[WORK_SIZE - 1];
while (1)
{
printf("Enter some text\n");
fgets(input, WORK_SIZE, stdin);
pthread_mutex_lock(&work_mutex);
strcpy(work_area, input);
pthread_mutex_unlock(&work_mutex);
}
return 0;
}
void *thread_start(void *arg)
{
sleep(1);
while (1)
{
pthread_mutex_lock(&work_mutex);
if (work_area[0] != '\0')
{
printf("You enetered %d char\n", strlen(work_area));
work_area[0] = '\0';
}
pthread_mutex_unlock(&work_mutex);
}
}
Putting asside the suggestion to use a semaphore, I think that the reason for the behaviour that you are observing is as follows.
Until the pthread_mutex_lock in thread_start is called, the loop in main won't be blocked.
Therefore, the only time that thread_start's loop will get a chance to call pthread_mutex_lock is when the time slice of the thread executing main expires
The chances of that time slice expiry occuring while the lock is released is miniscule. This is because the main thread will probably have a fresh time slice when it wakes from the blocked state while it waited for the ENTER key.
Note, this explanation assumes a single core. But even on a multicore system the thread_start thread is only going to be scheduled when another thread's time slice runs out. The chances of that happening while main's thread isn't holding the lock is small.
One possible test for my above hypothesis would be to call pthread_yield after releasing the lock. You'll probably want to do that in both threads. Even then I don't think it will GUARANTEE a thread switch every time.
You may want to create and initialise a semaphore and then wait in the 2nd thread for the main function to signal a event when a input is fed to it.
Check conditional wait and semaphores.
The second thread doesnt know what event is generated in the main thread. For your reference.
After reading the comments given by torak, I changed the code. Now it is working fine as expected.
[root#localhost threads]# diff -Nurp mutex.c mutex_modified.c
--- mutex.c 2010-07-09 19:50:51.000000000 +0530
+++ mutex_modified.c 2010-07-09 19:50:35.000000000 +0530
## -18,6 +18,7 ## pthread_mutex_lock(&work_mutex);
printf("Enter some text\n");
fgets(work_area, WORK_SIZE, stdin);
pthread_mutex_unlock(&work_mutex);
+sleep(1);
}
return 0;
}
## -30,5 +31,6 ## while(1)
pthread_mutex_lock(&work_mutex);
printf("You enetered %d char",strlen(work_area));
pthread_mutex_unlock(&work_mutex);
+sleep(1);
}
}
It is still very confusing though. Although it was a test program, what should one do to avoid such kind of situation while coding a real application?
Here's a slightly more awkward solution that's guaranteed to work: #include
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#define WORK_SIZE 1024
pthread_mutex_t work_mutex;
char input_area[WORK_SIZE];
char work_area[WORK_SIZE];
void *thread_start(void *);
int main()
{
pthread_t a_thread;
pthread_mutex_init(&work_mutex,NULL);
work_area[0] = 0;
pthread_create(&a_thread,NULL,thread_start,NULL);
while(1) {
printf("Enter some text\n");
fgets(input_area, WORK_SIZE, stdin);
pthread_mutex_lock(&work_mutex);
while (work_area[0] != 0) {
pthread_mutex_unlock(&work_mutex);
sleep(1);
pthread_mutex_lock(&work_mutex);
}
memcpy(work_area, input_area, WORK_SIZE);
pthread_mutex_unlock(&work_mutex);
}
return 0;
}
void *thread_start(void *arg)
{
while(1)
{
pthread_mutex_lock(&work_mutex);
if (work_area[0] > 0) {
printf("you enetered %d char\n",strlen(work_area));
work_area[0] = 0;
pthread_mutex_unlock(&work_mutex);
} else {
pthread_mutex_unlock(&work_mutex);
sleep(1);
}
}
}
Note that because POSIX mutex locks are thread-specific, the consumer thread can't wait on a signal from the producer thread, so here it just wakes up every second to check for new data. Similarly, if the producer needs to put something in queue and the work area is full, it waits by seconds until the consumer gets around to emptying the buffer. You could get rid of some delays by using pthread_yield instead of sleep, but then your threads will 'busy-wait', consuming lots of CPU to check again and again for their condition to be met
Note that if you want it to print a line for 0-character entries you could add a separate bool indicating whether there's new data in the queue.
#torax
*"Note, this explanation assumes a single core. But even on a multicore system the thread_start thread is only going to be scheduled when another thread's time slice runs out"*
I think this is not true, the main thread and the thread_start can be scheduled parallely on both cores
I'm working on an application for Linux in C which uses multiple threads. The threads which are spawned by the main function do most of the work, and therefore usually finish last. I'm seeing some strange behavior, and I believe it's due to the main thread terminating before the spawned threads have a chance to finish their jobs. Here's some sample code to illustrate what I'm talking about:
#define _POSIX_C_SOURCE 200112L
#define _ISOC99_SOURCE
#define __EXTENSIONS__
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
void
my_cleanup(void *arg)
{
printf("cleanup: %s\n", (char *)arg);
}
void *
thread_stuff(void *arg)
{
printf("thread started\n");
pthread_cleanup_push(cleanup, "running");
if (arg)
pthread_exit((void *)2);
pthread_cleanup_pop(0);
pthread_exit((void *)2);
}
int
main()
{
int err;
pthread_t tid1, tid2;
err = pthread_create(&tid1, NULL, thread_stuff, (void *)1);
err = pthread_create(&tid2, NULL, thread_stuff, (void *)1);
sleep(10); /* change the value here if you want */
return SUCCESS;
}
When this code is run, the message from the cleanup function is printed twice, as it should be, but other times when it is run, I see the message printed only once sometimes, and other times I see it printed three times or not at all. You add in the sleep function in the main function to play with how long it takes the main function to terminate.
What can I do to make the program run as it should? I suspect it has something to do with joining to the children, but I don't entirely understand the concept of a join or how to apply it to this situation.
Thanks in advance!
Yes, you should "join" the threads. "Joining" a thread simply means waiting until the thread has terminated. In other words, you would do
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
to wait until both threads have terminated.
Edit: What to do if you have a child thread which, in turn, creates a "grandchild" thread? As a rule, whoever created the thread should wait for it to terminate ("join" it). So in this scenario, the child thread would call phtread_join on the grandchild thread, and the main thread would call join on the child thread.
I think you want to run pthread_join on each of the threads when your main thread completes -- this makes the main thread stop until the given thread finishes running. Other threads can still complete first though, so running pthread_join on every thread will prevent the main thread from terminiating until all of the others have terminated.
There is a definite problem if main() finishes before the threads it spawned if you don't call pthread_exit() explicitly. All of the threads it created will terminate because main() is done and no longer exists to support the threads.
By having main() explicitly call pthread_exit() as the last thing it does, main() will block and be kept alive to support the threads it created until they are done.
int main()
{
int err;
pthread_t tid1, tid2;
err = pthread_create(&tid1, NULL, thread_stuff, (void *)1);
err = pthread_create(&tid2, NULL, thread_stuff, (void *)1);
sleep(10); /* change the value here if you want */
/* Add the pthread_exit */
pthread_exit(NULL);
return SUCCESS;
}
Refer for more info here