Unexpected results from passing int-value in multithreading, C - 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.

Related

Threads in C interrupt each other

So i have a global variable called counter and i run 4 threads which increment in million times but the result i am getting at the end does not even reach 2 million.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
int nthread;
int counter=0;
void *f(void *arg)
{
int i = *(int *)arg;
int *p;
for (int c = 0; c < 1000000; c++)
{
counter++;
}
printf(" I am thread %d (out of %d),tid =% ld\n", i, nthread, pthread_self());
p = malloc(sizeof(int));
*p = i * 2;
pthread_exit(p); // return p
}
int main(int argc, char *argv[])
{
pthread_t *tid;
int e, i, *ti;
nthread = 4;
tid = malloc(nthread * sizeof(pthread_t));
ti = malloc(nthread * sizeof(int));
for (i = 0; i < nthread; i++)
{
ti[i] = i;
if ((e = pthread_create(&tid[i], NULL, f, &ti[i])) != 0)
send_error(e, " pthread_create ");
}
for (i = 0; i < nthread; i++)
{
void *r;
if ((e = pthread_join(tid[i], &r)) != 0)
send_error(e, " pthread_join ");
printf(" Return of thread %d = %d\n", i, *(int *)r);
free(r);
}
printf("counter is %d\n",counter);
free(tid);
free(ti);
}
What causes this and how i can fix this?
PS:if your code not compile replace send_error with printfs
The pthreads standards is very clear that you may not access an object in one thread while another thread is, or might be, modifying it. Your code violates this rule.
There are many reasons for this rule, but the most obvious is this:
for (int c = 0; c < 1000000; c++)
{
counter++;
}
You want your compiler to optimize code like this. You want it to keep counter in a register or even eliminate the loop if it can. But without the requirement that you avoid threads overlapping modifications and accesses to the same object, the compiler would have to somehow prove that no other code in any other thread could touch counter while this code was running.
That would result in a huge amount of valuable optimizations being impossible on the 99% of code that doesn't share objects across threads just because the compiler can't prove that accesses might overlap.
It makes much more sense to require code that does have overlapping object access to clearly indicate that they do. And every threading standard provides good ways to do this, including pthreads.
You can use any method to prevent this problem that you like. Using a mutex is the simplest and definitely the one you should learn first.

variable in thread callstack changing unexpectedly c

Using c11 threads, I'm trying to ensure that foo is thread safe. While foo isn't reentrant, I'm trying to mitigate this with mutexes.
I don't understand why the value of thrdn is changing in the critical loop. My understanding was that each threaded call to foo would have its own version of thrdn, but it seems that it is being modified by other threads at run-time.
I've tried moving the mtx_lock above thrdn's declaration and changing thrdn to be of type atomic_int * however these both result in the same behaviour.
#include <stdio.h>
#include <threads.h>
#include <string.h>
#include <stdlib.h>
#define THREAD_MAX 5
thrd_t threads[THREAD_MAX];
mtx_t mtx;
void foo(void * data)
{
int* thrdn = (int *)data;
mtx_lock(&mtx);
for(int i = 0; i < 3; ++i) {
printf("thread %d, number %d\n", *thrdn, i);
}
mtx_unlock(&mtx);
}
int main()
{
mtx_init(&mtx, mtx_plain | mtx_recursive);
for(int i = 0; i < THREAD_MAX; ++i){
thrd_create(&threads[i], foo, &i);
}
for(int i = 0; i < THREAD_MAX; ++i){
thrd_join(threads[i], NULL);
}
mtx_destroy(&mtx);
}
As has been noted in the comments, the issue was the reference to the local variable i. Tracking thread ids separately as seen in this answer solved the issue.

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.
}

segmentation fault during execution of program

I have written a program to create 10 threads and run them normally. The Program is running fine but at the end it gives a segmentation fault. What is this fault, what is causing it, and how do I resolve it?
My code is :
#include<stdio.h>
#include<pthread.h>
void *print(void *num);
int main()
{
pthread_t tid[10];
int n,check;
void *exitstatus;
for(n=1;n<=10;n++)
{
check=pthread_create(&tid[n],NULL,print,(void *)&n);
if(check=0)
printf("thread created");
pthread_join(tid[n],&exitstatus);
}
return 0;
}
void *print(void *num)
{
int i,*val=(int *)num;
for(i=0;i<(5);i++)
printf("Hello World!!!(thread %d )\n",*val);
}
You have many flaws:
for(n=1;n<=10;n++) // No, The array starts from 0 and lasts on 9
Try this
for(n=0;n<10;n++)
if(check=0) // No, this will assign 0 to check instead of compare it
Try this
if(check==0)
You are accessing an array beyond its index. It is undefined behavior.
your array t[10] starts at index t[0] and should end at t[9] -
for(n = 0; n < 10; n++) {
//your stuff
}
Also check == 0 is how you check equality. check = 0 will assign 0 to check
So your code must look like this:
#include<stdio.h>
#include<pthread.h>
void *print(void *num);
int main()
{
pthread_t tid[10];
int n,check;
void *exitstatus;
for(n = 0; n < 10; n++)
{
check=pthread_create(&tid[n], NULL, print, (void *)&n);
if(check == 0)
printf("thread created");
pthread_join(tid[n], &exitstatus);
}
return 0;
}
void *print(void *num)
{
int i,*val=(int *)num;
for(i = 0; i < 5; i++)
printf("Hello World!!!(thread %d )\n", *val);
}
Another important note on programming style: Please use proper indentation and use whitespace judiciously. Most programming errors and bugs can be eliminated if proper indentation and whitespace is used. For example, one white space before and after an operator in the for loop, and between parameters while calling a function after , and before the next parameter.

How can I initiate an array, each element in a separate thread

I am trying to create an array of size n (where n is user's input) and when the user runs the program, the array elements should be set to 1 (each in a separate thread). Here is what I have done so far:
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>
int *x;
DWORD WINAPI init_X(LPVOID param)
{
int index = *(int *) param;
x[index] = 1;
return 0;
}
int main(int argc, char *argv[])
{
int n = atoi(argv[1]);
int i; // counter.
HANDLE THandles[n];
x = malloc(n * sizeof (int));
for(i = 0; i < n; i++)
{
THandles[i] = CreateThread(NULL, 0, init_X, &i, 0, NULL);
}
// Now wait for threads to finish
WaitForMultipleObjects(n, THandles, TRUE, INFINITE);
// Close the thread handle
for(i = 0; i < n; i++)
{
CloseHandle(THandles[i]);
}
printf("After initialization x = ");
for(i = 0; i < n; i++)
{
printf("%d ", x[i]);
if(i < n - 1) printf(" ");
}
// ...
return 0;
}
I run this program and I got wrong outputs:
> Test.exe 3
After initialization x = 11611536 11600064 50397186
It should be After initialization x = 1 1 1 though. I am not sure how I can I fix this, but I am sure its something related to the pointers.
P.S: I'm Java programmer so I'm not familiar with pointers.
The value you are passing as your array index will more than likely be invalid by the time the thread runs, as there is no guaranteeing that the thread is run immediately after the call to CreateThread.
You have two solutions, either pass by value (simple & easy, but not always safe) or allocate a temporary buffer for the value that will be freed by the thread when its used.
Minor Update:
In fact, a better way would be to pass &x[i], then you can just do *(int*)param = 1;
You are passing i by pointer to the thread, so the value each thread gets will depend on when int index = *(int *) param; actually executes and it should be something between 0 and n. You can just pass i by value (casted to a pointer) to avoid this.

Resources