I have a problem with my project which is supposed to add up every line using a thread then sum it all, but I'm getting an error that says lvalue required as unary '&" operand
pthread_create(&tid, NULL, &sum_line(0), NULL);
I've tried some thing but couldn't solve it, any ideas? Thanks
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
static void * sum_line(int nr_line);
int Sum;
int A[4][4];
int main() {
pthread_t tid;
Sum=0;
printf("\nOrig thread tid(%d) Sum=%d", pthread_self(), Sum);
pthread_create(&tid, NULL, &sum_line(0), NULL);
printf("\nChild thread was created tid(%d)", tid);
pthread_join(tid,NULL);
printf("\nOrig thread tid(%d)-->Child thread ended tid(%d) Sum=%d",pthread_self(), tid, Sum);
printf("\n");
}
static void * sum_line(int nr_line) {
int i;
for(i=0;i<4;i++) {
Sum=Sum+A[i];
printf("\nChild thread tid(%d), i=%d, Sum=%d",pthread_self(),i,Sum);
sleep(2);
}
printf("\nChild thread tid(%d)--> ending", pthread_self());
}
Pass a pointer to function to pthread_create()
Write just sum_line, not &sum_line(0).
The pthread_create() function expects a pointer to the thread function — i.e. the function name — and not the result of calling the function. The pthread_create() function will arrange for the new thread to call the function, but it needs a function pointer.
Also, the signature for a thread function must be:
void *function(void *arg);
The function should also return a value — add return 0; before the close brace.
You pass a null pointer to the function; you can't expect that to work as int nr_line. You'll need to do some fancy footwork to get a number to the function.
There are two main options:
Either
int nr_line = 247;
pthread_create(&tid, NULL, sum_line, &nr_line);
The function then looks like:
void *sum_line(void *arg)
{
int nr_line = *(int *)arg;
…
return 0;
}
Just make sure each thread gets a pointer to a different object when you start multiple threads.
Or
uintptr_t nr_line = 247;
pthread_create(&tid, NULL, sum_line, (void *)nr_line);
Or:
int nr_line = 247;
pthread_create(&tid, NULL, sum_line, (void *)(uintptr_t)nr_line);
and the function then looks like:
void *sum_line(void *arg)
{
int nr_line = (uintptr_t)arg;
…
return 0;
}
The double cast avoids compiler warnings about converting an integer of a different size to a pointer.
Note that pthread_create() will call the function as if it is void *function(void *args), so passing it any other type of function pointer, even if cast with (void (*)(void *)), is cheating and leads to undefined behaviour.
Related
I have found several codes using dynamic memory allocation method for passing an integer as the last argument, like this example:
void *foo(void *i) {
int a = *((int *) i);
free(i);
}
int main() {
pthread_t thread;
for ( int i = 0; i < 10; ++1 ) {
int *arg = malloc(sizeof(*arg));
if ( arg == NULL ) {
fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
exit(EXIT_FAILURE);
}
*arg = i;
pthread_create(&thread, 0, foo, arg);
}
/* Wait for threads, etc */
return 0;
}
Otherwise, I found academic examples that use an array method, like this example passing a struct:
//Runnable example
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct my_Struct{
int index;
int value;
};
void* my_Func(void *received_struct){
struct my_Struct *struct_ptr = (struct my_Struct*) received_struct;
printf("index: %d | value: %d \n", struct_ptr->index, struct_ptr->value);
//Now use 'struct_ptr->index', 'struct_ptr->value' as you wish
}
int main(){
struct my_Struct mystruct_1[5];
printf("\nEnter 5 numbers:\n");
for (int i=0; i<5; i++){
scanf("%d", &mystruct_1[i].value);
mystruct_1[i].index = i;
}
pthread_t tid[5];
for(int i=0; i<5; i++){
pthread_create(&(tid[i]), NULL, my_Func, &mystruct_1[i]);
}
for (int i=0; i<5; i++){
pthread_join(tid[i], NULL);
}
}
//To run: gcc [C FILE].c -lpthread -lrt
// ./a.out
//Grepper Profile: https://www.codegrepper.com/app/profile.php?id=9192
What is the advantage of the dynamic memory allocation method?
Update: I found in the IBM i documentation, based on gcc, that they use memory allocation
The last parameter of pthread_create() is passed on the stack of the newly created thread. When it is an integer or anything else which the size is little or equal than the size of a pointer, the parameter can be passed as it is to pthread_create() with a cast. But it is not the recommended way to make it as it is not portable on machines where for example the integers do not have the same size as the pointers. Let's compile the following simple program:
#include <pthread.h>
#include <stdio.h>
void* thread_task(void* arg)
{
printf("Thread received parameter: %d\n", (int)arg);
return NULL;
}
int main(void)
{
pthread_t tid;
int i = 45;
pthread_create(&tid, NULL, thread_task, (void *)i);
pthread_join(tid, NULL);
return 0;
}
The gcc compiler raises the following warnings:
$ gcc pcreate.c -o pcreate -lpthread
pcreate.c: In function ‘thread_task’:
pcreate.c:6:45: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
printf("Thread received parameter: %d\n", (int)arg);
^
pcreate.c: In function ‘main’:
pcreate.c:15:43: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
pthread_create(&tid, NULL, thread_task, (void *)i);
Hence, using a pointer on a structure or a table entry or a dynamically allocated memory area is the way to make it portable. The preceding program could be fixed as:
#include <pthread.h>
#include <stdio.h>
void* thread_task(void* arg)
{
printf("Thread received parameter: %d\n", *((int *)arg));
return NULL;
}
int main(void)
{
pthread_t tid;
int t[1] = { 45 };
pthread_create(&tid, NULL, thread_task, (void *)t);
pthread_join(tid, NULL);
return 0;
}
The compiler no longer raises any warnings:
$ gcc pcreate.c -o pcreate -lpthread
$ ./pcreate
Thread received parameter: 45
When you only want to pass one integer you can just cast it to a pointer:
void *foo(void *i) {
int a = (int)i;
}
for ( int i = 0; i < 10; ++1 ) {
pthread_create(&thread, 0, foo, (void*)i);
}
This gives maximum efficiency and no lifetime concerns.
I'm learning threading in C in OS. I don't know why following code is giving me segmentation fault. Can anyone help me here? I am also confused a bit about how pthread_join uses its argument void ** retval. What is its function?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void *thread (void *vargp) {
int* arg = *((int*)vargp);
return (void*)arg;
}
int main () {
pthread_t tid;
int thread_arg = 0xDEADBEEF;
int *ret_value;
pthread_create(&tid, NULL, thread, &thread_arg);
pthread_join(tid, (void **)(&ret_value));
printf("%X\n", *ret_value);
return 0;
}
This is not correct:
int* arg = *((int*)vargp);
(int*)vargp cast your void* to int*. But by writing int* arg = *((int*)vargp); you assing to the arg pointer the VALUE (0xDEADBEEF) of the argument vargp. This value (0xDEADBEEF) is not a valid adress.
what is the version of your compiler? because he must alert you :
invalid conversion from int to int*
You should write:
int* arg = (int*) vargp;
this is the right use of pthread_create with no warning:
#include <pthread.h>
#include <stdio.h>
void *check(void *temp) {
int* i = (int *)temp;
printf("%d\n", *i);
}
int main(void) {
pthread_t check_thread;
int i = 1;
pthread_create(&check_thread, NULL, check , (void *)&i);
pthread_join(check_thread, NULL);
return 0;
}
but the following code can also run well, just change void *check to void check:
#include <pthread.h>
#include <stdio.h>
void check(void *temp) {
int* i = (int *)temp;
printf("%d\n", *i);
}
int main(void) {
pthread_t check_thread;
int i = 1;
pthread_create(&check_thread, NULL, check, (void *)&i);
pthread_join(check_thread, NULL);
return 0;
}
if i change check to &check, it can also run well
#include <pthread.h>
#include <stdio.h>
void check(void *temp) {
int* i = (int *)temp;
printf("%d\n", *i);
}
int main(void) {
pthread_t check_thread;
int i = 1;
pthread_create(&check_thread, NULL, &check, (void *)&i);
pthread_join(check_thread, NULL);
return 0;
}
i see the thrid argument of pthread_create is: void *(*start_routine) (void *)
can someone tell me what does it mean?
Per the POSIX standard for pthread_create():
SYNOPSIS
#include <pthread.h>
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);
That means that the third argument to pthread_create() must be a function pointer of the form void *(*start_routine)(void*). The function pointer passed must refer to a function
declared and defined as
void *start_routine( void *arg )
{
void *ptr = ...;
...
return( ptr );
}
Period. End of discussion. Full stop.
You are invoking undefined behavior by not passing a function of the type void *(*start_routine) (void *) as the third argument to pthread_create().
Per J.2 Undefined behavior, paragraph 1 of the C standard:
The behavior is undefined in the following circumstances:
...
A pointer is used to call a function whose type is not compatible with the referenced type.
"Works with no observed issue" is covered by "undefined behavior". "Program crashes" is also covered.
The deal of the C standard is to write portable code, that could run on any conforming platform. The fact that this runs on your platform without visible errors, does not mean that it would on other platforms. Reasons for failure could e.g be that pthread_join could try to access a hardware register with the return value.
It is nothing but a function pointer. Lets break it down.
void *(*start_routine) (void *)
void* -> return type of function
start_routine -> function pointer name
void* -> argument type
the address of the function you pass will be assigned to function pointer start_routine and start_routine will be invoked as new thread from kernel.
I have the following functions :
void *foo(void *i) {
int a = (int) i;
}
int main() {
pthread_t thread;
int i;
pthread_create(&thread, 0, foo, (void *) i);
}
At compilation, there are some errors about casting ((void *) i and int a = (int) i). How can I pass an integer as the last argument of pthread_create properly?
Building on szx's answer (so give him the credit), here's how it would work in your for loop:
void *foo(void *i) {
int a = *((int *) i);
free(i);
}
int main() {
pthread_t thread;
for ( int i = 0; i < 10; ++1 ) {
int *arg = malloc(sizeof(*arg));
if ( arg == NULL ) {
fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
exit(EXIT_FAILURE);
}
*arg = i;
pthread_create(&thread, 0, foo, arg);
}
/* Wait for threads, etc */
return 0;
}
On each iteration of the loop, you're allocating new memory, each with a different address, so the thing that gets passed to pthread_create() on each iteration is different, so none of your threads ends up trying to access the same memory and you don't get any thread safety issues in the way that you would if you just passed the address of i. In this case, you could also set up an array and pass the addresses of the elements.
You can allocate an int on the heap and pass it to pthread_create(). You can then deallocate it in your thread function:
void *foo(void *i) {
int a = *((int *) i);
free(i);
}
int main() {
pthread_t thread;
int *i = malloc(sizeof(*i));
pthread_create(&thread, 0, foo, (void *) i);
}
You should cast the address of i (rather than the value of i as you do now) in the last argument of pthread_create().
pthread_create(&thread, 0, foo, (void *) &i);
^ is missing
And the casting is wrong in your function too. It should be:
int a = *((int*) i);
If you intend to read the value, you should also initialize i to some value in main() as it's uninitialized now.
2 Use proper definition for main():
int main(void)
or int main(int argc, char *argv[]) or its equivalent.
Old question, but I faced the same problem today, and I decided not to follow this path.
My application was really about performance, so I chose to have this array of ints declared statically.
Since I don't know a lot of applications where your pthread_join / pthread_cancel is in another scope than your pthread_create, I chose this way :
#define NB_THREADS 4
void *job(void *_i) {
unsigned int i = *((unsigned int *) _i);
}
int main () {
unsigned int ints[NB_THREADS];
pthread_t threads[NB_THREADS];
for (unsigned int i = 0; i < NB_THREADS; ++i) {
ints[i] = i;
pthread_create(&threads[i], NULL, job, &ints[i]);
}
}
I find it more elegant, more efficient, and you don't have to worry about freeing since it only lives in this scope.
While this is an old question there is one option missing when all you need is to pass a positive integer like a descriptor: you can pass it directly as the address, while it it a hack it works well and avoid allocating anything :)
NOTE: the size of the integer must match the size of a pointer on your OS but nowadays most systems are native 64bits.
#include <pthread.h>
#include <inttypes.h>
#include <stdio.h>
void *_thread_loop(void *p)
{
uint64_t n = (uint64_t)p;
printf("received %llu\n", n);
return NULL;
}
int main(int argc, char const *argv[])
{
pthread_t read_thread_id;
uint64_t n = 42;
pthread_create(&read_thread_id, NULL, _thread_loop, (void *)n);
pthread_join(read_thread_id, NULL);
return 0;
}
I know how to pass a function as an argument for another function. But I don't know if the argument of a function passed to pthread can be another function. Is this even possible?
Here is sample code that compiles OK, but doesn't work:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_t idThread;
void aFunction(){
while(1){
fprintf(stderr,"I've been called!\n");
usleep(1000000);
}
}
void * threadFunction(void *argFunc){
// Do here some stuff;
// ...
// Now call the function passed as argument
void (*func)() = argFunc;
}
int thread_creator(void(*f)()){
// I want to use as argument for threadFunction the f function
pthread_create(&idThread, NULL, threadFUnction, (void *)f);
}
int main(){
thread_creator(aFunction);
while(1);
return 0;
}
It can be a function pointer, if you're willing to bend rules a little. Strictly speaking a void * isn't guaranteed to be able to hold a function pointer. Something like this (untested):
void some_fun()
{
/* ... */
}
void thread_fun(void *arg)
{
void (*fun)() = arg;
}
pthread_create(...., (void *) some_fun);
EDIT
In your example, you also need to call the function, via the function pointer. Something like:
void (*func)() = argFunc;
funct(); /* <-- */
Stricly speaking, it is not possible. According to the standard, a pointer to void may just be converted to or from a pointer to an object type. On some architectures, function adresses are larger than object adresses.
C11, § 6.3.2.3 Pointers
A pointer to void may be converted to or from a pointer to any object
type. A pointer to any object type may be converted to a pointer to
void and back again; the result shall compare equal to the original
pointer.
Otherwise, it is a common extension.
C11, § J.5.7 Function pointer casts
A pointer to an object or to void may be cast to a pointer to a
function, allowing data to be invoked as a function (6.5.4).
In your example, you don't call func.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_t idThread;
void aFunction(void)
{
while (1) {
fprintf(stderr, "I've been called!\n");
usleep(1000000);
}
}
void *threadFunction(void *argFunc)
{
void (*func)(void) = argFunc;
func(); /* HERE */
}
int thread_creator(void (*f)(void))
{
pthread_create(&idThread, NULL, threadFUnction, (void *) f);
}
int main(void)
{
thread_creator(aFunction);
while (1);
return 0;
}
To add to the answers already given:
Conceptually, function pointers can be passed around just like any other type of pointer, but - as has been pointed out - a void * is not guaranteed to be large enough to hold a function pointer, only a data pointer.
A workaround for something like the pthread_create callback function is to wrap your desired function pointer in a structure that you use as the user data:
struct threadArg
{
void (*callback)(void);
};
// ...
struct threadArg *threadArg = malloc(sizeof(threadArg));
threadArg->callback = myFunction;
pthread_create(&idThread, NULL, threadFunction, (void *) threadArg);
There is no need for dubious casts involving function pointers. The argument to the thread can be a pointer to a struct which can contain anything.
#include <pthread.h>
struct arg {
void (*func)(void);
int other_stuff;
};
void function(void)
{
}
void *thread_function(void *arg)
{
struct arg *a1 = arg;
a1->func();
return NULL;
}
int main(void)
{
pthread_t tid;
struct arg arg = {.func = function};
pthread_create(&tid, NULL, thread_function, &arg);
.
.
.
}