I'm new to C and multithreading programming, just a question on what happen if the main thread finish but peer threads are not, does the process still wait until all peer threads finish or the process terminates immediately right after the main thread is done?
When the main function returns, or you call exit, then the system will terminate the process and all threads running in that process.
If you have background (detached) threads that you want to keep running, you have to end the "main" thread only, not the process. How to do that is platform-dependent, but on POSIX platforms (e.g. Linux or macOS) then you call pthread_exit instead of exit.
If you don't have any background threads then you need to join all the running threads to keep them from being forcibly terminated.
Here is an example program which illustrates the preceding answer on GLIBC/Linux operating system. The program creates a detached secondary thread and if it is not passed a parameter, the main thread exits otherwise it calls pthread_exit():
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
void *th_entry(void *p)
{
int i;
printf("Secondary thread starting...\n");
for (i = 0; i < 5; i ++) {
printf(".");
fflush(stdout);
sleep(1);
}
printf("\nSecondary thread exiting\n");
return NULL;
}
int main(int ac, char *av[])
{
int rc;
pthread_t tid;
printf("Main thread starting...\n");
rc = pthread_create(&tid, NULL, th_entry, NULL);
if (rc != 0) {
errno = rc;
fprintf(stderr, "pthread_create(): '%m' (%d)\n", errno);
return 1;
}
// Detach the secondary thread
rc = pthread_detach(tid);
if (rc != 0) {
errno = rc;
fprintf(stderr, "pthread_detach(): '%m' (%d)\n", errno);
return 1;
}
// Some dummy work
sleep(1);
if (av[1]) {
printf("Main thread exiting\n");
return 0;
} else {
printf("Main thread calling pthread_exit()\n");
pthread_exit(NULL);
}
return 0;
}
Compile it:
$ gcc td.c -l pthread
When the program is not passed any parameter, the main thread calls pthread_exit() and the process ends when the secondary thread finishes.
$ ./a.out
Main thread starting...
Secondary thread starting...
.Main thread calling pthread_exit()
....
Secondary thread exiting
$
When the program is passed a parameter, the main thread calls exit() (it returns 0 but it is equivalent) and the process ends immediately terminating the secondary thread:
$ ./a.out 1
Main thread starting...
Secondary thread starting...
.Main thread exiting
$
Related
I'm trying to write a program that can prevent halting forever on a blocking syscall. Please note that I'm NOT trying to solve the halting problem. The program should try to call a blocking syscall, and then give up after a given time interval has exceeded.
I've tried to write a program where I spawn a thread that tries to perform the possibly forever blocking syscall. The MAIN thread waits for a specified time interval for the spawned thread to finish. If the time interval is exceeded, the MAIN thread should give up and continue with other pressing matters.
In the code below The MAIN thread spawns a detached thread to do the work. This is in order to avoid having to join with a thread that has possibly halted forever.
Next the MAIN thread waits for a condition ("I'm finished!") signaled by the spawned thread using pthread_cond_timedwait in order to timeout after the specified time interval (given as a program argument) is exceeded.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
struct ThreadData {
pthread_attr_t attr;
pthread_t thread;
pthread_cond_t cond;
pthread_mutex_t mutex;
bool result;
};
static void *ThreadRoutine(void *data) {
struct ThreadData *thread_data = data;
puts("THREAD: Locking mutex");
int ret = pthread_mutex_lock(&thread_data->mutex);
if (ret != 0) {
printf("THREAD: Failed to lock mutex: %s\n", strerror(ret));
return NULL;
}
/* Also tried setting cancel state to async, but it did not help */
// puts("THREAD: Setting cancel state enable");
// ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
// if (ret != 0) {
// printf("Failed to set cancel state enable: %s\n", strerror(ret));
// return NULL;
// }
// puts("THREAD: Setting cancel type async");
// ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
// if (ret != 0) {
// printf("THREAD: Failed to set cancel type async: %s\n", strerror(ret));
// return NULL;
// }
puts("THREAD: Blocking for 3 sec");
sleep(3); /* example blocking syscall */
thread_data->result = true;
puts("THREAD: Signalling main thread");
ret = pthread_cond_signal(&thread_data->cond);
if (ret != 0) {
printf("THREAD: Failed to signal main thread: %s\n", strerror(ret));
return NULL;
}
puts("THREAD: Unlocking mutex");
ret = pthread_mutex_unlock(&thread_data->mutex);
if (ret != 0) {
printf("THREAD: Failed to unlock mutex: %s\n", strerror(ret));
return NULL;
}
puts("THREAD: Returning from thread routine");
return NULL;
}
int main(int argc, char **argv) {
if (argc <= 1) {
puts("Missing argument");
return EXIT_FAILURE;
}
const int timeout = atoi(argv[1]);
struct ThreadData thread_data;
thread_data.result = false;
puts("MAIN: Initializing mutex");
int ret = pthread_mutex_init(&thread_data.mutex, NULL);
if (ret != 0) {
printf("MAIN: Failed to initialize mutex: %s\n", strerror(ret));
return EXIT_FAILURE;
}
puts("MAIN: Initializing condition");
ret = pthread_cond_init(&thread_data.cond, NULL);
if (ret != 0) {
printf("MAIN: Failed to initialize condition: %s\n", strerror(ret));
return EXIT_FAILURE;
}
puts("MAIN: Locking mutex");
ret = pthread_mutex_lock(&thread_data.mutex);
if (ret != 0) {
printf("MAIN: Failed to lock mutex: %s\n", strerror(ret));
return EXIT_FAILURE;
}
puts("MAIN: Initializing thread attributes");
ret = pthread_attr_init(&thread_data.attr);
if (ret != 0) {
printf("Failed to initialize thread attributes\n");
return EXIT_FAILURE;
}
puts("MAIN: Setting thread detach state");
ret = pthread_attr_setdetachstate(&thread_data.attr, PTHREAD_CREATE_DETACHED);
if (ret != 0) {
printf("MAIN: Failed to set thread detach state: %s\n", strerror(ret));
return EXIT_FAILURE;
}
puts("MAIN: Creating thread");
ret = pthread_create(&thread_data.thread, &thread_data.attr, &ThreadRoutine, &thread_data);
if (ret != 0) {
printf("MAIN: Failed to create thread: %s\n", strerror(ret));
return EXIT_FAILURE;
}
puts("MAIN: Destroying thread attributes");
ret = pthread_attr_destroy(&thread_data.attr);
if (ret != 0) {
printf("MAIN: Failed to destroy thread attributes: %s\n", strerror(ret));
return EXIT_FAILURE;
}
puts("MAIN: Calculating timeout interval");
struct timespec ts = {0};
if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
printf("MAIN: Failed to get current time: %s\n", strerror(errno));
return EXIT_FAILURE;
}
ts.tv_sec += timeout;
printf("MAIN: Waiting for thread to finish (timeout: %d sec)\n", timeout);
ret = pthread_cond_timedwait(&thread_data.cond, &thread_data.mutex, &ts);
switch (ret) {
case 0:
printf("MAIN: Thread finished in time; computation evaluated to %s\n", (thread_data.result) ? "true" : "false");
return EXIT_SUCCESS;
case ETIMEDOUT:
puts("MAIN: Thread did not finish in time");
return EXIT_SUCCESS;
default:
printf("MAIN: Failed to wait for thread to finish: %s", strerror(ret));
return EXIT_FAILURE;
}
}
Running this program, it looks like it's blocked on pthread_cond_timedwait for longer than the specified timeout interval.
$ gcc -g -Wall -Wextra -c main.c -o main.o
$ gcc main.o -o prog -pthread
$ time ./prog 1
MAIN: Initializing mutex
MAIN: Initializing condition
MAIN: Locking mutex
MAIN: Initializing thread attributes
MAIN: Setting thread detach state
MAIN: Creating thread
MAIN: Destroying thread attributes
MAIN: Calculating timeout interval
MAIN: Waiting for thread to finish (timeout: 1 sec)
THREAD: Locking mutex
THREAD: Blocking for 3 sec
THREAD: Signalling main thread
THREAD: Unlocking mutex
THREAD: Returning from thread routine
MAIN: Thread did not finish in time
./prog 1 0.00s user 0.00s system 0% cpu 3.007 total
The program correctly outputs that the thread did not finish in time. But according to the time command, it looks like the main thread still was blocked until the spawned thread had finished. While I would expect the man thread to continue once the timeout interval was exceeded.
I can't figure out how to implement this using threads. Another option could be to try to implement this using fork. But I'd rather use threads if that is possible.
Thanks :)
As mentioned by #Shawn pthread_cond_timedwait has to reacquire the mutex. By releasing the mutex in the spawned thread before calling the "possibly forever" blocking syscall, the code works as expected. Thanks :)
$ time ./prog 1
MAIN: Initializing mutex
MAIN: Initializing condition
MAIN: Locking mutex
MAIN: Initializing thread attributes
MAIN: Setting thread detach state
MAIN: Creating thread
MAIN: Destroying thread attributes
MAIN: Calculating timeout interval
MAIN: Waiting for thread to finish (timeout: 1 sec)
THREAD: Locking mutex
THREAD: Unlocking mutex
THREAD: Blocking for 3 sec
MAIN: Thread did not finish in time
./prog 1 0.00s user 0.00s system 0% cpu 1.008 total
Execution time is now approx 1 second, as I expected.
I have a threadpool of workers. Each worker executes this routine:
void* worker(void* args){
...
pthread_mutex_lock(&mtx);
while (queue == NULL && stop == 0){
pthread_cond_wait(&cond, &mtx);
}
el = pop(queue);
pthread_mutex_unlock(&mtx);
...
}
main thread:
int main(){
...
while (stop == 0){
...
pthread_mutex_lock(&mtx);
insert(queue, el);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);
...
}
...
}
Then I have a signal handler that executes this code when it receives a signal:
void exit_handler(){
stop = 1;
pthread_mutex_lock(&mtx);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mtx);
}
I have omitted declarations and initialization, but the original code has them.
After a signal is received most of the time it's all ok, but sometimes it seems that some worker threads stay in the wait loop because they don't see that the variable stop is changed and/or they are not waken up by the broadcast.
So the threads never end.
What I am missing?
EDIT: stop=1 moved inside the critical section in exit_handler. The issue remains.
EDIT2: I was executing the program on a VM with Ubuntu. Since the code appears to be totally right I tried to change VM and OS (XUbuntu) and now it seems to work correctly. Still don't know why, anyone has an idea?
Some guessing here, but it's too long for a comment, so if this is wrong, I will delete. I think you may have a misconception about how pthread_cond_broadcast works (at least something I've been burned with in the past). From the man page:
The pthread_cond_broadcast() function shall unblock all threads
currently blocked on the specified condition variable cond.
Ok, that make sense, _broadcast awakens all threads currently blocked on cond. However, only one of the awakened threads will then be able to lock the mutex after they're all awoken. Also from the man page:
The thread(s) that are unblocked shall contend for the mutex according
to the scheduling policy (if applicable), and as if each had called
pthread_mutex_lock().
So this means that if 3 threads are blocked on cond and _broadcast is called, all 3 threads will wake up, but only 1 can grab the mutex. The other 2 will still be stuck in pthread_cond_wait, waiting on a signal. Because of this, they don't see stop set to 1, and exit_handler (I'm assuming a Ctrl+c software signal?) is done signaling, so the remaining threads that lost the _broadcast competition are stuck in limbo, waiting on a signal that will never come, and unable to read that the stop flag has been set.
I think there are 2 options to work-around/fix this:
Use pthread_cond_timedwait. Even without being signaled, this will return from waiting at the specified time interval, see that stop == 1, and then exit.
Add pthread_cond_signal or pthread_cond_broadcast at the end of your worker function. This way, right before a thread exits, it will signal the cond variable allowing any other waiting threads to grab the mutex and finish processing. There is no harm in signaling a conditional variable if no threads are waiting on it, so this should be fine even for the last thread.
EDIT: Here is an MCVE that proves (as far as I can tell) that my answer above is wrong, heh. As soon as I press Ctrl+c, the program exits "immediately", which says to me all the threads are quickly acquiring the mutex after the broadcast, seeing that stop is false, and exiting. Then main joins on the threads and it's process over.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#define NUM_THREADS 3
#define STACK_SIZE 10
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c = PTHREAD_COND_INITIALIZER;
volatile bool stop = false;
int stack[STACK_SIZE] = { 0 };
int sp = 0; // stack pointer,, also doubles as the current stack size
void SigHandler(int sig)
{
if (sig == SIGINT)
{
stop = true;
}
else
{
printf("Received unexcepted signal %d\n", sig);
}
}
void* worker(void* param)
{
long tid = (long)(param);
while (stop == false)
{
// acquire the lock
pthread_mutex_lock(&m);
while (sp <= 0) // sp should never be < 0
{
// there is no data in the stack to consume, wait to get signaled
// this unlocks the mutex when it is called, and locks the
// mutex before it returns
pthread_cond_wait(&c, &m);
}
// when we get here we should be guaranteed sp >= 1
printf("thread %ld consuming stack[%d] = %d\n", tid, sp-1, stack[sp-1]);
sp--;
pthread_mutex_unlock(&m);
int sleepVal = rand() % 10;
printf("thread %ld sleeping for %d seconds...\n", tid, sleepVal);
sleep(sleepVal);
}
pthread_exit(NULL);
}
int main(void)
{
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
srand(time(NULL));
for (long i=0; i<NUM_THREADS; i++)
{
int rc = pthread_create(&threads[i], &attr, worker, (void*)i);
if (rc != 0)
{
fprintf(stderr, "Failed to create thread %ld\n", i);
}
}
while (stop == false)
{
// produce data in bursts
int numValsToInsert = rand() % (STACK_SIZE - sp);
printf("main producing %d values\n", numValsToInsert);
// acquire the lock
pthread_mutex_lock(&m);
for (int i=0; i<numValsToInsert; i++)
{
// produce values for the stack
int val = rand() % 10000;
// I think this should already be guaranteed..?
if (sp+1 < STACK_SIZE)
{
printf("main pushing stack[%d] = %d\n", sp, val);
stack[sp++] = val;
// signal the workers that data is ready
//printf("main signaling threads...\n");
//pthread_cond_signal(&c);
}
else
{
printf("stack full!\n");
}
}
pthread_mutex_unlock(&m);
// signal the workers that data is ready
printf("main signaling threads...\n");
pthread_cond_broadcast(&c);
int sleepVal = 1;//rand() % 5;
printf("main sleeping for %d seconds...\n", sleepVal);
sleep(sleepVal);
}
for (long i=0; i<NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
In the context of an existing multi-threaded application I want to suspend a list of threads for a specific duration then resume their normal execution. I know some of you wil say that I should not do that but I know that and I don't have a choice.
I came up with the following code that sort of work but randomly failed. For each thread I want to suspend, I send a signal and wait for an ack via a semaphore. The signal handler when invoked, post the semaphore and sleep for the specified duration.
The problem is when the system is fully loaded, the call to sem_timedwait sometimes fails with ETIMEDOUT and I am left with an inconsistent logic with semaphore used for the ack: I don't know if the signal has been dropped or is just late.
// compiled with: gcc main.c -o test -pthread
#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/syscall.h>
#define NUMTHREADS 40
#define SUSPEND_SIG (SIGRTMIN+1)
#define SUSPEND_DURATION 80 // in ms
static sem_t sem;
void checkResults(const char *msg, int rc) {
if (rc == 0) {
//printf("%s success\n", msg);
} else if (rc == ESRCH) {
printf("%s failed with ESRCH\n", msg);
} else if (rc == EINVAL) {
printf("%s failed with EINVAL\n", msg);
} else {
printf("%s failed with unknown error: %d\n", msg, rc);
}
}
static void suspend_handler(int signo) {
sem_post(&sem);
usleep(SUSPEND_DURATION*1000);
}
void installSuspendHandler() {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = suspend_handler;
int rc = sigaction(SUSPEND_SIG, &sa, NULL);
checkResults("sigaction SUSPEND", rc);
}
void *threadfunc(void *param) {
int tid = *((int *) param);
free(param);
printf("Thread %d entered\n", tid);
// this is an example workload, the real app is doing many things
while (1) {
int rc = sleep(30);
if (rc != 0 && errno == EINTR) {
//printf("Thread %d got a signal delivered to it\n", tid);
} else {
//printf("Thread %d did not get expected results! rc=%d, errno=%d\n", tid, rc, errno);
}
}
return NULL;
}
int main(int argc, char **argv) {
pthread_t threads[NUMTHREADS];
int i;
sem_init(&sem, 0, 0);
installSuspendHandler();
for(i=0; i<NUMTHREADS; ++i) {
int *arg = malloc(sizeof(*arg));
if ( arg == NULL ) {
fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
exit(EXIT_FAILURE);
}
*arg = i;
int rc = pthread_create(&threads[i], NULL, threadfunc, arg);
checkResults("pthread_create()", rc);
}
sleep(3);
printf("Will start to send signals...\n");
while (1) {
printf("***********************************************\n");
for(i=0; i<NUMTHREADS; ++i) {
int rc = pthread_kill(threads[i], SUSPEND_SIG);
checkResults("pthread_kill()", rc);
printf("Waiting for Semaphore for thread %d ...\n", i);
// compute timeout abs timestamp for ack
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
const int TIMEOUT = SUSPEND_DURATION*1000*1000; // in nano-seconds
ts.tv_nsec += TIMEOUT; // timeout to receive ack from signal handler
// normalize timespec
ts.tv_sec += ts.tv_nsec / 1000000000;
ts.tv_nsec %= 1000000000;
rc = sem_timedwait(&sem, &ts); // try decrement semaphore
if (rc == -1 && errno == ETIMEDOUT) {
// timeout
// semaphore is out of sync
printf("Did not received signal handler sem_post before timeout of %d ms for thread %d", TIMEOUT/1000000, i);
abort();
}
checkResults("sem_timedwait", rc);
printf("Received Semaphore for thread %d.\n", i);
}
sleep(1);
}
for(i=0; i<NUMTHREADS; ++i) {
int rc = pthread_join(threads[i], NULL);
checkResults("pthread_join()\n", rc);
}
printf("Main completed\n");
return 0;
}
Questions?
Is it possible for a signal to be dropped and never delivered?
What causes the timeout on the semaphore at random time when the system is loaded?
usleep() is not among the async-signal-safe functions (though sleep() is, and there are other async-signal-safe functions by which you can produce a timed delay). A program that calls usleep() from a signal handler is therefore non-conforming. The specifications do not describe what may happen -- neither with such a call itself nor with the larger program execution in which it occurs. Your questions can be answered only for a conforming program; I do that below.
Is it possible for a signal to be dropped and never delivered?
It depends on what exactly you mean:
If a normal (not real-time) signal is delivered to a thread that already has that signal queued then no additional instance is queued.
A thread can die with signals still queued for it; those signals will not be handled.
A thread can change a given signal's disposition (to SIG_IGN, for example), though this is a per-process attribute, not a per-thread one.
A thread can block a signal indefinitely. A blocked signal is not dropped -- it remains queued for the thread and will eventually be received some time after it is unblocked, if that ever happens.
But no, having successfully queued a signal via the kill() or raise() function, that signal will not be randomly dropped.
What causes the timeout on the semaphore at random time when the system is loaded?
A thread can receive a signal only when it is actually running on a core. On a system with more runnable processes than cores, some runnable processes must be suspended, without a timeslice on any core, at any given time. On a heavily-loaded system, that's the norm. Signals are asynchronous, so you can send one to a thread that is currently waiting for a timeslice without the sender blocking. It is entirely possible, then, that the thread you have signaled does not get scheduled to run before the timeout expires. If it does run, it may have the signal blocked for one reason or another, and not get around to unblocking it before it uses up its timeslice.
Ultimately, you can use your semaphore-based approach to check whether the target thread handled the signal within any timeout of your choice, but you cannot predict in advance how long it will take for the thread to handle the signal, nor even whether it will do so in any finite amount of time (for example, it could die for one reason or another before doing so).
Here is a code sample of pthread cancellation:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *my_routine(void *arg) {
int i;
for (i = 0; i < 10; i++) {
printf("%d\n", i);
}
return NULL;
}
int main(void) {
pthread_t thread;
if (pthread_create(&thread, NULL, my_routine, NULL)) {
fprintf(stderr, "Cannot create pthread\n");
return 1;
}
usleep(20);
pthread_cancel(thread);
pthread_join(thread, NULL);
//fflush(stdout);
sleep(1);
return 0;
}
I compile with:
gcc -pthread -Wall threadtest.c -o threadtest
When executing, sometimes, it prints an additional number after sleep(1).
Sometimes this number is a duplicate:
0
1
2
3
4
4 // printed after sleep(1)
Sometimes not:
0
1
2
3
4
5 // printed after sleep(1)
If I fflush(stdout) before sleep(1), then the additional number is printed immediately.
How can I avoid this weird printf behaviour when cancelling a thread?
Thank you.
You could disable cancellation while doing the printf() and add an explicit cancellation point:
int cancel_state = 0;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
printf("%d\n", i);
pthread_setcancelstate(cancel_state);
pthread_testcancel();
(error checking left out for the sake of readability)
When using pthread_cancel you should take more care on thread handler.
man page of pthread_cancel explain lot about this.
man pthread_cancel
Check the example program available in the man page
When thread handler start you have to make PTHREAD_CANCEL_DISABLE with the help of pthread_setcancelstate system call, when handler meet the cancellation point set PTHREAD_CANCEL_ENABLE.
In the main check the pthread_cancel success or not with the help of PTHREAD_CANCELED macro.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *my_routine(void *arg) {
int i;
//pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
for (i = 0; i < 10; i++) {
sleep(1);
printf("%d\n", i);
}
//pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
sleep(60);
return NULL;
}
int main(void)
{
pthread_t thread;
if (pthread_create(&thread, NULL, my_routine, NULL)) {
fprintf(stderr, "Cannot create pthread\n");
return 1;
}
usleep(20);
pthread_cancel(thread);
pthread_join(thread, NULL);
//fflush(stdout);
sleep(1);
return 0;
}
Initially compile and run the above program, note the output. It may not display anything and terminate the program because after thread created thread handler will wait 1sec and sleep, in that time parent thread will cancel the thread and finish process.
Then uncomment the two pthread_setcancelstate() from above program, now compile and run the program. It will now display from 1 to 9. Because thread is set as PTHREAD_CANCEL_DISABLE so parent pthread_cancel will not cancel and wait for PTHREAD_CANCEL_ENABLE.When thread handler meet PTHREAD_CANCEL_ENABLE parent thread will cancel the thread.
when you note the output. handler will not stay on sleep(60), because before that parent will cancel the thread.
For the code below my cpu usage is 97%. I am running c code on Ubuntu.
#include <stdio.h>
#include<pthread.h>
void *s_thread(void *x)
{
printf("I am in first thread\n");
}
void *f_thread(void *x)
{
printf("I am in second thread\n");
}
int main()
{
printf("I am in main\n");
pthread_t fth;
int ret;
ret = pthread_create( &fth,NULL,f_thread,NULL);
ret = pthread_create( &sth,NULL,s_thread,NULL);
while(1);
return 0;
}
This simple code is giving me more cpu usage than running only one thread.
int main()
{
printf("I am in main\n");
pthread_t fth,sth;
int ret;
ret = pthread_create( &fth,NULL,f_thread,NULL);
ret = pthread_create( &sth,NULL,s_thread,NULL);
pthread_join(&fth,NULL);
pthread_join(&sth,NULL);
return 0;
}
while(1) uses more CPU cycles, so use pthread_join and join the process so that main thread waits for child threads to complete.
In linux there are 3 threads :
1 - main thread in which your main() is executing
2 - f_thread
3 - s_thread
The main thread waits on a while(1) loop, which is causing heavy resource usage.
You should not use while(1), instead use pthread_join (http://www.manpagez.com/man/3/pthread_join/) .
With pthread_join, your main thread will sleep until other two threads are finished. Thus there won't be unnecessary resource usage.
Put a sleep command into your loop. For example, the following "sleep" command sleeps for one second:
while(1) {
sleep(1);
}
There are other commands that sleep for less time, such as "usleep" provided by unistd.h, which sleeps for a given number of microseconds:
while(1) {
usleep(1000);
}