Create pthread with the function of multiple arguments - c

If I am going to create a pthread for the following function.
Assume everything is properly delared.
pthread_create(&threadId, &attr, (void * (*)(void*))function, //what should be the arguments for here??);
int a = 0;
int b = 1;
//c and d are global variables.
void function(int a, int b){
c = a;
d = b;
}

This does not work. function() has to take exactly one argument. That's why you have to do this:
(void * ()(void))
You're telling your compiler "no, seriously, this function only takes one argument", which of course it doesn't.
What you have to do instead is pass a single argument (say a pointer to a struct) which gets you the information you need.
Edit: See here for an example: number of arguments for a function in pthread

The pthread thread function always takes one void * argument and returns a void * value. If you want to pass two arguments, you must wrap them in a struct - for example:
struct thread_args {
int a;
int b;
};
void *function(void *);
struct thread_args *args = malloc(sizeof *args);
if (args != NULL)
{
args->a = 0;
args->b = 1;
pthread_create(&threadId, &attr, &function, args);
}
and for the thread function itself:
void *function(void *argp)
{
struct thread_args *args = argp;
int c = args->a;
int d = args->b;
free(args);
/* ... */
You don't need to use malloc() and free(), but you must somehow ensure that the original thread doesn't deallocate or re-use the thread arguments struct until the called thread has finished with it.

Related

how to use pthread for not just void functions with void argument in C/C++?

I wanna call multiple functions and deal with their return values (using pthread_join) in main(), but they are all int functions with multiple non-void arguments, and the definition of pthread_create is:
int pthread_create(pthread_t * thread,
const pthread_attr_t * attr,
void * (*start_routine)(void *),
void *arg);
all examples of the start_routine I found in the internet are type of void * with type of single void * argument, is it possible to call int functions with multiple non-void type arguments in pthread_create?
You want to wrap the int function into a function of the required type.
So assuming you want to return an int you might do it like this:
(The example assume C99 and leaves out relevant error checking for the sake of readebility.)
#include <inttypes.h> /* for intptr_t */
#include <stdio.h>
#include <pthread.h>
struct S
{
int x;
int y;
};
int sum(int x, int y)
{
return x + y;
}
void * thread_function(void * pv)
{
struct S * ps = pv;
pthread_exit((void *) (intptr_t) sum(ps->x, ps->y));
}
int main(void)
{
struct S s = {41, 1};
pthread_t pt;
pthread_create(&pt, NULL, thread_function, &s);
void * pv;
pthread_join(pt, &pv);
int z = (intptr_t) pv;
printf("%d + %d = %d\n", s.x, s.y, z);
}
This prints:
41 + 1 = 42
The casting to and from intptr_t is necessary to assure the misuse of a pointer value as an integer does not violate the C-Standard.
If you look at the manual page you will see that the function argument is
void *(*start_routine) (void *).
You cannot pass a different type of function to start routine.
You can use (void *) to pass an argument to start_routine.
You can cast the pThread pointer to some type compatible with integer. Better solution is to put the entire functionality in a wrapper function. Please refer to the below link:
C++, create a pthread for a function with a return type?
Let's see if I understood the question.
You want to call a function with a signature like
int myfunct(int a, int b, int c)
then define a struct like this
struct my_funct_param_t
{
int a ;
int b ;
int c ;
} ;
and a wrapper to use as start routine
void *myfunct1(void *arg)
{
my_funct_param_t *arg1 = (my_funct_param_t *)arg ;
myfunct(arg1->a, arg1->b, arg1->c) ;
....
}
The code that starts the thread must create the my_funct_patam_t object and fill in accordingly. Beware of this object lifetime....

Equivalent of std::bind in C by hacking the stack

After some research I didn't find a good way to implement the std::bind in C.
I build a small program that implements an equivalent of std::bind in C by hacking the stack.
There's two functions I will try to bind to function with pre-defined arguments.
My problem is this code is only working under Windows. Under Linux, this is a mess. I this the problem is my knowledge of the stack and the way that arguments are store in memory.
Thanks,
Please, find below the code I made:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
The two functions I want to bind :
void test1 (int nombre, char t, int nombre2)
{
printf ("test 1 : %d%c%d\n", nombre, t, nombre2);
}
void test2 (char t, int nombre, int nombre2)
{
printf ("test 2 : %c%d%d\n", t, nombre, nombre2);
}
Two struct that will store the argument of each function (order of fields is important).
typedef struct {
int nombre;
char t;
int nombre2;
} struct1;
typedef struct {
char t;
int nombre;
int nombre2;
} struct2;
This "fake" struct will be use to write on the stack by dereferencing a structvoid* variable.
// Size must be bigger than every struct*
typedef struct {
int i[10];
} structvoid;
The main function.
int main(int argc, char** argv) {
// Variables to store the two functions and their arguments.
void * functions[2];
structvoid * data[2];
void *func1 = (void *)&test1;
void *func2 = (void *)&test2;
void (*functionPtrc)(structurevoid);
// Definition of the argument of the first function test1
struct1 data1;
data1.nombre = 15;
data1.t = 'c';
data1.nombre2 = 30;
// and storing data.
void *datac = malloc (sizeof (structvoid));
memcpy(datac, &data1, sizeof (struct1));
data[0] = (structvoid*)datac;
functions[0] = func1;
// Same thing with function 2.
struct2 data2;
data2.t = 'a';
data2.nombre = 5;
data2.nombre2 = 10;
datac = malloc (sizeof (structvoid));
memcpy(datac, &data2, sizeof (struct2));
data[1] = (structvoid*)datac;
functions[1] = func2;
// Get the pointer to the first function (test1);
functionPtrc = functions[0];
// All the hack is here. By dereferencing the data, this will write on the stack all arguments need by the test1 function.
functionPtrc(*data[0]);
functionPtrc = functions[1];
functionPtrc(*data[1]);
// To check the result.
test1 (data1.nombre, data1.t, data1.nombre2);
test2 (data2.t, data2.nombre, data2.nombre2);
return 0;
}
EDIT
Here a new version of the program by calling function via the calling convention. I only wrote the new lines. The problem of this method is I can only store data inside a "void *" field. If I increase the size of structvoid, I got garbage behaviors.
// Structure that memories each argument
typedef struct {
void *i[1];
} structvoid;
int main(int argc, char** argv) {
// Variables to store the two functions and their arguments.
void * functions[2];
structvoid * data[2];
void *func1 = (void *)&test1;
// Let's start with a maximum of 5 arguments
void (*functionPtrc)(structurevoid, structurevoid, structurevoid, structurevoid, structurevoid);
// Definition of the argument of the first function test1
struct1 data1;
data1.nombre = 15;
data1.t = 'c';
data1.nombre2 = 30;
// and storing data.
structvoid *datac = malloc (sizeof (structvoid)*5);
memcpy(&datac[0], &data1.nombre, sizeof (data1.nombre));
memcpy(&datac[1], &data1.t, sizeof (data1.t));
memcpy(&datac[2], &data1.nombre2, sizeof (data1.nombre2));
data[0] = datac;
functions[0] = func1;
// Get the pointer to the first function (test1);
functionPtrc = functions[0];
// Call the function with the arguments. The unused argument will be ignored.
functionPtrc(data[0][0], data[0][1], data[0][2], data[0][3], data[0][4]);
}

pthread_create and passing an integer as the last argument

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;
}

The argument of pthread function can be another function?

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);
.
.
.
}

How to pass parameters to the function called by clone()?

I have to use the clone() system call in the main-function to get 2 threads. (I know, there are other options, but in this case, it has to be clone()).
The system call works and both threads arrive in the designated function (foo). But in this function I need them to call another function with this signature:
void increment(int* a, int b)
(Sidenote: It adds b * 1 to a. (= a+b))
The important thing is, that both, a and b, are declared in the main-function and I don't know how to pass them to foo.
I already tried different things, but without success. I've gotten a hint: Use an adapter.
But I have no clue how to do this. (I also dont know how to use the args in clone with int.)
Any suggestions?
One of the arguments to clone() is a void* arg. This lets you pass a void pointer to your function. In order to pass an int pointer and an int instead, you have to create a struct with an int pointer and int assigned to a and b respectively, then cast a pointer to that struct into a void pointer. Then inside the function you reverse the process.
My C is a little rusty and I haven't compiled this, so don't quote me on it, but it should look roughly like this:
struct clone_args {
int* a;
int b
};
int main(int argc, char* argv[])
{
struct clone_args args;
args.a = a;
args.b = b;
void* arg = (void*)&args;
clone(fn, ..., arg, ...);
}
int fn(void* arg)
{
struct clone_args *args = (struct clone_args*)arg;
int* a = args->a;
int b = args->b;
}
Note: take care that the struct you create is still in scope when fn is called, as it isn't copied. You might have to malloc it.
Here is the example code:
#define stacksize 1048576
typedef struct
{
int ii;
int jj;
} someinput1;
static int /* Start function for cloned child */
childFunc(someinput1 *struc)
{
printf("Child: PID=%ld PPID=%ld\n", (long) getpid(), (long) getppid());
printf("Hi!! I am child process created by Clone %ld \n",(long) getpid());
printf("Value of x %d %d\n",struc->ii,struc->jj);
}
int main()
{
someinput1 inputtest;
int i;
char *stack; /* Start of stack buffer */
char *stack1; /* End of stack buffer */
pid_t pid;
stack = malloc(stacksize);
stack1 = stack + stacksize;
for (i = 0;i<5;i++)
{
inputtest.ii = i+5;
inputtest.jj = inputtest.ii + 10;
pid = clone(childFunc, stack1, NULL, (void *) (&inputtest));
printf("clone returned -- %ld \n", (long) pid);
}
sleep(1);
exit(EXIT_SUCCESS);
}

Resources