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;
}
Related
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;
}
I am having some trouble understanding this code since I am new to pthread programming. From what I understand, we create N threads and execute the run function on them, which only prints the thread number. Am I missing something?
Is there any advantage of using snprintf (with buffers) over printf in this particular case? Could this program be improved any further?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static int N = 5;
static void* run(void *arg)
{
int *i = (int *) arg;
char buf[123];
snprintf(buf, sizeof(buf), "thread %d", *i);
return buf;
}
int main(int argc, char *argv[])
{
int i;
pthread_t *pt = NULL;
for (i = 0; i < N; i++) {
pthread_create(pt, NULL, run, &i);
}
return EXIT_SUCCESS;
}
First of all, your threads return garbage. Deferencing the pointer returned would be Undefined Behaviour because it points to storage that no longer exists after the function returns. Good thing nothing used the pointer.
Next, the threads don't print anything because snprintf outputs to an array, not stdout.
Furthermore, the threads would print garbage if you switched to printf because the same pointer is passed to to all threads.
And that's assuming the threads have a chance to run since main doesn't wait for the threads to finish. You gotta join them.
Fixed:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define N 5
static void *run(void *arg) {
size_t job = *(size_t*)arg;
printf("Job %zu\n", job);
return NULL;
}
int main(int argc, char *argv[]) {
size_t jobs[N];
pthread_t threads[N];
for (size_t i=0; i<N; ++i) {
jobs[i] = i;
pthread_create(threads+i, NULL, run, jobs+i);
}
for (size_t i=0; i<N; ++i) {
pthread_join(threads[i]);
}
return EXIT_SUCCESS;
}
It's also common to pass an integer cast to a pointer.
#include <inttypes.h>
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
static void *run(void *arg) {
size_t job = *(uintptr_t*)arg;
printf("Job %" PRIuPTR "\n", job);
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t threads[N];
for (uintptr_t i=0; i<N; ++i) {
pthread_create(threads+i, NULL, run, (void*)i);
}
for (uintptr_t i=0; i<N; ++i) {
pthread_join(threads[i]);
}
return EXIT_SUCCESS;
}
Hi I am having trouble passing an integer argument to a thread and calculation the factorial using that integer. Here is my code.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <ctype.h>
void * factorial(void * number) {
int factorial = 1;
int counter = 1;
int newnum = *((int*)number);
printf("%d", newnum);
pthread_exit(NULL);
}
void * sumup( void * number) {
}
int main(int argc, char *argv[]) {
if(argc != 2) {
printf("Argument number error\n");
exit(1);
}
pthread_t thread1;
pthread_t thread2;
int i;
for(i = 0; i < argc; i++){
printf(argv[i]);
printf("\n");
}
int rc;
void * t = argv[1];
rc = pthread_create(&thread1, NULL, factorial, (void*)t );
if (rc != 0) {
printf("There was an error creating the thread\n");
exit(1);
}
pthread_exit(NULL);
exit(0);
}
Right now i am just trying to print the integer sent to get it working properly but here is my output:
./Task1
5
1162608693
It should printing out 5 instead of 1162608693
argv table stores pointers to characters. By doing:
void * t = argv[1];
int newnum = *((int*) t );
what you are trying to print is integer value of string "5". You are passing address of string:
'5' '\0'
casted to pointer to int, therefore you try to read integer value of first sizeof(int) bytes which yields:
5 0 [and you read sizeof(int)-2 bytes out of range]
which results in undefined behavior.
SOLUTION
To convert to integer a string passed as argument to your program use atoi or strtol which does better error checking.
I'm trying to edit this code to work with ints parameters:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
void* worker (void* param) {
int* nr = (int *) param;
printf ("I got: %d\n",nr);
}
int main (int argc, int *argv[])
{
pthread_t th;
int i;
for(i=1;i<argc;i++){
pthread_create (&th, NULL, worker,(void*)argv[i]);
pthread_join (th, NULL);
}
}
This is not working, smth about pointers, I don't understand. Can anyone explain me? I don't want to use "atoi" function.
For number 5 and 2 I get: -1078000975,-1078000973 and a warning:
11:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf ("I got: %d\n", nr);
^
A few issues:
argv should be written char * argv[], not int * argv[].
Your (void *) cast in your pthread_create() call is unnecessary.
Your thread function should return a void *.
atoi(), or its more capable cousin, strtol(), is exactly what you're looking for, here. You can either use them, or convert your strings manually, which is suboptimal.
Here's a working version:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void * worker (void * param)
{
char * numstr = param, * endptr;
long num = strtol(numstr, &endptr, 0);
if ( *endptr ) {
printf("Invalid number.\n");
}
else {
printf ("I got: %ld\n", num);
}
return NULL;
}
int main (int argc, char *argv[])
{
pthread_t th;
for ( int i = 1; i < argc; ++i ) {
pthread_create (&th, NULL, worker, argv[i]);
pthread_join (th, NULL);
}
return 0;
}
and some sample output:
paul#horus:~/src/sandbox$ ./trd 5 haha 10
I got: 5
Invalid number.
I got: 10
paul#horus:~/src/sandbox$
If the arguments you recieve are smaller than 10, you can do this:
pthread_create (&th, NULL, worker,(void*)(argv[i][0]-'0'));
This can be done because ASCII numbers begin at 48 ('0' value). So if you receive a '7' (55 ascii number), you can subtract the '0' to get it: 55-48=7.
If the arguments can be 10 or greater, you must use atoi or a self-implementation of that function, as you can not cast from char* to int in C.
There is another problem with your code, you try to print an int*, which is only a variable that contains a memory address. You should recieve it as an int:
void* worker (void* param)
{
int nr = (int) param;
printf ("I got: %d\n",nr);
}
EDIT:
So your code should look like this:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
void* worker (void* param) {
int nr = (int) param;
printf ("I got: %d\n",nr);
}
int main (int argc, char *argv[])
{
pthread_t th;
int i;
for(i=1;i<argc;i++){
pthread_create (&th, NULL, worker,(void*)(argv[i][0]-'0'));
pthread_join (th, NULL);
}
}
It works for me...
You should pass the pointer to the string and then manipulate it.
pthread_create (&th, NULL, worker, argv[i]); //cast is not required
void* worker (void* param) {
char* nr = param ;
Now you got your string in the thread. Get the first character, and convert it to an integer.
int n = nr[0]-'0' ;
printf ("I got: %d\n",n);
}
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);