pthread_exit() and pthread_join() don't work [duplicate] - c

This question already has answers here:
How to return a value from pthread threads in C?
(9 answers)
Closed 1 year ago.
I don't know why it doesn't return the value that I type in. I know it's not the void* arg because it prints the right number, but I don't have any idea.
CODE:
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
void* stampa(void* arg) {
float dato = *(float*)arg;
printf("Read: %f\n", dato);
pthread_exit((void*)&dato);
}
// Main
int main() {
system("clear");
pthread_t miot;
int creathread;
float x;
float *status;
printf("Number: ");
scanf("%f", &x);
creathread = pthread_create(&miot, NULL, stampa, (void*)&x);
if (creathread != 0) {
printf("Error\n");
}
pthread_join(miot, (void*)&status);
printf("Returned: %f\n", *status);
return 0;
}
RESULT:
Number: 10
Read: 10.000000
Returned: 0.000000

void* stampa(void* arg) {
float dato = *(float*)arg;
printf("Read: %f\n", dato);
pthread_exit((void*)&dato);
}
dato no longer exists as soon as the function returns. By taking the address of that variable and dereferencing it after the function returns (back in the main thread), you're invoking undefined behavior.
You can either:
Cast the float to void * and return the value directly (as if it were a pointer) and cast it back to float in main.
This may break some rules (is a void * guaranteed to be big enough to hold a float?), but I've seen this used often.
Allocate an object using malloc and return that pointer.
First option:
void* stampa(void* arg) {
float dato = *(float*)arg;
printf("Read: %f\n", dato);
pthread_exit((void*)dato);
}
// Main
int main() {
system("clear");
pthread_t miot;
int creathread;
float x;
float status;
printf("Number: ");
scanf("%f", &x);
creathread = pthread_create(&miot, NULL, stampa, (void*)&x);
if (creathread != 0) {
printf("Error\n");
}
pthread_join(miot, (void*)&status);
printf("Returned: %f\n", status);
return 0;
}

Related

How to pass an array of structures in a function? [duplicate]

This question already has answers here:
How do I pass an array of structures to a function?
(3 answers)
Closed 1 year ago.
About to ready to give up on this
Been having an issue with my code for hours, has been telling me I have an error about the error: expected expression before 'Robot_t' and cannot find a solution, if anyone has a working solution you will save me
This is the error message provided
Arrayintofn.c: In function 'main':
Arrayintofn.c:23:23: error: expected expression before 'Robot_t'
loading_Profiles (Robot_t RobotInfo[]);
No matter what I do or who I consult there is no solution
Here is the code as well
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
typedef struct
{
int Robot_Number;
char Robot_Name[30];
int Year_Manufacturer;
float Top_Speed;
float Mass;
float Best_Score;
} Robot_t;
void loading_Profiles();
int main()
{
Robot_t RobotInfo[5];
loading_Profiles (Robot_t RobotInfo[]);
int i;
for (i = 0; i < 50; i++) {
printf("%d\t\t%s\t\t%d\t\t\t%.2f\t\t%.2f\t\t%.2f\n",
RobotInfo[i].Robot_Number, RobotInfo[i].Robot_Name,
RobotInfo[i].Year_Manufacturer, RobotInfo[i].Top_Speed,
RobotInfo[i].Mass, RobotInfo[i].Best_Score);
}
return 0;
}
void loading_Profiles()
{
int Counter = 0;
int i;
Robot_t RobotInfo[5];
FILE *ROBOTtxt = fopen("Robot.txt", "r");
if (ROBOTtxt == NULL) {
perror("an error occured during the loading of the file\n");
exit(-1);
}
for (i = 0; i < 50; i++) {
char LineNumber[100] = "";
fgets(LineNumber, 100, ROBOTtxt);
sscanf(LineNumber, "%d %s %d %f %f %f",
&RobotInfo[i].Robot_Number,
RobotInfo[i].Robot_Name,
&RobotInfo[i].Year_Manufacturer,
&RobotInfo[i].Top_Speed,
&RobotInfo[i].Mass,
&RobotInfo[i].Best_Score);
Counter++;
if (feof(ROBOTtxt)) {
break;
}
}
if (ferror(ROBOTtxt)) {
perror("an error has occured");
exit(-1);
}
fclose(ROBOTtxt);
}
Your function loading_Profiles() written like this doesnt accept any parameters but you pass an array in the main function. You should rewrite the declaration as
"void loading_Profiles(Robot_t arr_name[])"
In the main function you should pass an argument only by its name. So instead of this:
"loading_Profiles(Robot_t RobotInfo[]);"
just pass:
"loading_Profiles(RobotInfo);"
There were a number of errors in your code, I'll paste my commented solution below, but for reference:
in the loading_Profiles prototype you weren't specifying a parameter
in the main, you were calling the function uncorrectly
inside the loading_Profiles implementation, you were trying to work on a local array, and not the one passed as an argument.
Also, sometimes you were using 50, sometimes 5? Which is it?
Here's the code, tested using a file generated on Mockaroo.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
typedef struct
{
int Robot_Number;
char Robot_Name[30];
int Year_Manufacturer;
float Top_Speed;
float Mass;
float Best_Score;
} Robot_t;
void loading_Profiles(Robot_t RobotInfo[]); // added parameter to prototype
int main()
{
Robot_t RobotInfo[50]; // 50 instead of 5
loading_Profiles(RobotInfo); // simply pass your variable
int i;
for (i = 0; i < 50; i++) {
printf("%d\t\t%s\t\t%d\t\t\t%.2f\t\t%.2f\t\t%.2f\n",
RobotInfo[i].Robot_Number, RobotInfo[i].Robot_Name,
RobotInfo[i].Year_Manufacturer, RobotInfo[i].Top_Speed,
RobotInfo[i].Mass, RobotInfo[i].Best_Score);
}
return 0;
}
void loading_Profiles(Robot_t RobotInfo[]) // added parameter
{
int Counter = 0;
int i;
FILE *ROBOTtxt = fopen("Robot.txt", "r");
//Robot_t RobotInfo[5]; // removed, work on the array passed as argument, not a local one
if (ROBOTtxt == NULL) {
perror("an error occured during the loading of the file\n");
exit(-1);
}
for (i = 0; i < 50; i++) {
char LineNumber[100] = "";
fgets(LineNumber, 100, ROBOTtxt);
sscanf(LineNumber, "%d %s %d %f %f %f",
&RobotInfo[i].Robot_Number,
RobotInfo[i].Robot_Name,
&RobotInfo[i].Year_Manufacturer,
&RobotInfo[i].Top_Speed,
&RobotInfo[i].Mass,
&RobotInfo[i].Best_Score);
Counter++;
if (feof(ROBOTtxt)) {
break;
}
}
if (ferror(ROBOTtxt)) {
perror("an error has occured");
exit(-1);
}
fclose(ROBOTtxt);
}
Let me know if it works
While declaring parameter for the function you need to specify variable type as structure and create an array of structure type.
void loading_Profiles(Robot_t RobotInfo[]) // added parameter

How to convert * to double/float with pthread, pthread_exit

I need to create a program which calculates recursion (for certain sequence). When I use int and decleare a recursion, that calculates values without floating numbers (like fibonacci sequence, which returns only neutral numbers) it works. However, when trying to use sequences based on divison (with floating numbers) it displays an error as below:
error: cannot convert to a floating type
pthread_exit((void*)(float)wynik;
How should I change the code (or actually a function *ciag, because problem is with that one), that it will accept floating numbers?
Function which works fine (with int)
int* fibo(int n){
int wynik;
int* n1;
if (n==0) wynik=0;
else if (n==1) wynik=1;
else wynik =(int)fibo((int)(n-1))+(int)fibo((int)(n-2));
return (int*)wynik;
pthread_exit((void*)wynik);
}
And the one I have problem with (with float, but same happens when I try to use double)
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#define COUNT 2
float *ciag(int n) {
float wynik;
if(n == 0)
wynik = -1;
else
wynik = ((float)ciag(n - 1)*(n + 1))/(float)ciag(n - 1)*(float)ciag(n - 1)*(float)ciag(n - 1);
return(float *)wynik;
pthread_exit((void *)wynik);
}
void *drugi_watek(void* wynik) {
int i = 1;
while(i == 0) {
printf("#");
fflush(stdout);
usleep(300000);
pthread_exit((void*)wynik);
}
}
int main() {
pthread_t watek_1, watek_2;
int n;
float wynik;
printf("Podaj numer ciagu: ");
scanf("%d", &n);
pthread_create(&watek_1, NULL,(void*)&ciag, n);
pthread_create(&watek_2, NULL, &drugi_watek, NULL);
if(!pthread_join(watek_1,(void**)&wynik))
{
pthread_cancel(watek_2);
}
printf("Element numer %f ciagu: %f\n", &n, &wynik);
return 0;
}
You cannot directly convert a float to a void * or vice-versa.
The cleanest way to do this is to allocate space for a float somewhere -- either from the heap or on the caller's stack -- and have the thread function store the float value into the pointed-to variable (float * is easily convertible to/from void *). If you go this route and allocate the value on the stack, you need to make sure that the caller's stack frame remains in existence until the thread completes.
Since the function you want to call is recursive, having it as the thread function is too cumbersome. Better to make it a separate (ordinary) function that takes an int argument and returns a float. Then make a wrapper function that will be the target for pthread_create.
And since you also need to pass an argument int to your function, it's easiest to allocate a struct to contain both argument and return value (a union would also work since you don't really need argument and return value at the same time). Here's a sample program that demonstrates the pattern:
#include <pthread.h>
#include <stdio.h>
static float ciag(int n)
{
float wynik;
if(n == 0)
wynik = -1;
else
wynik = (ciag(n - 1)*(n + 1))/ciag(n - 1)*ciag(n - 1)*ciag(n - 1);
return wynik;
}
typedef struct {
int i;
float f;
} if_t;
static void *ciag_thread(void *vp)
{
if_t *ifp = vp;
// Obtain argument from the structure and put the result back into the structure
ifp->f = ciag(ifp->i);
return vp;
}
int main()
{
pthread_t watek_1;
int n = 4;
// Obtain n however you like. Then place argument into structure allocated
// on the stack
if_t arg;
arg.i = n;
// Pointer to structure is implicitly convertible to (void *)
pthread_create(&watek_1, NULL, ciag_thread, &arg);
pthread_join(watek_1, NULL);
printf("Thread returned %f\n", arg.f);
return 0;
}
One other note. Your code seems to suggest that pthread_join on the first thread might sometimes fail. That will not happen here. Though for large values of n, it may take a very long time to complete, due to the quartic nature of your function.

C passing array to pthread in Dining Philosopher

I'm writing code for the Dining Philosopher thread problem for N number of philosophers from user input. I get an error for dereferencing void * pointer. What am I doing wrong specifically with passing in the array?
void *philosopher(void *arg_l);
int main()
{
int i,A,B;
scanf("%10d", &A);
scanf("%10d", &B);
printf("You got %d phils and %d turns each\n",A,B);
int args[2];
args[0] = A;
args[1] = B;
pthread_t thread_id[A];
sem_init(&mutex,0,1);
for(i=0;i<A;i++)
sem_init(&S[i],0,0);
for(i=0;i<A;i++)
{
args[2] = phil_num[i];
pthread_create(&thread_id[i],NULL,philosopher,&args);
printf("Philosopher %d is thinking\n",i+1);
}
for(i=0;i<A;i++)
pthread_join(thread_id[i],NULL);
}
void *philosopher(void *arg_l)
{
arg_l[0] = int A;
arg_l[1] = int B;
...
return NULL;
}
Since arg_l has type void *, you can't use the subscript operator [] on it. That would mean each element has type void, which cannot be instantiated. Also, the syntax on the right side of the assignment is not valid.
You need to cast the thread argument to int * before you can use it. Also, you need to pass in args without taking its address, since an array decays into a pointer to the first element when passed to a function.
pthread_create(&thread_id[i],NULL,philospher,args);
...
void *philospher(void *arg_l)
{
int *args = arg_l;
...
}
Your lines like:
arg_l[0] = int A;
are completely broken. You would get away with:
int A = ((int *)arg_l)[0];
You cannot dereference a void * validly, nor can you index them (in part because that requires dereferencing, in part because in standard C — as opposed to GNU C — the sizeof(void) is undefined). You need to convert to an appropriate type with a cast and then derefence, as shown.
Note: args[2] = phil_num[i]; is writing out of bounds (you define int args[2]; but it appears you need int args[3];.
You have to pass each philosopher a separate array because there is no guarantee that a given thread will have read the information before the main thread reassigns a new value. Usually, you'll use a structure, not an array, for the data passed to an individual thread; you have an initialized array of those structures so that each thread gets its own unique control information.
Is there any way you can give an example of this?
Somewhat like this. The key point is the array of struct Info, each of which is separately initialized (using a C99 compound literal) and a different element of the array is passed to each thread so that it gets its own data, rather than trying to share data with other threads.
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
struct Info
{
int number;
int turns;
int diner;
};
enum { MAX_PHILOSOPHERS = 10 };
enum { MAX_TURNS = 99 };
static sem_t mutex;
static sem_t S[MAX_PHILOSOPHERS];
static void *philosopher(void *arg_l);
int main(void)
{
int A, B;
printf("How many philosophers? How many turns? ");
fflush(stdout);
if (scanf("%d %d", &A, &B) != 2)
{
fprintf(stderr, "Failed to read input\n");
return 1;
}
if (A < 2)
fprintf(stderr, "You specified too few philosophers (%d)\n", A);
if (A > MAX_PHILOSOPHERS)
fprintf(stderr, "You specified too many philosophers (%d, but the maximum is %d)\n",
A, MAX_PHILOSOPHERS);
if (B < 1)
fprintf(stderr, "You specified too few turns (%d)\n", B);
if (B > MAX_TURNS)
fprintf(stderr, "You specified too many turns (%d, but the maximum is %d)\n",
B, MAX_TURNS);
if (A < 2 || A > MAX_PHILOSOPHERS || B < 1 || B > MAX_TURNS)
return 1;
printf("You have %d philosophers who get %d turns each\n", A, B);
/* This assignment could be in the thread creation loop before pthread_create() */
/* Or in the loop that uses sem_init() */
struct Info info[A];
for (int i = 0; i < A; i++)
info[i] = (struct Info){ A, B, i};
sem_init(&mutex, 0, 1);
for (int i = 0; i < A; i++)
sem_init(&S[i], 0, 0);
pthread_t thread_id[A];
for (int i = 0; i < A; i++)
{
pthread_create(&thread_id[i], NULL, philosopher, &info[i]);
printf("Philosopher %d is thinking\n", i + 1);
}
for (int i = 0; i < A; i++)
pthread_join(thread_id[i], NULL);
printf("Dinner is over\n");
return 0;
}
static void *philosopher(void *arg_l)
{
struct Info *info = arg_l;
printf("N = %d, T = %d, I = %d\n", info->number, info->turns, info->diner);
/* ...do dining stuff; remember to share nicely!... */
return 0;
}
The #pragma allows the code to compile on macOS Sierra, which doesn't have working versions of the <semaphore.h> functions — they just return an error indication and set errno to ENOSYS (function not implemented).
This code should check the return value of the pthread functions and the semaphore operations too — it is being lazy not to do so.

Conversion of integer to string in multi-threads

in this code, I am creating two threads (joystick and motor). The intention of the joystick thread is to ask the user to input a certain speed integer value (for eg. 200). From my understanding, this integer value must be converted to a string in-order for the motor thread to receive this string value and convert it back to an integer value, before passing it into my application.
The result of the compiled code in GCC is my motor application receives a speed of zero despite a user input of any other numbers, and hence, it is not moving. May I know if I had done the conversion from integer to string or vice versa wrongly?
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <semaphore.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define MAX_LEN 128
//char n[1024];
pthread_mutex_t lock= PTHREAD_MUTEX_INITIALIZER;
int string_read=FALSE;
pthread_cond_t cond;
void * joystick()
{
while (1)
{
int s;
char str[7];
while(string_read);
pthread_mutex_lock(&lock);
printf("Enter speed: ");
scanf("%d", &s);
snprintf(str, 7, "%d", s); //Convert int to string: itoa or snprintf
//itoa (j, n, 10);
//printf ("Decimal: %s\n", n);
string_read=TRUE;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
}
}
void * motor()
{
while (1)
{
pthread_mutex_lock(&lock);
while (!string_read)
pthread_cond_wait(&cond,&lock);
char *s = "s"; //How to receive the string value from joystick()?
int val = atoi(s);
printf ("Integer value of string is %d\n", val);
char buffer [MAX_LEN];
system ("./SmcCmd --resume"); //WORKING
snprintf (buffer, MAX_LEN, "./SmcCmd --speed %d", val); //WORKING
int status = system(buffer); //WORKING
string_read=FALSE;
pthread_mutex_unlock(&lock);
}
}
int main ()
{
int status;
pthread_t tj, tm;
pthread_create(&tj, NULL, joystick, NULL);
pthread_create(&tm, NULL, motor, NULL);
pthread_join(tj, NULL);
pthread_join(tm, NULL);
return 0;
}

Multi-threaded random number generator keeps getting a SegFault at initstate_r function

I'm trying to develop a program in C that will generate a given number of random integers. It is supposed to use a given number of threads to speed this up. I found out that the regular random function won't work with threads and am now using random_r instead. I keep getting a SegFault at the initstate_r function, which doesn't make sense because I'm trying to initialize variables, not access them. Can anyone tell me what I'm doing wrong here? (The initstate_r function needs to stay in the generateRandomNumbers function.)
Here is the code:
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h> // must include stdio for pvm3.h to compile correctly
#include <sys/times.h> /* for times system call */
#include <sys/time.h> /* for gettimeofday system call */
#include <pthread.h>
/*#define DEBUG 1*/
#define RANDOM_SEED 12345678
//The main work routine
//void generateRandomNumbers(long long);
void *generateRandomNumbers(void *);
double getMilliSeconds();
/* The main work routine */
//void generateRandomNumbers(long long int count)
void *generateRandomNumbers(void *arg)
{
struct random_data buf;
int32_t result;
char rand_statebuf;
printf("hold 1\n");
// This is the function that gives me a SegFault
initstate_r(RANDOM_SEED, &rand_statebuf, 128, &buf);
printf("hold 2\n");
long long int* count = (long long int*) arg;
//printf("Count for thread ID# %ld is %lld\n", pthread_self(), *count);
long long int i;
//long int x;
srandom_r(RANDOM_SEED, &buf);
for (i = 0; i < *count; i++) {
random_r(&buf, &result);
#ifdef DEBUG
printf("%ld\n", result);
#endif
}
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
long long int count, newCount;
int numThreads;
//pthread_t *tids;
double timeStart = 0;
double timeElapsed = 0;
if (argc < 3) {
fprintf(stderr, "Usage: %s <n>\n" ,argv[0]);
exit(1);
}
sscanf(argv[1],"%lld",&count); /* lld for long long int */
sscanf(argv[2],"%d",&numThreads);
pthread_t tids[numThreads];
newCount = count/numThreads;
timeStart = getMilliSeconds(); //And we are off
int i;
for (i=0; i<numThreads; i++)
{
pthread_create(&tids[i], NULL, generateRandomNumbers, (void *) &newCount);
//pthread_join(tids[i], NULL);
}
int j;
for (j=0; j<numThreads; j++)
{
pthread_join(tids[j], NULL);
}
//generateRandomNumbers(count);
printf("generated %lld random numbers\n", count);
timeElapsed = getMilliSeconds() - timeStart;
printf("Elapsed time: %lf seconds\n",(double)(timeElapsed/1000.0));
fflush(stdout);
exit(0);
}
The problem is, initstate_r's second param is supposed to be a char*,
You do:
char rand_statebuf;
printf("hold 1\n");
// This is the function that gives me a SegFault
initstate_r(RANDOM_SEED, &rand_statebuf, 128, &buf);
You pass it a pointer to 1 character which meets the requirement for a character pointer, however you need much more space than just one character. It should be:
char rand_statebuf[128];
initstate_r(RANDOM_SEED,rand_statebuf,sizeof(rand_statebuf),&buf);

Resources