#include <stdio.h>
#include <stdlib.h>
// Thread Declarations
#include <pthread.h>
pthread_t monitor_thread;
void *Get_Monitor_Data(void *BM_params);
// this is my struct ///
typedef struct
{
HCORE BM_cores[0];
int total_cores;
} BM_PARAMS;
BM_PARAMS BM_Dat;
int Start_monitor(void)
{
int RETVAL=0;
RETVAL = pthread_create(&monitor_thread, NULL, Get_Monitor_Data,(void*)BM_Dat);
if(RETVAL !=0)
{
printf("Error Starting Thread \n");
}
return 0;
}
void *Get_Monitor_Data (void *BM_Dat) // Bus Monitor Thread
{
BM_PARAMS*monitor_params;
int no_of_cores=0;
monitor_params = (BM_PARAMS *) BM_Dat;
BTICard_CardReset(*monitor_params->BM_cores);// reset card if required
return 0;
}
The pthread create portion is giving error of "cannot convert to a pointer type"
is there anything wrong which i am doing?
i need to pass a structure to the P thread function as argument, how can i do that?
You're trying to cast BM_Dat which has structure type to a void *. A struct cannot be converted to a pointer. You can however pass the address of BM_Dat:
RETVAL = pthread_create(&monitor_thread, NULL, Get_Monitor_Data, &BM_Dat);
A BM_PARAMS * can be converted to a void * (implicitly in fact), and in fact your thread function converts the parameter to this type.
Related
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;
I'm trying to pass pointers to struct lower_hyper_id from a thread to the main thread, by the means of pthread_exit() function, that would compare and output the value in the struct. However, i receive an error (Segmentation fault) when i am trying to use the returned value and cast it to the struct.
thread that creates and returns the struct:
void *compute(void *arg){
lower_hyper_id *data = (lower_hyper_id *)malloc(sizeof(lower_hyper_id));
//some code
//i debug the program, and at this point, the struct i want
//to return has the values i want.
pthread_exit((void *)data);
}
in the main:
lower_hyper_id l_hyper_id;
int main(){
void *ap_state;
lower_hyper_id values;
void *ret;
//some code
for (int i = 0; i < NUMBER_OF_FILTERING_THREADS; i++)
{
s = pthread_join(filtering_threads[i], (void *)&ret);
//some error checking
values = *((lower_hyper_id *)ret); //this is where i receive the error
if (values.lowest_cost <= l_hyper_id.lowest_cost)
{
l_hyper_id.hyper_id = values.hyper_id;
l_hyper_id.lowest_cost = values.lowest_cost;
}
free(ret);
}
I have already looked at answers in the stackoverflow such as this question, but it hasn't helped me resolving this. I actually changed the code to be exactly equal to the code in this answer, but still it gives me an error.
You're not testing if malloc returned NULL. That could be an issue if you're allocing a large chunk and the allocation can fail.
Other than that, I don't think the problem is in the return value passing.
pthread_exit()ing with a mallocd pointer should work just fine.
A minimial working example:
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *compute (void *arg)
{
printf("thread=%llx\n", (unsigned long long)pthread_self());
size_t sz = strlen("hello world")+1;
char *ret = malloc(sz+1);
if(ret) memcpy(ret, "hello world", sz+1);
return ret;
}
int main()
{
printf("thread=%llx\n", (unsigned long long)pthread_self());
pthread_t ptid;
int er;
if((er=pthread_create(&ptid,0,compute,0))) return errno=er,perror(0),1;
void *retval;
if((er=pthread_join(ptid,&retval))) return errno=er,perror(0),1;
printf("thread returned: %s\n", (char*)retval);
free(retval);
}
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.
having some trouble finding out the syntax around returning a vector from a pthread function. Here's currently what I have:
typedef struct vectorData {
vector v1;
vector v2;
} vectorData;
void *vectorAddThread(void *arg) {
vectorData *data = (vectorData *)arg;
vector v1 = data->v1;
vector v2 = data->v2;
vector result = {v1->x + v2->x, v1->y + v2->y, v1->z + v2->z};
return (void*) result;
}
I'm getting errors on the last two lines about the return result, and the the adding part. Thanks
You can't convert a struct to a void * pointer. You need dynamically allocate a vector in your case with malloc, and return the pointer.
vector *result = malloc(sizeof(vector));
result->x = ?;
result->y = ?;
result->z = ?;
return (void *)result;
Now that would solve the issue of returning a struct from a function that returns void *. But if you're using pthreads you shouldn't be returning objects from them, you need to pass the vector to it as user data in arg.
This is probably easiest:
typedef struct vectorData {
vector v1;
vector v2;
vector result;
} vectorData;
Saves messing about with dubious thread-stack vars, mallocs etc. and ties the result output directly to the inputs.
The thread start function in pthread library returns a pointer to void. Can return any pointer type by type-casting it to (void *). The return value can be accessed by pthread_join(3).
However, a vector needs the type of element information also. Not sure if type-casting it to (void *) and accessing it again will work fine. Using it as an element of structure seems better.
In the following example, I am returning a pointer to structure from the thread start function. The structure contains a vector and two character arrays. You can change it according to your requirement. I am using two pointers to show that data is copied on the variable used for pthread_join(3).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <vector>
void *functionPthread(void *);
struct retStruct
{
std::vector<int> vecNumber;
char name[20];
char city[20];
};
struct retStruct *r2;
struct retStruct *r1;
int main()
{
int rc, i;
pthread_t th;
r2 = (retStruct*) malloc(sizeof(retStruct));
memset(r2, '\0', sizeof(r2));
if(rc = pthread_create(&th, NULL, &functionPthread, NULL))
{
printf("Thread creation failed, return code %d, errno %d", rc, errno);
}
pthread_join(th, (void**)&r2);
for(i = 0; i < r2->vecNumber.size(); i++)
printf("Vectore element at index %d = %d\n", i, r2->vecNumber.at(i));
printf("Name: %s, City: %s, Vector Number: %d\n", r2->name, r2->city, r2->vecNumber.front());
free(r1);
free(r2);
return 0;
}
void *functionPthread(void *)
{
r1 = (retStruct*) malloc(sizeof(retStruct));
memset(r1, '\0', sizeof(r1));
strcpy(r1->name, "xxxx");
strcpy(r1->city, "yyyy");
r1->vecNumber.push_back(11);
r1->vecNumber.push_back(12);
return r1;
}
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);
.
.
.
}