How to pass multiple parameters to a thread function - c

I have created a function for a thread, but I want to pass multiple parameters to the function.
Here's my source code :
#include "work.h"
#include <stdio.h>
#include <unistd.h>
#include <pthread.h> // compile with -lpthread
int count = 20;
void* ChildProc(void* arg)
{
int i;
for(i = 1; i <= count; i++)
{
printf("%s:%d from thread <%x>\n", arg, i, pthread_self());
DoWork(i);
}
return NULL;
}
void ParentProc(void)
{
int i;
for(i = count / 2; i > 0; i--)
{
printf("Parent:%d from thread <%x>\n", i, pthread_self());
DoWork(i);
}
}
int main(void)
{
pthread_t child;
pthread_create(&child, NULL, ChildProc, "Child");
ParentProc();
pthread_join(child, NULL); // make child a non-daemon(foreground) thread
}
Now how do I pass multiple parameter to ChildProc() method?
One way is either pass an array or a structure. But what if I want to pass multiple variables without an array or a structure?

A fast and junk answer is to create a struct to hold all parameter and pass its pointer

One way is either pass a array or a structure.
That's the way. Pointer to a structure, that is.
what if I want to pass multiple variables withous a array or a structure?
Then you're out of luck. Array or a pointer to a structure is what you need.

You can pass a void * buffer stream and if you know the lengths then you can access them. Its similar to implementation of GArrays.
How do you create them?
void *buffer = malloc(sizeofelements);
memcpy(buffer,element1,sizeof element1);
memcpy(buffer+sizeof element1,element2, sizeof element2);
NOTE: The above is not a compilable C code. You need to work on it.
You can use something of the above sort.
You can later access the variables as you already know the size

Related

Global Array Issues Not Updating, C Programming

I have a program distributed across a number of files. There are a number of functions which need access to a global array. The issue I'm having is that I don't know the size of the array before the program starts. It opens up a file and then downloads a number of points, and then the array is created with a corresponding size. But for the array to be global, it needs to be declared outside of the main function i.e. before I know the number of points.
What I've tried to do right now is:
file1.c:
#include <stdio.h>
#include "file3.h"
int useful[];
int main()
{
int useful[10];
int i;
for (i = 0; i < 10; i++) {
useful[i] = i+1;
}
SPN();
return 0;
}
file2.c:
#include <stdio.h>
#include "file3.h"
void SPN() {
int i;
for (i = 0; i < 10; i++) {
printf("%i\n", useful[i]);
}
}
file3.h:
extern int useful[];
extern void SPN();
What I'm getting in output is just a bunch of 0s. At first I was thinking that the second int useful[... in file1.c creates a new array with a different internal name, but that doesn't seem to make any sense considering that no segmentation fault is triggered by SPN() when it tries to access memory outside the arrays bounds (if useful[] creates an array and isn't changed, it has default size 1 i.e. < 10). Help?
The int useful[10]; isn't initializing the global int useful[]; or anything like that. It's a new variable, and with the loop here
for (i = 0; i < 10; i++) {
useful[i] = i+1;
}
You're modifying the second useful without touching the global one. This is then discarded at the end of the function.
Instead have a global variable like this:
int *useful;
And initialize it this way:
useful = malloc(sizeof(int)*10);
The declaration of useful inside the main is shadowing the external one.
This means that the values that you think are inserting (in the main) in the global variable are actually going into the local variable.
Take a look at the following article about shadowing for more info.
It might also be interesting to look at scope rules in C.

Avoiding race condition using int to void * casting [duplicate]

This question already has answers here:
Pass integer value through pthread_create
(4 answers)
Closed 5 years ago.
I am trying to understand following code. This code has no race conditions, but I cannot understand.
#include <stdio.h>
#include <pthread.h>
void *foo(void *vargp) {
int id;
id = (int)vargp;
printf("Thread %d\n", id);
}
int main() {
pthread_t tid[2];
int i;
for (i = 0; i < 2; i++)
pthread_create(&tid[i], NULL, foo, (void *)i);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
How does the typecasting from int to void* work?
The race condition that is avoided is illustrated by this code, which is very similar to the original code, but subtly different, and the difference makes it incorrect:
/* Incorrect code! */
#include <pthread.h>
#include <stdio.h>
static void *foo(void *vargp)
{
int id = *(int *)vargp;
printf("Thread %d\n", id);
return 0;
}
int main(void)
{
pthread_t tid[2];
int i;
for (i = 0; i < 2; i++)
pthread_create(&tid[i], NULL, foo, &i); // Bad idea!
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
Since the function foo takes a void * argument, it seems logical to pass the address of the int to it. However, this has a major problem:
There is no guarantee which order the threads will execute, nor when, so there's no way to know which values the threads will see.
Indeed, when I ran this code the first time, both threads reported 2.
The way around this is to not pass the address of i but to pass i by value. However, the argument is still supposed to be a void *, so the code casts i to a void * before calling pthread_create(), and the thread function undoes the cast to retrieve the value.
When I'm doing this, I also use <stdint.h> to make the uintptr_t type available, and I use:
int id = (uintptr_t)vargp;
and
pthread_create(&tid[i], NULL, foo, (void *)(uintptr_t)i);
That looks excessive and/or obsessive, but the uintptr_t cast ensures the integer is the same size as a pointer to avoid the 'cast to pointer from integer of different size' compiler warning (which, since I tell the compiler to treat all warnings as errors, is necessary for me to get the code to compile at all).
If you do pass a pointer-to-data to the thread function (foo in this discussion), you must ensure that each thread you create gets its own copy of the data unless that data is meant to be identical in each thread.
You can see this technique at work in POSIX threads — unique execution.

Passing a struct to a function

So I am trying to pass my struct to a function and I am also trying to assign my variable to the struct, which does not seem to work. I don't know what's wrong with it either.
This is how my code looks:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ACE 1;
#define CardSize 52
#define colors 4
struct MyCards {
int *cards;
char *color[4];
};
void count(struct MyCards record);
int main() {
struct MyCards record;
count(record);
system("pause");
return 0;
}
void count(struct MyCards record) {
int i, j, f;
// I actually want to put this variable and the values into the struct, how do i do it?
char *color[4] = { "Diamon", "Heart", "Spade", "Clubs" };
record.cards = malloc(CardSize * sizeof(int));
for (f = 0; f < 4; f++) {
for (i = 0; i < 13; i++) {
record.cards[i] = (i % 13) + 1;
printf("%d of %s\n", record.cards[i], color[f]);
}
}
}
As you might see, the thing I commented out, I also want to put that variable AND the values that I have assign to it, but I dont know how to do that, would love some help there as well.
C uses pass-by-value. record inside count is a different variable to record in main - a copy is made when you call the function.
If you want main to see the changes you either need to return the changed object (in which case you wouldn't pass it in in the first place, in this example), or use pass-by-reference which you implement by passing a pointer to the object.
Returning the object would look like:
struct MyCard count(void)
{
struct myCard record;
// ... do stuff with record ...
return record;
}
Passing by reference would look like:
void count(MyCard *p_record)
{
// ... do stuff with (*p_record)
}
Also you want record.color[f] = color[f]; as the first line of the f loop. And (as discussed last time you posted about this code) you should be using string or char const *, not char *.
You have to pass a pointer to the struct in order to edit it, or you will edit the variable only in the stack of the function, which will be deleted once the function returns. Try passing &record to your function.
Also change your prototype: you have to accept a pointer to the struct.
When you have a pointer, to resolve the struct you have to use the -> operator. Let's do an example:
records->cards[i] = ...

Programming in UNIX - Semaphores,shared memory in C

I started a week ago understanding and working with semaphores and shared memory, and actually created this program, the problem is i cant find anything wrong with it i been looking at it for hours and everything seems correct.. The code compiles and i can create the build but when i execute it nothing happens ...
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <semaphore.h>
#define MAXCHILDS 4
#define MAX_SIZE 10
#define MAX_WRITES 4
typedef struct{
int m[MAX_SIZE][MAX_SIZE];
} matrix;
/*fork variables*/
pid_t child[MAXCHILDS];
/*semphores variables */
sem_t *empty, *full, * mutex;
/*share memory id*/
int shmid;
/*shared memory array pointer */
matrix * sh_mem;
/*pointer to matrix*/
int **p;
void init(){
/*create pointer to matrix*/
p = &sh_mem->m;
/*semaphores unlink and creation */
sem_unlink("EMPTY");
empty=sem_open("EMPTY",O_CREAT|O_EXCL,0700,MAX_WRITES);
sem_unlink("FULL");
full=sem_open("FULL",O_CREAT|O_EXCL,0700,0);
sem_unlink("MUTEX");
mutex=sem_open("MUTEX",O_CREAT|O_EXCL,0700,1);
/*initialize shared memory */
shmid = shmget(IPC_PRIVATE,sizeof(matrix),IPC_CREAT|0777);
/*map shared memory*/
sh_mem = (matrix*)shmat(shmid,NULL,0);
if(sh_mem== (matrix*)(-1)){
perror("shmat");
}
}
void writer(int ** m){
int i,k;
for(i = 0;i<MAX_SIZE;i++){
for(k= 0;k<MAX_SIZE;k++){
m[i][k] = 0;
}
}
}
void reader(int **m){
int i = 0;
int k = 0;
for(i = 0;i<MAX_SIZE;i++){
for(k= 0;k<MAX_SIZE;k++){
printf(m[i][k]);
}
printf("\n");
}
}
void terminate() {
sem_close(empty);
sem_close(full);
sem_close(mutex);
sem_unlink("EMPTY");
sem_unlink("FULL");
sem_unlink("MUTEX");
shmctl(shmid, IPC_RMID, NULL);
}
int main(int argc, char **argv)
{
int i;
init();
for(i = 0;i<MAXCHILDS;i++){
if((child[i]= fork()) < 0) // error occured
{
perror("Fork Failed");
exit(1);
}
if((child[i] =fork())==0){
writer(p);
exit(0);
}
}
/*father*/
reader(p);
wait(NULL);
terminate();
return 0;
}
The childs are supposed to write the the matrix in shared memory, and the father is supposed to read the shared memory array and the print the matrix.
Can you help me with this? Thanks for the help ...
You have several problems with your code.
You declare your p variable as follows:
int **p;
But the actual type of your array is int[MAXSIZE][MAXSIZE]. Although those can both be considered 2-dimensional arrays, they are not at all the same type and do not share the same structure in memory:
int ** is a pointer to a pointer to an integer. When used as a 2-dimensional array, it describes a 2-level array. The first level (dereferencing the pointer once) contains an array of int * pointers that each point to 1-dimensional arrays of integers.
int[MAXSIZE][MAXSIZE] is a flat 2-dimentional array. It is a single pointer to an array of MAXSIZE*MAXSIZE integers. It has the same memory structure as the 1-dimensional array int[MAXSIZE*MAXSIZE] even though it offers the convenience of using 2 levels of subscripts.
Passing around pointers to type[][]-style arrays in C is non-intuitive and very difficult to get right. I don't advise doing it. You might consider passing pointers to your matrix type instead. Still, it is possible to get it to work with this declaration:
typedef int array2d[MAX_SIZE][MAX_SIZE];
array2d *p;
then you have to change the m parameter in reader and writer to array2d *m instead or int **m and use it as *m instead of just m. This gets ugly. Like I said, consider using your matrix type instead.
This problem should have been caught by the compiler. It should have been giving you lots of type mismatch warnings. Make sure you always compile with gcc -Wall and aim to have your program compile with no errors and no warnings.
In init(), you set p too early. You should set it at the end of the function after sh_mem has been assigned, not at the start of the function.
You are fork()ing too many processes in your main() function, as discussed in comments above. You probably meant to call fork() only once each time through the for loop, not twice.
You don't wait until the writers have finished filling out the shared memory structure before you go ahead and read its contents.
Note that even if you move your wait(NULL) before the call to reader(), that's not enough, since wait(NULL) will only wait for one child process to complete, not all of them.
In general, you should compile your program with warnings enabled, pay attention to the warnings, and fix them before wondering what might be wrong with your program. If it still does something unexpected, you should run it under a debugger, use breakpoints, inspect variables, and try to take a look at what's happening. Using these two techniques, you probably would have solved your problem without needing to post here.

Define the size of a global array from the command line

I am doing an assignment where I need to use pthreads or semaphores to synchronize some processes which access some shared resource. Since all of our examples in class use a global variable as the shared resource I planned on doing the same thing, but I wanted to base the value of the shared resource on a command line argument. I know how to use command line arguments within my main method, but how do I define the size of a global array (the shared resource) based on a command line argument?
Update:
Wallyk's answer seems like it will work, but I'm still fuzzy on some of the finer details. See the example and comments...
#include <stdio.h>
void print_array(void);
int *array;
int count;
int main(int argc, char **argv){
int count = atoi(argv[1]);
array = malloc(count *sizeof(array[0]));
int i;
for(i = 0; i < count; i++){ /*is there anyway I can get the size of my array without using an additional variable like count?*/
array[i] = i;
}
print_array();
return 0;
}
void print_array(){
int i;
for(i = 0; i < count; i++){
printf("current count is %d\n", array[i]);
}
}
You can't do a static dynamic declaration like:
int globalarray[n];
Where n is a variable set at runtime. This doesn't work because the array is initialized before the program begins running.
A good alternative is to use a pointer to dynamic memory:
int *globalarray;
int main (int argc, char **argv)
{
...
int elements = atoi (argv [j]); // parse out the program argument array size
globalarray = malloc (elements * sizeof (globalarray[0]));
}
A global pointer to a malloc'd array is one possible solution.
So you malloc the array of needed size depending on your command line argument and make the pointer to the array visible to all your pthreads.

Resources