thread parameter passing c - c

My question regards parameter passing to a thread.
I have a function Foo that operates on an array, say arrayA. To speed things up, Foo is coded to operate at both directions on the array. So, Foo takes arrayA and an integer X as parameters. Depending on the value of X, it operates in forward or reverse direction.
I'm looking to avoid making global use of "arrayA" and "X". So, I'm after passing "arrayA" and "X" as parameters to Foo, and creating two threads to run Foo-- one in each direction. Here's what I did:
typedef struct {int* arrayA[MSIZE]; int X; } TP; //arrayPack=TP
void Foo (void *tP) {
TP *tp = (TP*)tP; // cast the parameter tP back to what it is and assign to pointer *tp
int x;
printf("\nX: %d", tp->X);
printf("\n arrayA: "); for (x=0; x<tp->arrayA.size(); printf("%d ", aP->arrayA[x]), x++);
} // end Foo
void callingRouting () {
int* arrayA[MSIZE] = {3,5,7,9};
TP tp; tp.arrayA=arrayA;
tp.X=0; _beginthread(Foo, 0, (void*)&tp); // process -- forward
tp.X=1; _beginthread(Foo, 0, (void*)&tp); // process -- reverse
}
The values aren`t passed-- my array is printing empty and I'm not getting the value of X printed right. What am i missing ?
I would also appreciate suggestions on some readings on this-- passing parameters to threads-- especially on passing the resources shared by the threads. Thanks.

You're passing the address of a stack variable to your thread function, once callingRouting exits the TP structure no longer exists. They need to be either globals or allocated on the heap.
However you'll need two copies of the TP for each thread as the change tp.X=1 may be visible to both threads.
There are problems there but how you see them depends on how the OS decides to schedule the threads on each execution.

The first thing to remember is that you have a thread that is starting up two other threads. Since you do not have any control over the processor time slice and how that is allocated, you can not be sure when the two other threads will start and may be not even the order that they will start in.
Since you hare using an array on the stack that is local to the function callingRouting () as soon as that function returns the local variables allocated will basically be out of scope and can no longer be depended on.
So there are a couple of ways to do this.
The first is to use global or static memory variables for these data items being passed to the threads.
The other is to start both threads and then wait for both to complete before continuing.
Since you do not know when or the order of the threads being started, you really should use two different TP type variables, one for each thread. Otherwise you run the risk of the time slice allocation to be such that both threads will have the same TP data.

Related

initialize pthread mutex lock inside a C struct

I am trying to code a C project to simulate air traffic control in an airline. There is a Plane struct that has to have a mutex lock and cond.
This is the struct:
typedef struct Plane {
int ID;
int arrival_time;
pthread_mutex_t lock;
pthread_cond_t cond;
}Plane;
And there are landing/departing functions that create and use Plane structures. However, I do not know how to initialize a struct's mutex lock inside a function.
void landing_func(int arrival_time)
{
Plane plane;
plane.ID = ++plane_id;
plane.arrival_time = arrival_time;
// initialize lock and cond here
};
However, I am not sure how to do that. I also declare a function that creates and returns a Plane*
Plane* createPlane(int arrival_time){
Plane* plane;
plane = (Plane*)malloc(sizeof(Plane));
plane->arrival_time = arrival_time;
plane->ID = ++plane_id;
pthread_mutex_init(&plane->lock, NULL);
pthread_cond_init(&plane->cond, NULL);
return plane;
};
I am not sure about correctness of this initialization.
A minor question: Can I return Plane instead of Plane*? I need Plane in other functions instead of Plane*.
However, I do not know how to initialize a struct's mutex lock inside a function.
It's unclear what your confusion is.
The mutex and condition variable initialization functions require as first argument a pointer to the object to initialize, which is perfectly natural. Their second arguments can be null pointers if you want default attributes, which you probably do.
Given
Plane plane;
, as in your first example, the mutex you want to initialize is plane.lock. The address-of operator will produce a pointer to it: &plane.lock (or if you're uncertain about precedence and too lazy to look it up, then &(plane.lock) avoids the precedence question). Thus, you might initialize it with
pthread_mutex_init(&plane.lock, NULL);
Similar for the CV.
I guess the main thing to appreciate is that the mutex being a member of a structure does not constitute a special case. Objects that are structure members or array elements have the same properties as objects of the same type that are not contained in such aggregates. The difference is simply in how you reference such objects.
I also declare a function that creates and returns a Plane* [...] I am not sure about correctness of this initialization.
It's fine, as you should also be able to infer from my previous comments.
A minor question: Can I return Plane instead of Plane*? I need Plane
in other functions instead of Plane*.
I take it that you're referring specifically to the second example, where you allocate space dynamically for the Plane. Yes, you can return a Plane instead of a Plane *, supposing that you adjust the function's return type, but that defeats the purpose of the dynamic allocation. Moreover, if you do that naively (just return *plane;, for example) then you will leak memory.
But it is extremely important to understand that when you pass or return an object, you are delivering a copy of that object to the receiver. Where once there was one, suddenly there are two.* Additionally, it is a shallow copy, so the two might not be wholly independent. That can be ok under some circumstances, but yours are not such circumstances. I guarantee that passing your Plane structures around that way will cause you no end of grief in your particular program, on account of its reliance on the mutex and CV belonging to each. There are other gotchas there, too, but the mutex and CV are at the center of the most glaring ones.
Do yourself a tremendous favor, and adjust to exchanging Planes via pointer instead of by copying. It may take some adjustment, and that mode has its own issues to contend with, but trust me: the other way leads to disaster for you.
* This applies just as much to pointers as to any other kind of object, but if you pass a copy of a pointer then only the pointer itself is copied, and the copy points to the same object as the original does.

pthread_create argument is lost

I'm writing a very simple code in which i need to use some threads.
When I create first type of thread i pass argument with pthread_create:
fman thread_arg;
thread_arg.sd=sda;
char* split = strtok(buffer, "|");
thread_arg.wcount=atoi(split);
split = strtok(NULL,"");
strcpy(thread_arg.id, split);
pthread_create(&thread_temp, NULL, registerF, &thread_arg);
And everything works fine, but in function registerF I need to do something like this:
wman thread_arg;
thread_arg.sd=foremans_fd[ix];
thread_arg.fmanix=ix;
strcpy(thread_arg.id,tmpr);
pthread_create(&thread_temp, NULL, registerW, &thread_arg);
Those arguments are structures defined by me:
typedef struct fman
{
int sd;
char id[100];
int wcount;
} fman;
typedef struct wman
{
int sd;
int fmanix;
char id[100];
} wman;
And when I check it by printf("%x, args) I get the same address but values are different inside. Where is my mistake?
One likely problem is here:
fman thread_arg;
[...]
pthread_create(&thread_temp, NULL, registerF, &thread_arg);
Note that the thread_arg object is located on the stack, and thus will be destroyed (and likely overwritten by other stack variables) when the function it is declared in returns.
pthread_create(), on the other hand, launches a thread that will run asynchronously with this function, which means that the thread can (and often will) run after the function you excerpted has returned, which means that by the time the thread dereferences &thread_arg, thread_arg has likely already been destroyed and that pointer is now pointing to some other data that was written into the same stack location later on.
Unless you are doing something special to make sure that the struct's lifetime is long enough to include all of the spawned thread's accesses to the struct, then the fact that this code ever works is pure luck (i.e. the scheduler just happened to schedule the thread to run and perform all of its accesses to the struct before the struct was destroyed/overwritten). You definitely can't depend on that.
In order to fix the problem, you need to either allocate the struct on the heap (so that it won't be destroyed when the function returns -- the spawned thread can then free the struct when it is done using it), or use some kind of synchronization mechanism (e.g. a condition variable) to cause the main thread to block inside your function until the spawned thread has indicated that it is done accessing the struct.
The thread struct in the running thread is treated like a block of memory and accessed using offsets. Since your fman and wman structs have different orders (4+100+4) vs (4+4+100), it's likely that you're getting right struct but reading from different memory location, given the passed struct to this thread is fman, and it's being accessed as wman.
Try changing them both to same signature, as in, int, int, char* and it should work.

Mallocing in a recursive function

I have a function that is called recursively a number of times. Inside this function I malloc memory for a struct and pass it as an argument into the recursive call of this function. I am confused whether I can keep the name of the variable I am mallocing the same. Or is this going to be a problem?
struct Student{
char *studentName;
int studentAge;
};
recursiveFunction(*struct){ //(Whoever calls this function sends in a malloced struct)
Student *structptr = malloc(sizeof(Student));
<Do some processing>
.
.
if(condition met){
return;
}
else{
recursiveFunction(structptr);
}
}
free(){} // All malloced variables are free'd in another function
Would this be a problem since the name of the variable being malloced doesnt change in each recursive call.
The short answer is no. When you declare a variable it is scoped at the level where it is declared, in your case within this function. Each successive recursive call creates a new scope and allocates that memory within that scope so the name of your variable will not cause problems. However, you do want to be very careful that you free any memory that you malloc() before returning from your function as it will not be accessible outside the scope of your function unless you pass back a pointer to it. This question provides a lot of helpful information on using malloc() within functions. I also recommend reading more about scope here.
Each malloc() must have a matching free(). Either you need to free the record inside recursiveFunction (e.g. immediately before it exits), or in a function called by recursiveFunction or you need to maintain a list of them and free them elsewhere.
The name of the 'variable being malloced' being the same is irrelevant. In any case, it is not the variable that is being malloc()d; rather it is memory that is being malloc()d and the address stored in a variable. Each recursive iteration of recursiveFunction has a different stack frame and thus a different instance of this variable. So all you need to do is ensure that each malloc() is paired with a free() that is passed the address returned by malloc().
If you want to check you've done your malloc() / free() right, run valgrind on the code.
Can keep the name of the variable I am mallocing the same?
Yes, in a recursive function this is fine. As the function is called recursively, each variable holding the malloc'd pointer (it doesn't hold the memory itself) will be allocated on a new stack frame.
However, you're going to have to free that memory somehow. Only the pointer to the memory is on the stack, so only the pointer is freed when the function exits. The malloc'd memory lives on. Either at the end of each call to the function, or all that memory will have to be returned as part of a larger structure and freed later.
I am confused whether I can keep the name of the variable I am mallocing the same.
You seem to be confused about the concept of scope. Functions in C define scopes for the (local) variables you declare within them. That means that when you declare a local variable bar inside some function foo, then when you reference bar inside that function you reference whatever you declared it to be.
int bar = 21;
void foo(void) {
int bar = 42;
// ...
bar; // This is the bar set to 42
}
Now scope is only the theoretical concept. It's implemented using (among other details that I skip over here) so called stack frames:
When you call foo, then a new stack frame is created on the call stack, containing (this is highly dependent on the target architecture) things like return address (i.e. the address of the instruction that will be executed after foo), parameters (i.e. the values that you pass to a function) and, most importantly, space for the local variables (bar).
Accessing the variable bar in foo is done using addresses relative to the current stack frame. So accessing bar could mean access byte 12 relative to the current stack frame.
When in a recursive function the function calls itself, this is handled (mostly, apart from possible optimizations) like any other function call, and thus a new stack frame is created. Accessing the same (named) variable from within different stack frames will (because, as said, the access is using a relative address) thus access a different entities.
[Note: I hope this rather rough descriptions helps you, this is a topic that is - when talked about in depth - extremely depending on actual implementations (compilers), used optimizations, calling convention, operating system, target architecture, ... ]
I put together a simple stupid example, which hopefully shows that what you want to do should be possible, given that you appropriately free whatever you allocated:
unsigned int crazy_factorial(unsigned int const * const n) {
unsigned int result;
if (*n == 0) {
result = 1;
} else {
unsigned int * const nextN = malloc(sizeof(unsigned int));
*nextN = *n - 1;
result = *n * crazy_factorial(nextN);
free(nextN);
}
return result;
}
Running this with some output shows what's going on.

Per-thread state vs. shared state in threads

I'm trying to understand the details in the TCB (thread control block and the differences between per-thread states and shared states. My book has its own implementation of pthread, so it gives an example with this mini C program (I've not typed the whole thing out)
#include "thread.h"
static void go(int n);
static thread_t threads[NTHREADS];
#define NTHREADS 10
int main(int argh, char **argv) {
int i;
long exitValue;
for (i = 0; i < NTHREADS; i++) {
thread_create(&threads[i]), &go, i);
}
for (i = 0; i < NTHREADS; i++) {
exitValue = thread_join(threads[i]);
}
printf("Main thread done".\n);
return 0;
}
void go(int n) {
printf("Hello from thread %d\n", n);
thread_exit(100 + n);
}
What would the variables i and exitValue (in the main() function) be examples of? They're not shared state since they're not global variables, but I'm not sure if they're per-thread state either. The i is used as the parameter for the go function when each thread is being created, so I'm a bit confused about it. The exitValue's scope is limited only to main() so that seems like it would just be stored on the process' stack. The int n as the parameter for the void go() would be a per-thread variable because its value is independent for each thread. I don't think I fully understand these concepts so any help would be appreciated! Thanks!
Short Answer
All of the variables in your example program are automatic variables. Each time one of them comes into scope storage for it is allocated, and when it leaves its scope it is no longer valid. This concept is independent of whether the variables is shared or not.
Longer Answer
The scope of a variable refers to its lifetime in the program (and also the rules for how it can be accessed). In your program the variables i and exitValue are scoped to the main function. Typically a compiler will allocate space on the stack which is used to store the values for these variables.
The variable n in function go is a parameter to the function and so it also acts as a local variable in the function go. So each time go is executed the compiler will allocate space on the stack frame for the variables n (although the compiler may be able to perform optimization to keep the local variables in registers rather than actually allocating stack space). However, as a parameter n will be initialized with whatever value it was called with (its actual parameter).
To make this more concrete, here is what the values of the variales in the program would be after the first loop has completed 2 iterations (assuming that the spawned threads haven't finished executing).
Main thread: i = 2, exitValue = 0
Thread 0: n = 0
Thread 1: n = 1
The thing to note is that there are multiple independent copies of the variable n. And that n gets a copy of the value in i when thread_create is executed, but that the values of i and n are independent after that.
Finally I'm not certain what is supposed to happen with the statement exitValue = thread_join(threads[i]); since this is a variation of pthreads. But what probably happens is that it makes the value available when another thread calls thread_join. So in that way you do get some data sharing between threads, but the sharing is synchronized by the thread_join command.
They're objects with automatic storage, casually known as "local variables" although the latter is ambiguous since C and C++ both allow objects with local scope but that only have one global instance via the static keyword.

Returning from an array from thread in C?

I don't know what am I doing wrong in the following function. I am trying to return an array but it Seg Faults at while loop in the compute_average. I am using a structure to initialize the begin and the last word and used in the function "compute_average" You can assume the compute_average function works fine which was already there but I changed the code when using the structure or "first" and "second" value.
typedef struct parallel{
unsigned long first, second;
}Parallel;
return final_array;
}
Your argument to pthread_join is wrong. You are, in effect, doing this:
pthread_join(tid, NULL);
You need to supply the address of a void * variable (and technically you should capture the return value of pthread_join itself, in case it fails, although here it won't):
error = pthread_join(tid, &ary1);
If error==0 after this, ary1 will contain the value returned from the thread, and array1 = ary1 will suffice to make it useful (no cast is needed there).
(As ldav1s noted, the size is wrong too. You may want to augment the code to return more than just one pointer. Or you could fill in a data structure supplied by the thread's caller. [I'm making various guesses here about how you might implement multiple threads, in the end. The guesses may be wrong. :-) ])
This:
unsigned long *array1;
...
size = (sizeof(array1)/sizeof(array1[0]));
Looks extremely suspicious, unless size is supposed to be 1 or 2. array1 is a pointer, not an array.
pthread_join(tid, ary1);
should be:
pthread_join(tid, &ary1);
If you want to get any data back from compute_prime at all. You also need to "tack on" some kind of size in the data returned from compute_prime to tell you how many elements you've got.
You're also leaking memory allocated in compute_prime, better free(ary1).

Resources