How to save pthread_t id to an array - c

How can i save the id of p_thread to an array?
int i;
pthread_t t[N];
float arrayId[N];
for (i = 0; i < N; i++) {
pthread_create(&t[i], NULL, f, (void *) &i);
printf("creato il thread id=%lu\n", t[i]);
arrayId[i] = t[i];
printf("a[%d]=%f\n", i, arrayId[i]);
}
I can print it, but i'm not able to save...
I'll have to sort this array and then i'll have to execute first all the thread ordered by id

All threads will receive the same value for i because you are passing it by value (the same address).
This should fix it:
int i;
pthread_t t[N];
float arrayId[N];
int indexes[N];
for (i = 0; i < N; i++) {
indexes[i] = i;
pthread_create(&t[i], NULL, f, (void *) &indexes[i]);
printf("creato il thread id=%lu\n", t[i]);
arrayId[i] = t[i];
printf("a[%d]=%f\n", i, arrayId[i]);
}

I'll have to sort this array and then i'll have to execute first all the thread
ordered by id
pthread_create already executes a thread as man states:
The pthread_create() function starts a new thread in the calling process.
So your loop already starts N threads. Also you can't specify thread ids, they are returned when threads are created.

You don't need to save the array. You simply define a function, f, that you wish to operate on these numbers, and then, as you have done in your pthread_create(), have that function, f, as an input.
Each time pthread_create() is called the function, f, will be executed.

Related

How to Store Multiple Arrays Returned From Pthread in Another Array Using Pointers

I'm working on a project that needs to run multiple threads concurrently. Each thread runs a function that returns a pointer to an array of ints (cast as a void pointer). For example, in the function that the threads run, the values I want are stored as such:
void *func(void *args) {
int vals[3] = {0, 0, 0}, x = y = z = 0;
int *ptr = vals;
while(condition) {
.
.
.
ptr[0] += x;
ptr[1] += y;
ptr[2] += z;
}
return (void *) ptr;
}
By the end of this function, ptr[0], ptr[1], and ptr[2] hold the desired values. This code is just to give you an idea of whats happening, there is nothing wrong with my actual implementation.
I am required to use pthread_join() to get the various values from each thread. Each thread handles one file, so # of files == # of threads == # of times the above function runs.
I need to take the values of ptr[0], ptr[1], and ptr[2] from each thread and add them together once they are returned to main. Meaning if there are three threads, then I need to add ptr[0] from thread 1 to ptr[0] from thread 2 and ptr[0] from thread 3. The same thing goes for ptr[1] and ptr[2]. Then I need to print the three total values in main at the end. So far this is how I've done it and I got my code to compile but the values are garbage.
int main(int argc, char *argv[]) {
int NUM_THREADS = argc - 1;
int total1 = total2 = total3 = 0;
pthread_t *tids; /* Dynamically allocated array of pthreads */
void **vals; /* Stores the return values from each thread, this could be incorrect */
/*
** Some code where I allocate the arrays etc
*/
for (i= 0; i < NUM_THREADS; i++)
pthread_create(&tids[i], NULL, func, NULL);
for (i= 0; i < NUM_THREADS; i++)
pthread_join(tids[i], &(vals[i])); /* Again, this could be wrong */
for (i= 0; i < NUM_THREADS; i++) {
total1 += ((int*) vals[i])[0]; /* These statements very well could also be wrong */
total2 += ((int*) vals[i])[1];
total3 += ((int*) vals[i])[2];
}
/* Print totals */
return 0;
}
I know the values in each thread are correct at the end of func, but I don't know how to properly store, process, and print them in main.
Also, I am using C90 and cannot use any functionality from any other version of C and I must store the values using pthread_join().
Each thread runs a function that returns a pointer to an array of ints (cast as a void pointer). For example
void *func(void *args) {
int vals[3] = {0, 0, 0}, x = y = z = 0;
int *ptr = vals;
...
return (void *) ptr;
}
You should start by fixing the function to return something meaningful. As currently written, the function returns a pointer to automatic array vals, which no longer exists after the function returns.
Any use of the returned pointer will produce undefined behavior.
This code is just to give you an idea of whats happening, there is nothing wrong with my actual implementation.
It's somewhat hard to believe that.
pthread_join(tids[i], &(vals[i])); /* Again, this could be wrong */
That is wrong: vals is uninitialized at this point, so you are writing all over random memory.
I don't know how to properly store, process, and print them in main.
Here is how:
void *vals[NUM_THREADS];
..
for (i= 0; i < NUM_THREADS; i++) {
pthread_join(tids[i], &vals[i]);
}
for (i= 0; i < NUM_THREADS; i++) {
int *p = (int *)vals[i];
total1 += p[0];
total2 += p[1];
... etc.
}

Add elements to fifo queue

I'm trying to add int variables to this fifo.
fifo.c
But I only see the same var (this is the last var)
fifo_t *ff = fifo_new();
for (int i =0; i<4; i++) {
int *k = malloc(sizeof(int));
*k = rand();
printf("%d %p!\n", *k, k);
fifo_add(ff, k);
free(k);
}
fifo_iter(ff, my_callback, NULL);
If I create int var in stack and add to fifo like this
int x =0;
fifo_add(ff, (void *)x);
x = 2;
fifo_add(ff, (void *)x);
x = 3;
fifo_add(ff, (void *)x);
It is work fine, but I have warning - "cast to pointer from integer of different size"
What I do wrong? Best regards.
EDIT:
I found function in fifo.c for destroying all elements of fifo queue. For my example, you need to call fifo_free(of, NULL); If you will add your custom struct to the queue, you need to will write some function for destroying you struct and put it in second parametr of fifo_free.
ty for #JonathanLeffler and other commentators
Use
fifo_add(ff, &x);
You need to pass a pointer to data, rather than a casted scalar type, because fn_data is declared to be a void *, and a void * is not guaranteed to hold all scalar types. As a result, it's not possible to add int variables to a fifo.
Also note that
int x =0;
fifo_add(ff, &x);
x = 2;
fifo_add(ff, &x);
x = 3;
fifo_add(ff, &x);
may not work as you expect. It's the address of x that is stored in the new node, not the value it contains. So you will end up getting 3 new nodes, whose fn_datas point to a common memory.

SegFault after the call of pthread_join

I am new to threads and I have problem using pthread_join.
This is my code :
int create_threads(t_lemin *lem)
{
int i;
pthread_t **threads;
int j;
void *ret;
t_tree *tmp;
j = -1;
printf("starting algo\n");
threads = xmalloc(sizeof(pthread_t));
i = count_leaf(lem->start);
tmp = lem->start;
printf("%d\n", tmp->visited[0]);
while (++j != i)
{
tmp->leaf[j]->thread_nbr = j;
pthread_create(threads[j], NULL, find_way_out, tmp->leaf[j]);
usleep(100);
}
i = -1;
while (++j != i)
(void)pthread_join (*threads[j], &ret);
//printf("%d\n", *((int*)ret));
return (0);
}
One of my thread finished his work and after the second one finish, I have a Segmentation Fault.
My functions find_way_out returns pthread_exit((void*)j); or pthread_exit(0);
where j is a integer pointer.
Do you have an idea where it can comes from ?
Thanks !
The problem is that you should pass a pointer to an actual pthread_t variable as first argument to pthread_create, as a way of emulating pass by reference, pthread_create will then initialize the object.
Since you pass an uninitialized pointer, you will have undefined behavior when pthread_create dereferences the pointer. And you will have it too when you try to dereference the pointer for the pthread_join call.
And it's even worse, since you only allocate space for one single pthread_t object, so you will go way out of bounds of the "array".
And then for the pthread_join loop, you will have j being some small positive number, while i is a negative number, meaning your loop will iterate a lot since it has to iterate until j overflows and becomes negative and then continue looping until j equals -1.
Instead I suggest these changes:
Use a variable-length array for the pthread_t object
Save the "size" of the array in a variable that you don't change
And finally, use for loops instead
Something like
size_t count = count_leaf(lem->start);
pthread_t threads[count];
for (size_t i = 0; i < count; ++i)
pthread_create(&threads[i], ...);
...
for (size_t i = 0; i < count; ++i)
pthread_join(threads[i], NULL);

Unexpected results from passing int-value in multithreading, C

I am currently trying to learn about multi-threading in C. But I have got very unexpected results which have left me stumped. In this program, I am trying to fill up a matrix by using threads. I am creating 1024 threads, passing the i value into the function. Then I proceed to use it.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define SIZE 1024
static double a[SIZE][SIZE];
static double b[SIZE][SIZE];
static double c[SIZE][SIZE];
void*
init_matrix(void* msg)
{
int j;
int num = *((int*) msg);
printf("%d\n", num);
for (j = 0; j < SIZE; j++) {
a[num][j] = drand48();
b[num][j] = drand48();
}
pthread_exit(NULL);
}
int
main(int argc, char **argv)
{
//Init threads
pthread_t p_initThreads[SIZE];
int i,j;
for(i = 0; i< SIZE; i++)
{
pthread_create(&p_initThreads[i], NULL, init_matrix, (void*)&i);
}
for(j = 0; j<SIZE; j++)
{
pthread_join(p_initThreads[j], NULL);
}
}
Expected results from the prinf would be; 1-2-3-4-5-6-7-8-9-10. With the possible
result of it being inorder due to of it being in threads. But the reults on my computer is this;
1-2-2-4-5-7-24-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-26-35-36-36-37-37-37-37-37-37-37-37-38-39-40
By commentating out;
for (j = 0; j < SIZE; j++) {
a[num][j] = drand48();
b[num][j] = drand48();
}
I get the result that I want. Why is that? It should not do anything to num!
You are passing the address of i as the input parameter of the thread. If you were passing the value of i, you would get 1-2-3-4-5-... . But when you pass the address, it is entirely possible that before the printf line is executed, the main thread already incremented i. And printf displays the current value of i, not the value it had at the moment of thread creation.
What you have is a race condition with multiple threads accessing the same memory location (variable i) since you are passing the address of i to all threads.
What you really wanted to do was pass the value of i. Call the pthread_create() with:
pthread_create(&p_initThreads[i], NULL, init_matrix, (void*)i);
and read the value as:
int num = (int) msg;
instead of : int num = *((int*) msg);
You should also check if pthread_create() returns non-zero for failures. If that's the case, you are not going to get expected results.

I add values into a C array in one function, array is still empty in later function, what gives?

The pointer is declared
int *v;
And the two functions are called.
createMemObjects(M, N, v, context);
transferToDevice(M, v, commands);
So in my first function which I pass int *pv into, I fill the array:
pv = malloc(sizeof(int) * M);
memset(pv, 0, sizeof(int)*M);
for (int i = 0; i<M; i++) {
pv[i] = N; //Initialise every element of vector with N.
printf("Element %d: %d\n", i, pv[i]);
}
The print shows that pv has been filled with N=2.
In a later function which *pv as an argument again, I use a similar print loop:
for (int i = 0; i<M; i++) {
printf("Element %d: %d\n", i, pv[i]);
}
And instead of 2s, it shows all elements to be back to 0. What am I doing wrong? Pretty sure I've been using pointers correctly, but is there something I've missed?
As commented, you need to pass the address of the pointer v as C passes arguments by value, including pointers. As the code stands, a copy of v is being assigned within createMemObjects() so the change is not visible to the caller:
/* Invoke as */
createMemObjects(M, N, &v, context);
Change argument type of v to int** and within createMemObjects():
*pv = malloc(sizeof(int) * M);
The memset() immediately after malloc() is superfluous as the for is initalizing each int in pv.

Resources