c passing several arguments to threads - c

when i create a thread, i want to pass several arguments.
So i define in a header file the following:
struct data{
char *palabra;
char *directorio;
FILE *fd;
DIR *diro;
struct dirent *strdir;
};
In a .c file i do the following
if (pthread_create ( &thread_id[i], NULL, &hilos_hijos, ??? ) != 0){
perror("Error al crear el hilo. \n");
exit(EXIT_FAILURE);
}
How do i pass all this arguments to the threads. I though about:
1) first use malloc to allocate memory for this structure and then give each parameter a value:
struct data *info
info = malloc(sizeof(struct data));
info->palabra = ...;
2) define
struct data info
info.palabra = ... ;
info.directorio = ...;
and then, how do i access these parameters in the thread
void thread_function ( void *arguments){
???
}
thanks in advance

Here is a working (and relatively small) example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
/*
* To compile:
* cc thread.c -o thread-test -lpthread
*/
struct info {
char first_name[64];
char last_name[64];
};
void *thread_worker(void *data)
{
int i;
struct info *info = data;
for (i = 0; i < 100; i++) {
printf("Hello, %s %s!\n", info->first_name, info->last_name);
}
}
int main(int argc, char **argv)
{
pthread_t thread_id;
struct info *info = malloc(sizeof(struct info));
strcpy(info->first_name, "Sean");
strcpy(info->last_name, "Bright");
if (pthread_create(&thread_id, NULL, thread_worker, info)) {
fprintf(stderr, "No threads for you.\n");
return 1;
}
pthread_join(thread_id, NULL);
return 0;
}

Do not use option #2. The data structure could be overwritten (explicitly, for instance using the same structure to start another thread, or implicitly, for instance having it overwritten on the stack). Use option #1.
To get at your data, at the start of your thread, do
struct data *info = (struct data*)arguments;
Then access info as normal. Make sure to free it when the thread is done (or, as I prefer, have the caller free it after joining with the thread).

Create a pointer to a struct like you do in the first case above:
//create a pointer to a struct of type data and allocate memory to it
struct data *info
info = malloc(sizeof(struct data));
//set its fields
info->palabra = ...;
info->directoro = ...;
//call pthread_create casting the struct to a `void *`
pthread_create ( &thread_id[i], NULL, &hilos_hijos, (void *)data);

1) you need to use malloc and not define like below
struct data *info;
info = (struct data *)malloc(sizeof(struct data));
and pass the pointer of the structure in ptherad call as below
pthread_create ( &thread_id[i], NULL, &thread_fn, (void *)info );
2) you can access them in thread function as below
void thread_function ( void *arguments){
struct data *info = (struct data *)arguments;
info->....
}

Related

Why does my linked list in shared memory always lead to a segfault?

I have the following simple application. This has been stripped of error handling and such, to be, well, a minimal complete example.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
//#define SHM_SIZE 1024 /* make it a 1K shared memory segment */
struct node
{
int x;
struct node *next;
};
int main(int argc, char *argv[])
{
struct node *root[argc+1];
if (argc > 1)
{
int i;
root[0]= (struct node *) malloc( sizeof(struct node) );
for (i=0; i<argc-1; i++)
{
root[i]->x = (int)(*argv[i+1]-'0');
//root[i]->next=&root[i]+sizeof(struct node);
root[i+1]=(struct node *) malloc( sizeof(struct node) ); //Okay, wastes a few ops
root[i]->next=root[i+1];
}
free(root[i]->next);
root[i]=NULL;
}
key_t key;
int shmid;
struct node *data;
key = ftok("test1", 'O');
shmid = shmget(key, (size_t)(sizeof(struct node)*1000), 0777 | IPC_CREAT);
data = shmat(shmid, (void *)0, 0);
printf("%p", &data);
if (argc != 1)
{
int z=0;
for (z=0;z<argc-1;z++){
*(data+sizeof(struct node)*z)=*root[z];
if (z) (data+sizeof (struct node)*(z-1))->next=(data+sizeof (struct node)*z);
}
(data+z)->next=0;
}
if (argc)
{
printf("This is the routine that will retrieve the linked list from shared memory when we are done.");
struct node *pointer;
pointer=data;
printf("%p", data);
while (pointer->next != 0)
{
printf("\n Data: %i",pointer->x);
pointer=pointer->next;
}
}
/* detach from the segment: */
if (shmdt(data) == -1)
{
perror("shmdt");
exit(1);
}
return 0;
}
Basically, whenever I try to access the shared memory from the process that created it, my output looks good. Every time I open the shared memory from a process that did NOT create it (argc=1) then the program segfaults. I would appreciate it if someone could tell me why!
Each time you attach a shared memory segment in a process, it is attached at some address which has no relation to the address in any other process that attaches the shared memory. So the pointers in the shared memory, while they point at other objects in the shared memory in the original (creating) process's shared memory, do not point at the shared memory in any other process.
The net result -- if you want to store data structures in the shared memory, those data structures can't contain any pointers if you want them to work reasonably. If you want pointer-like behavior, you instead need to use indexes into the shared momory, possibly as an array. So you could do something like:
struct node {
int x; /* value */
int next; /* index of the next node */
};
struct node *data = shmat(...); /* shm was sized for 1000 nodes */
/* link all of the data objects into a linked list, starting from data[0] */
for (int i = 0; i < 1000; ++i) {
data[i].next = i+1;
}
data[999].next = -1; /* using -1 for "NULL" as 0 is a valid index; */
for (int i = 0; i >= 0; i = data[i].next) {
/* iterating down the linked list */
data[i].x = 0;
}

Thread handler with more than one argument [duplicate]

I need to pass multiple arguments to a function that I would like to call on a separate thread. I've read that the typical way to do this is to define a struct, pass the function a pointer to that, and dereference it for the arguments. However, I am unable to get this to work:
#include <stdio.h>
#include <pthread.h>
struct arg_struct {
int arg1;
int arg2;
};
void *print_the_arguments(void *arguments)
{
struct arg_struct *args = (struct arg_struct *)args;
printf("%d\n", args -> arg1);
printf("%d\n", args -> arg2);
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t some_thread;
struct arg_struct args;
args.arg1 = 5;
args.arg2 = 7;
if (pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0) {
printf("Uh-oh!\n");
return -1;
}
return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}
The output for this should be:
5
7
But when I run it I actually get:
141921115
-1947974263
Anyone know what I'm doing wrong?
Because you say
struct arg_struct *args = (struct arg_struct *)args;
instead of
struct arg_struct *args = arguments;
use
struct arg_struct *args = (struct arg_struct *)arguments;
in place of
struct arg_struct *args = (struct arg_struct *)args;
main() has it's own thread and stack variables. either allocate memory for 'args' in the heap or make it global:
struct arg_struct {
int arg1;
int arg2;
}args;
//declares args as global out of main()
Then of course change the references from args->arg1 to args.arg1 etc..
Use:
struct arg_struct *args = malloc(sizeof(struct arg_struct));
And pass this arguments like this:
pthread_create(&tr, NULL, print_the_arguments, (void *)args);
Don't forget free args! ;)
I have the same question as the original poster, Michael.
However I have tried to apply the answers submitted for the original code without success
After some trial and error, here is my version of the code that works (or at least works for me!). And if you look closely, you will note that it is different to the earlier solutions posted.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct arg_struct
{
int arg1;
int arg2;
} *args;
void *print_the_arguments(void *arguments)
{
struct arg_struct *args = arguments;
printf("Thread\n");
printf("%d\n", args->arg1);
printf("%d\n", args->arg2);
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t some_thread;
args = malloc(sizeof(struct arg_struct) * 1);
args->arg1 = 5;
args->arg2 = 7;
printf("Before\n");
printf("%d\n", args->arg1);
printf("%d\n", args->arg2);
printf("\n");
if (pthread_create(&some_thread, NULL, &print_the_arguments, args) != 0)
{
printf("Uh-oh!\n");
return -1;
}
return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}
The args of print_the_arguments is arguments, so you should use:
struct arg_struct *args = (struct arg_struct *)arguments.
struct arg_struct *args = (struct arg_struct *)args;
--> this assignment is wrong, I mean the variable argument should be used in this context.
Cheers!!!
In this code's thread creation, the address of a function pointer is being passed.
The original
pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0
It should read as
pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)
A good way to remember is that all of this function's arguments should be addresses.
some_thread is declared statically, so the address is sent properly using &.
I would create a pthread_attr_t variable, then use pthread_attr_init() on it and pass that variable's address. But, passing a NULL pointer is valid as well.
The & in front of the function label is what is causing the issue here. The label used is already a void* to a function, so only the label is necessary.
To say != 0 with the final argument would seem to cause undetermined behavior. Adding this means that a boolean is being passed instead of a reference.
Akash Agrawal's answer is also part of the solution to this code's problem.
Since asking the same question but for C++ is considered a duplicate I might as well supply C++ code as an answer.
// hello-2args.cpp
// https://stackoverflow.com/questions/1352749
#include <iostream>
#include <omp.h>
#include <pthread.h>
using namespace std;
typedef struct thread_arguments {
int thrnr;
char *msg;
} thargs_t;
void *print_hello(void *thrgs) {
cout << ((thargs_t*)thrgs)->msg << ((thargs_t*)thrgs)->thrnr << "\n";
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
cout << " Hello C++!\n";
const int NR_THRDS = omp_get_max_threads();
pthread_t threads[NR_THRDS];
thargs_t thrgs[NR_THRDS];
for(int t=0;t<NR_THRDS;t++) {
thrgs[t].thrnr = t;
thrgs[t].msg = (char*)"Hello World. - It's me! ... thread #";
cout << "In main: creating thread " << t << "\n";
pthread_create(&threads[t], NULL, print_hello, &thrgs[t]);
}
for(int t=0;t<NR_THRDS;t++) {
pthread_join(threads[t], NULL);
}
cout << "After join: I am always last. Byebye!\n";
return EXIT_SUCCESS;
}
Compile and run by using one of the following:
g++ -fopenmp -pthread hello-2args.cpp && ./a.out # Linux
g++ -fopenmp -pthread hello-2args.cpp && ./a.exe # MSYS2, Windows

Passing 2 structures as parameters to pthread in C

Can I pass two structures as parameters to a pthread in a C program. I need to do something like this:
void *funtion1(void *pass_arg, void *pass_arg1)
{
struct thread_arg *con = pass_arg;
struct thread_arg1 *con = pass_arg1;
//necessary code
}
int main()
{
pthread_t threaad;
//necessary code
while(1)
{
th1 = pthread_create(&threaad, NULL, function1, (void *)&pass_arg, (void*)&pass_arg);
//necessary codes
}
pthread_exit(NULL);
return 1;
}
I mean is there any way I can pass two structures into the same function while using pthread? Operating Platform: Linux.
Not directly, because the functions in libpthread accept only one user data argument. But that should be enough, shouldn't it?
struct user_struct {
void *p1, *p2;
} arg = { &arg1, &arg2 };
pthread_create(&tid, NULL, threadfunc, &arg);
Also, don't cast pointers to void *, it's superfluous, dangerous and decreases readability.
Define a new struct type which contains the two original types as members. Call it something meaningful like thread_args.
I solved the problem by nesting the two structures into a single structure like this:
struct s1
{
//variables
};
struct s2
{
//variables
}
struct s3
{
struct s1 ss1;
struct s2 ss2;
}
void *funtion1(void *pass_arg)
{
struct s3 *con = pass_arg;
//necessary code
}
int main()
{
//code
th1 = pthread_create(&thread, NULL, function1, (void *)&pass_arg);
}

How to work with pointer to pointer to a struct?

I have a bit of a problem. I am barely starting out with C, (comming from a C# background) and I am having problem with double pointers.
I have a structure as follows:
#ifndef __PROCESSINFO_H
#define __PROCESSINFO_H
struct ProcessInfo
{
int ProcesId;
int Priority;
int ExecutionTime;
int EllapsedTime;
char* ProcessName;
};
struct ProcessInfo *ProcessInfo_Allocate(int processId, char *processName, int priority, int executionTime);
void ProcessInfo_ToString(struct ProcessInfo *processInfo);
void ProcessInfo_Dispose(struct ProcessInfo *processInfo);
#endif
Implementation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "processinfo.h"
struct ProcessInfo *ProcessInfo_Allocate(int processId, char *processName, int priority, int executionTime)
{
struct ProcessInfo *processInfo;
processInfo = (struct ProcessInfo *)malloc(sizeof(struct ProcessInfo));
processInfo->ProcessId = processId;
processInfo->ProcessName = processName;
processInfo->Priority = priority;
processInfo->ExecutionTime = executionTime;
processInfo->EllapsedTime = 0;
return processInfo;
}
void ProcessInfo_ToString(struct ProcessInfo *processInfo)
{
printf(" %6i %6i %10i %10i, %25s", processInfo->ProcessId, processInfo->Priority, processInfo->ExecutionTime, processInfo->EllapsedTime, processInfo->ProcessName);
}
void ProcessInfo_Dispose(struct ProcessInfo *processInfo)
{
if(processInfo != NULL)
{
if(processInfo->ProcessName != NULL)
{
free(processInfo->ProcessName);
}
free(processInfo);
}
}
so now I have to manage a whole lot of ProcessInfo instances. I wrote another structure which would hold a pointer to a pointer to the ProcessInfo sturcture because i thought that I can increase and decrease it in size as needed (without too much hassle);
#ifndef __SCHEDULER_H
#define __SCHEDULER_H
struct Scheduler
{
struct ProcessInfo** Processes;
};
struct Scheduler* Scheduler_Allocate(void);
#endif
So the question is how do I initialize the **Processes member inside the Scheduler_Allocate method? How do I add stuff to it?
struct Scheduler s;
s.Processes = malloc(sizeof(struct ProcessInfo*) * size);
s.Processes[0] = ProcessInfo_Allocate(...);
// Add more items:
s.Processes = realloc(malloc(sizeof(struct ProcessInfo*) * (size + 1));
s.Processes[size] = ProcessInfo_Allocate(...);
size++;
Also see my example here:
Array of C structs
You don't need a double pointer to increase/decrease the size. Just use a normal pointer and realloc.
struct ProcessInfo* processes = malloc(sizeof(struct ProcessInfo) * 2);
struct ProcessInfo* processes_tmp;
if (!processes) {
/* bail */
}
/* do whatever with processes[0] and [1] */
processes_tmp = processes;
processes = realloc(processes, sizeof(struct ProcessInfo) * 5);
if (!processes) {
free(processes_tmp);
/* bail */
}
/* processes[0] and [1] are unchanged, and [2] [3] and [4] are now valid */
Then instead of having a ProcessInfo_Allocate, you could create a ProcessInfo_Init that would do most of the same except not allocating the memory:
int ProcessInfo_Init(struct ProcessInfo *pi, int processId, char *processName, int priority, int executionTime)
{
if (!pi) {
return -1;
}
pi->ProcessId = processId;
pi->ProcessName = processName;
pi->Priority = priority;
pi->ExecutionTime = executionTime;
pi->EllapsedTime = 0;
return 0;
}
size_t size = 10;//or what ever is the number of processes
struct ProcessInfo * process = (struct ProcessInfo *)malloc(size * sizeof(struct ProcessInfo));
if(!process)
//perhaps stop program? Do something
Processes = &process;
//later on
int i;
for(i = 0; i < size; i++)
{
printf("Process id =%d",Processes[i]->ProcesId);
etc
}
Pointer to pointer is initialized as array of pointers. So call malloc(count * sizeof(ProcessInfo*)) to initialize it. This way you get array of pointers to ProcessInfo. Then call malloc(sizeof(ProcessInfo)) many times to create particular ProcessInfo structures and put pointers to them to the array.
Also, user470379 is right that you don't need pointer to pointer just to change number of items in your array. But your idea is actually not bad either, you can stay with it if you want.
Also, since you are familiar with C#, I would recommend you to start with writing something like ArrayList in C. Then you can use it in many situations (like this one).
First change your definition to:
typedef struct Scheduler {
struct ProcessInfo** Processes;
} Scheduler;
Then something like this:
Scheduler *s;
s = malloc(sizeof(Scheduler));
if (s == NULL) {
exit(-1);
}
s = memset(s, 0, sizeof(Scheduler));
/* Or enter your own memory allocation stuff here */
i = 0; /* Or use some other number */
s->Processes[i] = someProcessInfo;

Multiple arguments to function called by pthread_create()?

I need to pass multiple arguments to a function that I would like to call on a separate thread. I've read that the typical way to do this is to define a struct, pass the function a pointer to that, and dereference it for the arguments. However, I am unable to get this to work:
#include <stdio.h>
#include <pthread.h>
struct arg_struct {
int arg1;
int arg2;
};
void *print_the_arguments(void *arguments)
{
struct arg_struct *args = (struct arg_struct *)args;
printf("%d\n", args -> arg1);
printf("%d\n", args -> arg2);
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t some_thread;
struct arg_struct args;
args.arg1 = 5;
args.arg2 = 7;
if (pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0) {
printf("Uh-oh!\n");
return -1;
}
return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}
The output for this should be:
5
7
But when I run it I actually get:
141921115
-1947974263
Anyone know what I'm doing wrong?
Because you say
struct arg_struct *args = (struct arg_struct *)args;
instead of
struct arg_struct *args = arguments;
use
struct arg_struct *args = (struct arg_struct *)arguments;
in place of
struct arg_struct *args = (struct arg_struct *)args;
main() has it's own thread and stack variables. either allocate memory for 'args' in the heap or make it global:
struct arg_struct {
int arg1;
int arg2;
}args;
//declares args as global out of main()
Then of course change the references from args->arg1 to args.arg1 etc..
Use:
struct arg_struct *args = malloc(sizeof(struct arg_struct));
And pass this arguments like this:
pthread_create(&tr, NULL, print_the_arguments, (void *)args);
Don't forget free args! ;)
I have the same question as the original poster, Michael.
However I have tried to apply the answers submitted for the original code without success
After some trial and error, here is my version of the code that works (or at least works for me!). And if you look closely, you will note that it is different to the earlier solutions posted.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct arg_struct
{
int arg1;
int arg2;
} *args;
void *print_the_arguments(void *arguments)
{
struct arg_struct *args = arguments;
printf("Thread\n");
printf("%d\n", args->arg1);
printf("%d\n", args->arg2);
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t some_thread;
args = malloc(sizeof(struct arg_struct) * 1);
args->arg1 = 5;
args->arg2 = 7;
printf("Before\n");
printf("%d\n", args->arg1);
printf("%d\n", args->arg2);
printf("\n");
if (pthread_create(&some_thread, NULL, &print_the_arguments, args) != 0)
{
printf("Uh-oh!\n");
return -1;
}
return pthread_join(some_thread, NULL); /* Wait until thread is finished */
}
The args of print_the_arguments is arguments, so you should use:
struct arg_struct *args = (struct arg_struct *)arguments.
struct arg_struct *args = (struct arg_struct *)args;
--> this assignment is wrong, I mean the variable argument should be used in this context.
Cheers!!!
In this code's thread creation, the address of a function pointer is being passed.
The original
pthread_create(&some_thread, NULL, &print_the_arguments, (void *)&args) != 0
It should read as
pthread_create(&some_thread, NULL, print_the_arguments, (void *) &args)
A good way to remember is that all of this function's arguments should be addresses.
some_thread is declared statically, so the address is sent properly using &.
I would create a pthread_attr_t variable, then use pthread_attr_init() on it and pass that variable's address. But, passing a NULL pointer is valid as well.
The & in front of the function label is what is causing the issue here. The label used is already a void* to a function, so only the label is necessary.
To say != 0 with the final argument would seem to cause undetermined behavior. Adding this means that a boolean is being passed instead of a reference.
Akash Agrawal's answer is also part of the solution to this code's problem.
Since asking the same question but for C++ is considered a duplicate I might as well supply C++ code as an answer.
// hello-2args.cpp
// https://stackoverflow.com/questions/1352749
#include <iostream>
#include <omp.h>
#include <pthread.h>
using namespace std;
typedef struct thread_arguments {
int thrnr;
char *msg;
} thargs_t;
void *print_hello(void *thrgs) {
cout << ((thargs_t*)thrgs)->msg << ((thargs_t*)thrgs)->thrnr << "\n";
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
cout << " Hello C++!\n";
const int NR_THRDS = omp_get_max_threads();
pthread_t threads[NR_THRDS];
thargs_t thrgs[NR_THRDS];
for(int t=0;t<NR_THRDS;t++) {
thrgs[t].thrnr = t;
thrgs[t].msg = (char*)"Hello World. - It's me! ... thread #";
cout << "In main: creating thread " << t << "\n";
pthread_create(&threads[t], NULL, print_hello, &thrgs[t]);
}
for(int t=0;t<NR_THRDS;t++) {
pthread_join(threads[t], NULL);
}
cout << "After join: I am always last. Byebye!\n";
return EXIT_SUCCESS;
}
Compile and run by using one of the following:
g++ -fopenmp -pthread hello-2args.cpp && ./a.out # Linux
g++ -fopenmp -pthread hello-2args.cpp && ./a.exe # MSYS2, Windows

Resources