Passing an array to pthread_create - c

So i was trying to make a program that creates a thread in c whose job is to find the maximum of 2 given numbers. The first program that i wrote (named askisi.c) was the following:
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
int max;
void *max_of_two(void *param);
int main(int argc , char *argv[])
{
pthread_t tid;
pthread_attr_t attr;
if (argc != 3)
{
fprintf(stderr,"You have to give 2 numbers... \n");
return -1;
}
pthread_attr_init(&attr);
pthread_create(&tid,&attr,max_of_two,argv);
pthread_join(tid,NULL);
printf("max = %d\n",max);
}
void *max_of_two(void *param)
{
if(atoi(*param[1]) >= atoi(*param[2]))
max = atoi(*param[1]);
else
max = atoi(*param[2]);
pthread_exit(0);
}
But using gcc in Linux i got these errors:
Now after a lot of research i found that my the function max_of_two should be written like this:
void *max_of_two(void *param)
{
char **arguments = (char**)param;
if(atoi(arguments[1]) >= atoi(arguments[2])){
max = atoi(arguments[1]);}
else
max = atoi(arguments[2]);
pthread_exit(0);
}
The first problem is that i didn't find any explanation on why my first program didn't work. The second one is that i didn't find an understandable explanation on what the instruction char **arguments = (char**)param; actually does.

void is not a real type, and in that context it means the function expect any type and its up to the programmer to decide which is done with casting.
So by doing char **arguments = (char**)param; you casted param into char ** and assigned that cast to the variable arguments.

Related

Multithreading in C, Fibonacci Program

I have newly started studying operating systems and creating processes/threads on Linux system by using C programming language(thats what is expected us to use) but I have some problems on the code that I've been trying to write:
Here is my code written on an Ubuntu system:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
int total = 0;
typedef struct
{
int start;
int end;
int threadNo;
}THREAD_PARAMETERS;
void *work(void *parameters);
int threadCount;
int main(int argc, char* argv[])
{
printf("please give the number of terms you want to diplay..");
scanf("%d", &threadCount);
pthread_t tid[threadCount];
pthread_attr_t attr[threadCount];
THREAD_PARAMETERS* lpParameter;
int n;
lpParameter = malloc(sizeof(THREAD_PARAMETERS)* threadCount);
int i=0;
for(i=0; i<threadCount; i++)
{
lpParameter[i].start = 0;
lpParameter[i].end = 1;
lpParameter[i].threadNo = i + 1;
pthread_attr_init(&attr[i]);
pthread_create(&tid[i],&attr[i],work,&lpParameter[i]);
}
for(i=0; i<threadCount; i++)
{
pthread_join(tid[i],NULL);
}
return 1;
}
void fibonacci(int a)
{
int prev_term = 0, current_term = 1, next_term = 0;
if(a==0){
printf("%d\n",prev_term);
}
else if(a==1){
next_term=current_term+prev_term;
printf("%d\n",current_term);
prev_term=current_term;
current_term=next_term;
void *work(void * parameters)
{
THREAD_PARAMETERS* param = (THREAD_PARAMETERS*)parameters;
fibonacci(threadCount);
pthread_exit(0);
}
The problem is the program counts with the threadCount variable but what the program prints is just threadCount times zeros.
And the main question is how can I make each of the threads write "only one term" of the Fibonacci series depending on the number of terms (which is at the same time the number of threads) entered by the user? Is there any other more logical way to implement this kind of program?
You are using lpParameter[i] as the argument to each thread's work, but then ignore its contents when calling fibonacci.

How can I have a shared counter in multithreading using structs?

I'm pretty new with multithreading and I was trying to increment a shared counter whithout using global variables, my goal is try to maximize the concurrency among the different threads and increment the variable until a number I give in arguments... Sorry if is a lame question, but I would like a help here, when I compile my code and run it i get a segmentation fault... I think the error is in the variable count that I create and the shared counter!
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex;
typedef struct {
long *cnt; /* pointer to shared counter */
long n; /* no of times to increment */
int nr;
pthread_t id; /* application-specific thread-id */
} targ_t;
void *sfun(void *arg) {
targ_t *est = (targ_t *) arg;
here:
pthread_mutex_lock(&mutex);
(*(est->cnt))++;
pthread_mutex_unlock(&mutex);
if(*(est->cnt)<est->n)
goto here;
return NULL;
}
int main(int argc, char *argv[]){
targ_t real[3];
int c=0;
long count=0;
real[0].cnt=&count;
pthread_mutex_init(&mutex, NULL);
for(c=0;c<3;c++){
real[c].n=atoi(argv[1]);
real[c].nr=c+1;
pthread_create(&real[c].id,NULL,&sfun,&real[c]);
}
for(c=0;c<3;c++){
pthread_join(real[c].id,NULL);
}
pthread_mutex_destroy(&mutex);
printf("OVERALL %lu\n", count);
return 0;
}
TY in advance.
There are a number of problems identified in the comments:
Writing out loops with a label here: and a goto here; is not a particularly good idea. There are occasions (some, but not many, occasions) when it is appropriate to use goto — this is not one of those rare occasions.
You don't actually validate that your code was given an argv[1] to convert; could it be that you forgot to pass that argument?
However, your primary problem is that you initialize real[0].cnt but you do not initialize real[1].cnt or real[2].cnt, so those threads are accessing who knows what memory — it might be that they're using null pointers, or they might be pointers to anywhere in memory, allocated or not, aligned or not, writable or not.
You're also missing <stdlib.h>
You're testing *(est->cnt) outside the scope of mutual exclusion.
This code fixes those and some other issues:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
typedef struct
{
long *cnt; /* pointer to shared counter */
long n; /* no of times to increment */
int nr;
pthread_t id; /* application-specific thread-id */
} targ_t;
static void *sfun(void *arg)
{
targ_t *est = (targ_t *)arg;
while (1)
{
pthread_mutex_lock(&mutex);
long cval = *est->cnt;
if (cval < est->n)
++*est->cnt;
pthread_mutex_unlock(&mutex);
if (cval >= est->n)
break;
}
return NULL;
}
int main(int argc, char *argv[])
{
targ_t real[3];
long count = 0;
if (argc != 2)
{
fprintf(stderr, "Usage: %s count\n", argv[0]);
return(EXIT_FAILURE);
}
for (int c = 0; c < 3; c++)
{
real[c].cnt = &count;
real[c].n = atoi(argv[1]);
real[c].nr = c + 1;
if (pthread_create(&real[c].id, NULL, &sfun, &real[c]) != 0)
break;
}
for (int c = 0; c < 3; c++)
pthread_join(real[c].id, NULL);
pthread_mutex_destroy(&mutex);
printf("OVERALL %lu\n", count);
return 0;
}
When run (for example, the program is pth59):
$ pth59 100
OVERALL 100
$
Before moving the test (now on cval) so that the read of *est->cnt was done inside the scope of the mutex, I got an output OVERALL 102 from the same command line. It is important to access shared variables with proper mutual exclusion, even if it is read-only access.

segmentation fault when converting (void*) to (int*)

I Wrote a multithreaded Pthread program that outputs prime numbers. This program works as follows: The user will run the program and will enter a number on the command line. The program will then create a separate thread that outputs all the prime numbers less than or equal to the number that the user entered.
The codes:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<math.h>
#include<string.h>
#define true 1
#define false 0
void* print_prime(void* arg)
{
int temp;
temp = *((int*)arg);//If I change it to 'temp = (int)arg',it runs well
int flag;
int i,j;
for(i = 2 ; i <= temp ; i++)
{
flag = true;
for(j = 2 ; j <= (int)sqrt(i) ; j++)
{
if(i%j == 0)
{flag = false;break;}
}
if(flag == true)
printf("%d\n",i);
}
}
int main(int argc,char *argv[])
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
if(argc != 2)
{perror("Parameters not enough");exit(0);}
int arg = atoi(argv[1]);
if(pthread_create(&tid,&attr,print_prime,(void*)arg))
{perror("Pthread created not successfully");exit(0);}
pthread_join(tid,NULL);
return 0;
}
when I wrote in the terminal as:./pthread_test 10,a segmentation fault(core dump) occurs.I use dmesg and addr2line -e pthread_test 0xxxxxx to locate the error.It turns to the instruction temp = *((int*)arg).
In pthread_create(&tid,&attr,print_prime,(void*)arg),I have converted arg to a void* type variable,why I was wrong for using *(int*)arg?
When you are passing the int as a pointer to void it does not alter the fact that you are sending the value of int and not its address. When you do *(int *) you are trying to obtain the content of the address(pointer to int) that you would obtain from the argument void. Obviously since you sent the value in int and not its address it will not work. Try maybe doing (void *)(&arg). But i think it is pointless castings. Why would you need to do *(int *)? Is there any particular reason? Do you understand the concept of pointer to void?
from the define of function
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
the type of fourth parameter is void*, but in your code, you write (void*)arg, so this is wrong.
you can change to:
pthread_create(&tid,&attr,print_prime,(void*)&arg)
The reason, arg in an int, and the value may be 100(just a example, your input value). If you use (void*)arg, that's means thay you want change 100(int type) to void* type. so your code fault, because your code read the memmory address 100. In should pass the address of value 100 to pthread_create, so you need write (void*)&arg.
Here you are passing the value
if(pthread_create(&tid,&attr,print_prime,(void*)arg))
Not the address. So you converted some value as void pointer and de-referencing it in another function. So this caused the problem.
if(pthread_create(&tid,&attr,print_prime,(void*)&arg)) is the correct one

Need help for int args (threads)

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

Reversing the strings from command line with threads in C - segmentation fault

I am new with threads.
I am trying to make a C program that reverses the string given from the command line and create a thread that does this for each one . When I run it gives me Segmentation fault .
Here is the code:
#include <stdio.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdlib.h>
#include <fcntl.h>
char* final[1000];
pthread_mutex_t *mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_t p[];
void *reverse(void* arg){
char* s[100];
char* temp;
int i;
strcpy(s,(char*)arg);
printf("S este %s",s);
for(i=0;i<=strlen(s)/2;i++){
strcpy(temp,s[i]);
strcpy(s[i],s[strlen(s)-i-1]);
strcpy(s[strlen(s)-i-1],temp);
}
sleep(1);
pthread_mutex_lock(&mutex);
strcat(final,s);
printf("Intermediar %s",s);
pthread_mutex_unlock(&mutex);
return NULL;
}
int main(int argc,char* argv[]) {
int i;
int n = argc;
strcpy(final,"");
for(i=1;i<n-2;i++){
pthread_create(&p[i],NULL,reverse,argv[i]);
}
for(i=1;i<n-2;i++){
pthread_join(p[i],NULL);
}
//printf("Sirul final este %s",final);
return 0;
}
Does anyone know a good site that could help me learn threads ?
Thanks !
char* final[1000];
is an array (with 1000 elements) of pointer to char, you want an array of char:
char final[1000];
the same problem with this array:
char* s[100];
temp is declared as a pointer, but you use it as an array with size 1
declare the mutex without the * ,remove the initialization and add in main:
pthread_mutex_init(&mutex, NULL);
you should also add a number to the array definition of pthread_t
You never initialize temp, so the call strcpy(temp, s[i]); causes undefined behavior.
Your treatment of s is also very confusing, the copying of arg (a string) into the memory used by s (an array of string pointers) is not valid. Just because you can cast away a warning doesn't mean you're doing something sensible.

Resources