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.
Related
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
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.
I'm trying to implement a class that creates a thread, increments a value and sends it to another thread, which number is defined as (value * value) % number of threads
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstdlib>
#include <vector>
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
volatile int counter = 0;
volatile int maxval = 0;
volatile int next = 0;
extern "C" void *func(void *p);
class Worker {
private:
pthread_t thread = 0;
int nth = 0;
int nproc = 0;
public:
Worker () {};
Worker(int _nproc, int _nth) {
nth = _nth;
nproc = _nproc;
};
void start() {
pthread_create(&thread, NULL, func, NULL); // Line 27
};
void wait() {
while (nth != next) {
pthread_cond_wait(&cv, &m);
}
};
void notify() {
pthread_cond_broadcast(&cv);
};
void run() {
while (counter != maxval) {
pthread_mutex_lock(&m);
Worker::wait();
if (counter != maxval) {
printf("%d %d\n", nth, counter);
++counter;
}
next = (counter * counter) % nproc;
Worker::notify();
pthread_mutex_unlock(&m);
}
};
void join() {
pthread_join(thread, NULL);
}
};
extern "C" void *func(void *p) {
Worker *w = reinterpret_cast<Worker*>(p);
w->run();
return NULL;
}
int main(int argc, char *argv[]) {
int nthreads = atoi(argv[1]);
maxval = atoi(argv[2]);
std::vector<Worker> workers;
for (int i = 0; i != nthreads; ++i) {
workers.push_back(Worker(nthreads, i));
}
for (int i = 0; i != workers.size(); ++i) {
workers[i].start();
}
for (int i = 0; i != workers.size(); ++i) {
workers[i].join();
}
return 0;
}
Can't check if the algorithm is correct since I get a Segmentation Error when I call pthread_create (line 27)
This is what gdb said:
#0 0x0000000000400f5a in Worker::wait (this=0x0) at ht19-4.cpp:30
#1 0x0000000000400fd5 in Worker::run (this=0x0) at ht19-4.cpp:40
#2 0x0000000000400d26 in func (p=0x0) at ht19-4.cpp:57
#3 0x00007ffff76296aa in start_thread (arg=0x7ffff6f4f700)
at pthread_create.c:333
#4 0x00007ffff735eeed in clone ()
at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
Could anyone explain what exactly happens in this function please? How do I implement this correctly?
Thanks a lot.
You're func doesn't handle NULL being passed in and the 4th argument of pthread_create is what gets sent the function in the third argument.
Change func to properly handle NULL and you should be good:
extern "C" void *func(void *p) {
if (NULL == p)
return NULL;
Worker *w = reinterpret_cast<Worker*>(p);
w->run();
return NULL;
}
Also, +1 for posting gdb output so here's some more information:
If we follow your stack trace upwards (I'm typing them in the order they happen) we see that func does its job of casting and calling run on the Worker it casted from NULL. Notice the (p=0x0) and (this=0x0):
#2 0x0000000000400d26 in func (p=0x0) at ht19-4.cpp:57
#1 0x0000000000400fd5 in Worker::run (this=0x0) at ht19-4.cpp:40
Worker::run works fine because it only accesses counter, maxval, and m before getting to Worker::wait()
#0 0x0000000000400f5a in Worker::wait (this=0x0) at ht19-4.cpp:30
In Worker::wait() you are accessing nth which is a member of the null Worker instance and you finally get your segfault.
The problem is while creating thread you are passing NULL for last argument.
pthread_create(&thread, NULL, func, NULL);
While the thread is started it calls func() with NULL value passed to it.
So inside func() p is NULL and you are trying to cast and then access that memory location. That's why you're getting segmentation fault.
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;
}
Whenever I try to compile the following program, I get this message from the compiler (g++ 4.4.3). Any idea, why?
main.cpp: In function ‘int main(int, char**)’:
main.cpp:52: error: void value not ignored as it ought to be
Line 52 has the code rc = pthread_create_with_stack( &thread[t], BusyWork, t );
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define NUM_THREADS 4
void *stackAddr[NUM_THREADS];
pthread_t thread[NUM_THREADS];
pthread_attr_t attr;
void *BusyWork(void *t)
{
int i;
long tid;
double result=0.0;
tid = (long)t;
printf("Thread %ld starting...\n",tid);
for ( i = 0; i < 1000; i++)
{
result = result + sin(i*tid) * tan(i*tid);
}
printf("Thread %ld done. Result = %e\n", tid, result);
pthread_exit((void*) t);
}
void pthread_create_with_stack( pthread_t * pthread, void *(*start_routine) (void *), int tid )
{
const size_t STACKSIZE = 0xC00000; //12582912
int rc;
size_t i;
pid_t pid;
stackAddr[tid] = malloc(STACKSIZE);
pthread_attr_setstack(&attr, stackAddr[tid], STACKSIZE);
rc = pthread_create( pthread, &attr, start_routine, (void*)0 );
}
int main (int argc, char *argv[])
{
int rc;
long t;
void *status;
/* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(t=0; t<NUM_THREADS; t++)
{
printf("Main: creating thread %ld\n", t);
// The following line is the line 52, where error occurs
rc = pthread_create_with_stack( &thread[t], BusyWork, t );
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Free attribute and wait for the other threads */
pthread_attr_destroy(&attr);
for(t=0; t<NUM_THREADS; t++)
{
rc = pthread_join(thread[t], &status);
if (rc)
{
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld having a status"
"of %ld\n",t,(long)status);
}
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
pthread_create_with_stack returns void, yet you're trying to save this void "value" in an int, which is an error.
It's this line
rc = pthread_create_with_stack( &thread[t], BusyWork, t );
Your definition of pthread_create_with_stack is of type void. Should be of type void* and return rc, the result of pthread_create().
Since pthread_create_with_stack is a void function, and it returns nothing in the definition, setting rc to its return value is not only meaningless, it's an error gcc/g++ won't even let you try to compile.
Yes, there is an error. A return type of void means that the function returns no value. You're trying to assign the return value of pthread_create_with_stack to a local variable, but there is no return value to assign.
You should instead declare pthread_create_with-stack as returning an int, and then make it actually return a value:
int pthread_create_with-stack(...)
{
...
return pthread_create(...);
}
You're taking the return value from a void function and trying to assign it to a variable. pthread_create_with_stack doesn't return anything; don't assign it or use it.
Your pthread_create_with_stack is a void function. It doesn't return a value. You can't assign it's result to a variable.
pthread_create_with_stack is defined as returning void.
rc = pthread_create_with_stack( &thread[t], BusyWork, t );
where rc is defined as int is not legal
void simply means "nothing"
N you simply cant save "nothing"!