Integrating pthread_create() and pthread_join() in the same loop - c++

I am new to multi-threaded programming and I am following this tutorial. In the tutorial, there is a simple example showing how to use pthread_create() and pthread_join(). My question: why can we not put pthread_join() in the same loop as pthread_create()?
Code for reference:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 2
/* create thread argument struct for thr_func() */
typedef struct _thread_data_t {
int tid;
double stuff;
} thread_data_t;
/* thread function */
void *thr_func(void *arg) {
thread_data_t *data = (thread_data_t *)arg;
printf("hello from thr_func, thread id: %d\n", data->tid);
pthread_exit(NULL);
}
int main(int argc, char **argv) {
pthread_t thr[NUM_THREADS];
int i, rc;
/* create a thread_data_t argument array */
thread_data_t thr_data[NUM_THREADS];
/* create threads */
for (i = 0; i < NUM_THREADS; ++i) {
thr_data[i].tid = i;
if ((rc = pthread_create(&thr[i], NULL, thr_func, &thr_data[i]))) {
fprintf(stderr, "error: pthread_create, rc: %d\n", rc);
return EXIT_FAILURE;
}
}
/* block until all threads complete */
for (i = 0; i < NUM_THREADS; ++i) {
pthread_join(thr[i], NULL);
}
return EXIT_SUCCESS;
}

I figured it out. For other users with same question, I am writing below the answer.
If we put the pthread_join() in the same loop with pthread_create(), the calling thread i.e. main() will wait for the thread 0 to finish its work before creating the thread 1. This would force the threads to execute sequentially, not in parallel. Thus it would kill the purpose of multi-threading.

Related

Pthreads pool, keeping 1000 opened threads, pthread_create() returns 11

Need some help with PTHREADS. I want to keep over 1000 threads opened at any time, something like a thread pool. Here is the code :
/*
gcc -o test2 test2.cpp -static -lpthread -lstdc++
*/
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstring>
#include <stdexcept>
#include <cstdlib>
int NUM_THREADS = 2000;
int MAX_THREADS = 100;
int THREADSTACK = 65536;
struct thread_struct{
int arg1;
int arg2;
};
pthread_mutex_t mutex_;
static unsigned int thread_count = 0;
string exec(const char* cmd)
{
int DEBUG=0;
char buffer[5000];
string result = "";
FILE* pipe = popen(cmd, "r");
if (!pipe && DEBUG) throw runtime_error("popen() failed!");
try
{
while (!feof(pipe))
{
if (fgets(buffer, 128, pipe) != NULL)
{
result += buffer;
}
}
}
catch(...)
{
pclose(pipe);
throw;
}
pclose(pipe);
return result;
}
void *thread_test(void *arguments)
{
pthread_mutex_lock(&mutex_);
thread_count++;
pthread_mutex_unlock(&mutex_);
// long tid;
// tid = (long)threadid;
struct thread_struct *args = (thread_struct*)arguments;
/*
printf("ARG1=%d\n",args->arg1);
printf("ARG2=%d\n",args->arg2);
*/
int thread_id = (int) args->arg1;
/*
int random_sleep;
random_sleep = rand() % 10 + 1;
printf ("RAND=[%d]\n", random_sleep);
sleep(random_sleep);
*/
int random_sleep;
random_sleep = rand() % 10 + 5;
// printf ("RAND=[%d]\n", random_sleep);
char command[100];
memset(command,0,sizeof(command));
sprintf(command,"sleep %d",random_sleep);
exec(command);
random_sleep = rand() % 100000 + 500000;
usleep(random_sleep);
// simulation of a work between 5 and 10 seconds
// sleep(random_sleep);
// printf("#%d -> sleep=%d total_threads=%u\n",thread_id,random_sleep,thread_count);
pthread_mutex_lock(&mutex_);
thread_count--;
pthread_mutex_unlock(&mutex_);
pthread_exit(NULL);
}
int main()
{
// pthread_t threads[NUM_THREADS];
int rc;
int i;
usleep(10000);
srand ((unsigned)time(NULL));
unsigned int thread_count_now = 0;
pthread_attr_t attrs;
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, THREADSTACK);
pthread_mutex_init(&mutex_, NULL);
for( i=0; i < NUM_THREADS; i++ )
{
create_thread:
pthread_mutex_lock(&mutex_);
thread_count_now = thread_count;
pthread_mutex_unlock(&mutex_);
// printf("thread_count in for = [%d]\n",thread_count_now);
if(thread_count_now < MAX_THREADS)
{
printf("CREATE thread [%d]\n",i);
struct thread_struct struct1;
struct1.arg1 = i;
struct1.arg2 = 999;
pthread_t temp_thread;
rc = pthread_create(&temp_thread, NULL, &thread_test, (void *)&struct1);
if (rc)
{
printf("Unable to create thread %d\n",rc);
sleep(1);
pthread_detach(temp_thread);
goto create_thread;
}
}
else
{
printf("Thread POOL full %d of %d\n",thread_count_now,MAX_THREADS);
sleep(1);
goto create_thread;
}
}
pthread_attr_destroy(&attrs);
pthread_mutex_destroy(&mutex_);
// pthread_attr_destroy(&attrs);
printf("Proccess completed!\n");
pthread_exit(NULL);
return 1;
}
After spawning 300 threads it begins to give
errors, return code from pthread_create() is 11, and after that keeps executing them one by one.
What im i doing wrong?
According to this website, error code 11 corresponds to EAGAIN which means according to this:
Insufficient resources to create another thread.
A system-imposed limit on the number of threads was encountered.
Hence to solve your problem either create less threads or wait for running ones to finish before creating new ones.
You can also change default thread stack size see pthread_attr_setstacksize

error: cast from ‘void*’ to ‘int’ loses precision [duplicate]

While working with Threads in C, I'm facing the warning
"warning: cast to pointer from integer of different size"
The code is as follows
#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<pthread.h>
void *print(void *id)
{
int a=10;
printf("My thread id is %ld\n",pthread_self());
printf("Thread %d is executing\n",id);
return (void *) 42;
}
int main()
{
pthread_t th[5];
int t;
int i;
int status;
void *ret;
for(i=0;i<5;i++)
{
status=pthread_create(&th[i],NULL,print,(void *)i); //Getting warning at this line
if(status)
{
printf("Error creating threads\n");
exit(0);
}
pthread_join(th[i],&ret);
printf("--->%d\n",(int *)ret);
}
pthread_exit(NULL);
}
Can anybody explain how to pass an integer to a function which receives (void * ) as a parameter?
This is a fine way to pass integers to new pthreads, if that is what you need. You just need to suppress the warning, and this will do it:
#include <stdint.h>
void *threadfunc(void *param)
{
int id = (intptr_t) param;
...
}
int i, r;
r = pthread_create(&thread, NULL, threadfunc, (void *) (intptr_t) i);
Discussion
This may offend your sensibilities, but it's very short and has no race conditions (as you'd have if you used &i). No sense in writing a few dozen lines of extra code just to get a bunch of numbered threads.
Data races
Here is a bad version with a data race:
#include <pthread.h>
#include <stdio.h>
#define N 10
void *thread_func(void *arg)
{
int *ptr = arg;
// Has *ptr changed by the time we get here? Maybe!
printf("Arg = %d\n", *ptr);
return NULL;
}
int main()
{
int i;
pthread_t threads[N];
for (i = 0; i < N; i++) {
// NO NO NO NO this is bad!
pthread_create(&threads[i], NULL, thread_func, &i);
}
for (i = 0; i < N; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}
Now, what happens when I run it with the thread sanitizer?
(Also, check out how it prints "5" twice...)
==================
WARNING: ThreadSanitizer: data race (pid=20494)
Read of size 4 at 0x7ffc95a834ec by thread T1:
#0 thread_func /home/depp/test.c:9 (a.out+0x000000000a8c)
#1 <null> <null> (libtsan.so.0+0x000000023519)
Previous write of size 4 at 0x7ffc95a834ec by main thread:
#0 main /home/depp/test.c:17 (a.out+0x000000000b3a)
Location is stack of main thread.
Thread T1 (tid=20496, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x0000000273d4)
#1 main /home/depp/test.c:18 (a.out+0x000000000b1c)
SUMMARY: ThreadSanitizer: data race /home/depp/test.c:9 thread_func
==================
Arg = 1
Arg = 2
Arg = 3
Arg = 4
Arg = 5
Arg = 6
Arg = 7
Arg = 8
Arg = 9
Arg = 5
ThreadSanitizer: reported 1 warnings
you can do something like this:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>
struct th {
pthread_t thread;
int id;
int ret;
};
void *print(void *id) {
int a=10;
struct th *self = (struct th *) id;
printf("My thread id is %ld\n",pthread_self());
printf("Thread %d is executing\n",self->id);
self->ret = random();
return;
}
int main(void) {
struct th th[5];
int t;
int i;
int status;
void *ret;
for(i=0;i<5;i++) {
th[i].id = i;
status=pthread_create(&th[i].thread,NULL,print,&th[i]); //Getting warning at this line
if(status) {
printf("Error creating threads\n");
exit(0);
}
}
for (i=0;i<5;i++) {
pthread_join(th[i].thread,&ret);
printf("%d--->%d\n",th[i].id,th[i].ret);
}
pthread_exit(NULL);
}
will output:
My thread id is 4496162816
My thread id is 4497870848
My thread id is 4498944000
My thread id is 4498407424
Thread 0 is executing
Thread 1 is executing
My thread id is 4499480576
Thread 3 is executing
Thread 2 is executing
0--->1804289383
Thread 4 is executing
1--->846930886
2--->1714636915
3--->1681692777
4--->1957747793
passing a unique pointer to each thread wont race, and you can get/save any kind of information in the th struct
you can pass the int value as void pointer like (void *)&n where n is integer, and in the function accept void pointer as parameter like void foo(void *n);and finally inside the function convert void pointer to int like, int num = *(int *)n;. this way you won't get any warning.
change:
status=pthread_create(&th[i],NULL,print,(void *)i);
to:
status=pthread_create(&th[i],NULL,print,(reinterpret_cast<void*>(i));
The reinterpret_cast makes the int the size of a pointer and the warning will stop. Basically its a better version of (void *)i.

Call join child pthread in main function

I have the test code:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_t th_worker, th_worker2;
void * worker2(void *data) {
for(int i = 0; i< 1000000; i++){
printf("thread for worker2----%d\n", i);
usleep(500);
}
}
void * worker(void *data){
pthread_create(&th_worker2, NULL, worker2, data);
for(int i = 0; i< 100; i++){
printf("thread for worker-----%d\n", i);
usleep(500);
}
}
void join(pthread_t _th){
pthread_join(_th, NULL);
}
In main() function, If I call join(the_worker2):
int main() {
char* str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void*) str);
/* problem in here */
join(th_worker2);
return 1;
}
--> Segment Fault error
Else, i call:
join(the_worker);
join(th_worker2);
---> OK
Why have segment fault error in above case?
Thanks for help !!!
If you posted all your code, you have a race condition.
main is synchronized with the start of worker but not worker2.
That is, main is trying to join th_worker2 before worker has had a chance to invoke pthread_create and set up th_worker2 with a valid [non-null] value.
So, th_worker2 will be invalid until the second pthread_create completes, but that's already too late for main. It has already fetched th_worker2, which has a NULL value and main will segfault.
When you add the join for th_worker, it works because it guarantees synchronization and no race condition.
To achieve this guarantee without the join, have main do:
int
main()
{
char *str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void *) str);
// give worker enough time to properly start worker2
while (! th_worker2)
usleep(100);
/* problem in here */
join(th_worker2);
return 1;
}
An even better way to do this is to add an extra variable. With this, the first loop is not needed [but I've left it in]:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int worker_running;
pthread_t th_worker;
int worker2_running;
pthread_t th_worker2;
void *
worker2(void *data)
{
// tell main we're fully functional
worker2_running = 1;
for (int i = 0; i < 1000000; i++) {
printf("thread for worker2----%d\n", i);
usleep(500);
}
return NULL;
}
void *
worker(void *data)
{
// tell main we're fully functional
worker_running = 1;
pthread_create(&th_worker2, NULL, worker2, data);
for (int i = 0; i < 100; i++) {
printf("thread for worker-----%d\n", i);
usleep(500);
}
return NULL;
}
void
join(pthread_t _th)
{
pthread_join(_th, NULL);
}
int
main()
{
char *str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void *) str);
// give worker enough time to properly start worker2
// NOTE: this not necessarily needed as loop below is better
while (! th_worker2)
usleep(100);
// give worker2 enough time to completely start
while (! worker2_running)
usleep(100);
/* problem in here (not anymore!) */
join(th_worker2);
return 1;
}

pthread_create() fails (invalid argument) every 60 threads on Xeon Phi

I have a piece of pthread code listed as the function "thread" here. It basically creates a number of threads (usually 240 on Xeon Phi and 16 on CPU) and then join them.
If I call this thread() only once, it works perfectly on both CPU and Xeon Phi. If I call it one more time, it still works fine on CPU but the pthread_create() will report "error 22" which should be "invalid argument" every 60 threads.
For example, thread 0, thread 60, thread 120 and so on of the 2nd run of thread() which are also the 241, 301, 361 and so on threads ever created in the process would fail (error 22). But thread 1~59, 61~119, 121~240, and so on work perfectly.
Note that this problem happens only on Xeon Phi.
I have checked the stack sizes, and the argument themselves, but I didn't find the reason for this. The arguments are correct.
void thread()
{
...
int i, rv;
cpu_set_t set;
arg_t args[nthreads];
pthread_t tid[nthreads];
pthread_attr_t attr;
pthread_barrier_t barrier;
rv = pthread_barrier_init(&barrier, NULL, nthreads);
if(rv != 0)
{
printf("Couldn't create the barrier\n");
exit(EXIT_FAILURE);
}
pthread_attr_init(&attr);
for(i = 0; i < nthreads; i++)
{
int cpu_idx = get_cpu_id(i,nthreads);
DEBUGMSG(1, "Assigning thread-%d to CPU-%d\n", i, cpu_idx);
CPU_ZERO(&set);
CPU_SET(cpu_idx, &set);
pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &set);
args[i].tid = i;
args[i].ht = ht;
args[i].barrier = &barrier;
/* assing part of the relR for next thread */
args[i].relR.num_tuples = (i == (nthreads-1)) ? numR : numRthr;
args[i].relR.tuples = relR->tuples + numRthr * i;
numR -= numRthr;
/* assing part of the relS for next thread */
args[i].relS.num_tuples = (i == (nthreads-1)) ? numS : numSthr;
args[i].relS.tuples = relS->tuples + numSthr * i;
numS -= numSthr;
rv = pthread_create(&tid[i], &attr, npo_thread, (void*)&args[i]);
if (rv)
{
printf("ERROR; return code from pthread_create() is %d\n", rv);
printf ("%d %s\n", args[i].tid, strerror(rv));
//exit(-1);
}
}
for(i = 0; i < nthreads; i++)
{
pthread_join(tid[i], NULL);
/* sum up results */
result += args[i].num_results;
}
}
Here's a minimal example to reproduce your problem and show where your code most likely goes wrong:
#define _GNU_SOURCE
#include <pthread.h>
#include <err.h>
#include <stdio.h>
void *
foo(void *v)
{
printf("foo\n");
return NULL;
}
int
main(int argc, char **argv)
{
pthread_attr_t attr;
pthread_t thr;
cpu_set_t set;
void *v;
int e;
if (pthread_attr_init(&attr))
err(1, "pthread_attr_init");
CPU_ZERO(&set);
CPU_SET(255, &set);
if (pthread_attr_setaffinity_np(&attr, sizeof(set), &set))
err(1, "pthread_attr_setaffinity_np");
if ((e = pthread_create(&thr, &attr, foo, NULL)))
errx(1, "pthread_create: %d", e);
if (pthread_join(thr, &v))
err(1, "pthread_join");
return 0;
}
As I speculated in the comments to your question, pthread_attr_setaffinity_np doesn't check if the cpu set is sane. Instead that error gets caught in pthread_create. Since the cpu_get_id functions in your code on github are obviously broken, that's where I'd start looking for the problem.
Tested on Linux, but that's where pthread_attr_setaffinity_np comes from, so it's probably a safe assumption.

Make thread loop for 5 iterations; pthreads, mutex, and semaphors

I have this code in an example for my class, and the instructions from the teacher say to "make each thread loop for 5 iterations". I am confused as to how to do that, wtih this code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <sys/utsname.h>
/* Symbolic Constants*/
#define NUM_THREADS 4
#define BUFFER_SIZE 10
/* Semaphore and Mutex lock */
sem_t cEmpty;
sem_t cFull;
pthread_mutex_t mutex;
/* Threads */
pthread_t tid; /* Thread ID */
pthread_attr_t attr; /* Thread attributes */
//prototypes
void *producer(void *param);
void *consumer(void *param);
int insert_item(int threadID);
int remove_item(int threadID);
void init();
/* Progress Counter and Thread IDs*/
int counter, pthreadID=0, cthreadID=0;
int main()
{
/* Variables */
int c1;
/* Perform initialization */
init();
/* Create the producer threads */
for(c1=0; c1<NUM_THREADS; c1++)
{
pthread_create(&tid, &attr, producer, NULL);
}
/* Create the consumer threads */
for(c1=0; c1<NUM_THREADS; c1++)
{
pthread_create(&tid, &attr, consumer, NULL);
}
/* Ending it */
sleep(2);
printf("All threads are done.\n");
/* Destroy the mutex and semaphors */
pthread_mutex_destroy(&mutex);
sem_destroy(&cEmpty);
sem_destroy(&cFull);
printf("Resources cleaned up.\n");
exit(0);
}
void init()
{
pthread_mutex_init(&mutex, NULL); /* Initialize mutex lock */
pthread_attr_init(&attr); /* Initialize pthread attributes to default */
sem_init(&cFull, 0, 0); /* Initialize full semaphore */
sem_init(&cEmpty, 0, BUFFER_SIZE); /* Initialize empty semaphore */
counter = 0; /* Initialize global counter */
}
void *producer(void *param)
{
int x;
for(x=0; x<5;)
{
sleep(1);
sem_wait(&cEmpty); /* Lock empty semaphore if not zero */
pthread_mutex_lock(&mutex);
if(insert_item(pthreadID))
{
fprintf(stderr, "Producer error.");
}
else
{
pthreadID++;
x++;
}
pthread_mutex_unlock(&mutex);
sem_post(&cFull); /* Increment semaphore for # of full */
}
return 0;
}
void *consumer(void *param)
{
int y;
for(y=0; y<5;)
{
sleep(1);
sem_wait(&cFull); /* Lock empty semaphore if not zero */
pthread_mutex_lock(&mutex);
if(remove_item(cthreadID))
{
fprintf(stderr, "Consumer error.");
}
else
{
cthreadID++;
y++;
}
pthread_mutex_unlock(&mutex);
sem_post(&cEmpty); /* Increments semaphore for # of empty */
}
return 0;
}
int insert_item(int threadID)
{
if(counter < BUFFER_SIZE) /* Buffer has space */
{
counter++;
printf("Producer %d inserted a cookie. Total:%d\n", threadID, counter);
return 0;
}
else /* Buffer full */
{
return -1;
}
}
int remove_item(int threadID)
{
if(counter > 0) /* Buffer has something in it */
{
counter--;
printf("Consumer %d removed a cookie. Total:%d\n", threadID, counter);
return 0;
}
else /* Buffer empty */
{
return -1;
}
}
Anyone have any idea of where I add my for loop to "make each thread loop for 5 iterations"? Thank you so much in advanced.
UPDATE: I changed the while(1) to a for loop with 5 iterations, but I still cant get the messages from the insert_item and remove_item functions to print 5 times, the only print once. Anyone know how I can get it to print 5 times?
The problem was that at the end of main, I call sleep(2). This is not enough time for all of the threads to print their output. I was also not passing the right index to my add_item and remove_item functions. In addition, I needed a join command for all of the threads rather than the sleep command, and the join command ensures that all of the threads finish before the program exits. Here is the updated and corrected code. Hope this helps someone trying to do something similar!
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <sys/utsname.h>
// Symbolic Constants
#define NUM_THREADS 4
#define BUFFER_SIZE 10
// Semaphore and Mutex lock
sem_t cEmpty;
sem_t cFull;
pthread_mutex_t mutex;
// Threads
pthread_t tid[NUM_THREADS]; //Thread ID
pthread_t tid2[NUM_THREADS]; //Thread ID
pthread_attr_t attr; //Thread attributes
//prototypes
void *producer(void *param);
void *consumer(void *param);
int insert_item(long threadID);
int remove_item(long threadID);
void init();
//Progress Counter and Thread IDs
int counter=0;
int main()
{
//Variables
long c1;
//Perform initialization
init();
//Create the producer threads
for(c1=0; c1<NUM_THREADS; c1++)
{
pthread_create(&tid[c1], &attr, producer, (void *)c1);
pthread_create(&tid2[c1], &attr, consumer, (void *)c1);
}
//Ending it
for(c1=0; c1<NUM_THREADS; c1++)
{
pthread_join(tid[c1], NULL);
pthread_join(tid2[c1],NULL);
}
printf("All threads are done.\n");
//Destroy the mutex and semaphors
pthread_mutex_destroy(&mutex);
sem_destroy(&cEmpty);
sem_destroy(&cFull);
printf("Resources cleaned up.\n");
exit(0);
}
//This function performs initialization
void init()
{
pthread_mutex_init(&mutex, NULL); //Initialize mutex lock
pthread_attr_init(&attr); //Initialize pthread attributes to default
sem_init(&cFull, 0, 0); //Initialize full semaphore
sem_init(&cEmpty, 0, BUFFER_SIZE); //Initialize empty semaphore
counter = 0; //Initialize global counter
}
//This function creates the producer thread
void *producer(void *param)
{
long index = (long)param;
for(int x = 0; x<5; x++)
{
sleep(1);
sem_wait(&cEmpty); //Lock empty semaphore if not zero
pthread_mutex_lock(&mutex);
//check to see if item inserted correctly; print error on fail
if(insert_item(index))
{
fprintf(stderr, "Producer error.");
}
pthread_mutex_unlock(&mutex);
sem_post(&cFull); //Increment semaphore for # of full
}
pthread_exit(NULL);
return 0;
}
//This function created the consumer thread
void *consumer(void *param)
{
long index = (long)param;
for(int x = 0; x<5; x++)
{
sleep(1);
sem_wait(&cFull); //Lock empty semaphore if not zero
pthread_mutex_lock(&mutex);
//print error if cookie not decremented correctly
if(remove_item(index))
{
fprintf(stderr, "Consumer error.");
}
pthread_mutex_unlock(&mutex);
sem_post(&cEmpty); //Increments semaphore for # of empty
}
pthread_exit(NULL);
return 0;
}
//Insert item function to increment the cookie count and print thread message
int insert_item(long threadID)
{
if(counter < BUFFER_SIZE) //Buffer has space
{
counter++;
printf("Producer %ld inserted a cookie. Total:%d\n", threadID, counter);
return 0;
}
else //Buffer full
{
return -1;
}
}
//Remove item function to decrement the cookie count and print thread message
int remove_item(long threadID)
{
if(counter > 0) //Buffer has something in it
{
counter--;
printf("Consumer %ld removed a cookie. Total:%d\n", threadID, counter);
return 0;
}
else //Buffer empty
{
return -1;
}
}