pthread_create undetermined variable - c

I am trying to create five threads in the main thread.
In the pthread_create() function, I am passing increasing 'num' value as a variable to function 'up' each time, so I thought the value of y in each thread should be 1,2,3,4 and 5 in a random order, respectively.
However, when printf("before add num is %d\n", y) in function 'up' is called which is to check the value of y , it shows y could be undetermined which means y may be any number between 1 to 5.
How shall I fix this parallel input problem...Thanks in advance for any help!
const int TOTAL_RUNS = 1000000;
void *up(void *ptr) {
int i;
int y = *((int*)ptr);
printf("before add num is %d\n", y);
for (i = 0; i < TOTAL_RUNS; i++)
y++;
printf("Finished adding 1 a total of %d times.\n", TOTAL_RUNS);
}
void main() {
int num = 1;
pthread_t t[5];
int i;
for (i = 0; i < 5; i++) {
pthread_create(&t[i], NULL, up,(void*) &num);
num++;
}
for (i = 0; i < 5; i++) {
pthread_join(t[i], NULL);
}
}

The problem is you're passing the same address to every thread - each thread has access to the same memory location (since you passed &num to each of them).
The cheapest way you could fix this would be to use an array:
int nums[] = {1, 2, 3, 4, 5};
/* ... */
pthread_create(&t[i], NULL, up, &nums[i]);
That should be safe since you call join in the same thread (nums won't go out of scope before the threads are done).

Related

Creating and passing multiple pthreads in C

I'm trying to get pthread to output a variable declared in a for loop:
pthread_t pthread[10];
void * count(void* argv){
int index = *(int*)argv;
printf("%d", index);
pthread_exit(NULL);
}
int main() {
for (int i = 0; i < 10; ++i) {
pthread_create(&pthread[i], NULL, count,(void*)&i);
}
return 0;
}
Output I thought:
0123456789 (or not in order, but all 10 number)
What I got:
123456789
Why 0 is not in here?
One problem is that your main() thread exits without waiting for the child threads to finish, which means the child threads may not have time to finish (or potentially even begin) their execution before the process is terminated.
To avoid that problem, you need to call pthread_join() on all of your threads before main() exits, like this:
int main() {
for (int i = 0; i < 10; ++i) {
pthread_create(&pthread[i], NULL, count,(void*)&i);
}
for (int i = 0; i < 10; ++i) {
pthread_join(pthread[i], NULL); // won't return until thread has exited
}
return 0;
}
The other problem, as mentioned by 500 in the comments, is that you are passing a pointer to i to the child threads, which they then dereference, and since i is being modified in the main thread's loop, it's undefined behavior what value the child threads will read from that pointer. One way to avoid this is to give each thread its own separate (non-changing) integer to read:
int values[10];
for (int i = 0; i < 10; ++i) {
values[i] = i;
pthread_create(&pthread[i], NULL, count,(void*)&values[i]);
}

C - pthread returns unexpected result

I am trying to get to the bottom of an issue with pthreads in C. While my second thread returns the value correctly, the first one just gives me (I assume) a memory address.
The code should do following:
Create a 2 threads which calculate the factorial and the exponential value of a given number from the console.
The Factorial is coded as a function and the exponential calculator is in the main code.
Thanks for any help!
#include <pthread.h>
#include <stdio.h>
void *fac_x(void *x_void_ptr)
{
int *x_ptr = (int *)x_void_ptr;
int counter = *x_ptr;
for (int i = 1; i < counter ; i++) {
*x_ptr *= i;
}
printf("x factorising finished\n");
return NULL;
}
int main()
{
int x,y, counter;
printf("Enter an integer: ");
scanf("%d",&x);
y = x;
counter = y;
printf("Input = %d\n",x);
pthread_t fac_x_thread;
if(pthread_create(&fac_x_thread, NULL, fac_x, &x)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
while (counter != 0) {
y *= y;
counter--;
}
if(pthread_join(fac_x_thread, NULL)) {
fprintf(stderr, "Error joining thread\n");
return 2;
}
printf("Factorial: %d \nExponential: %d\n", x, y);
return 0;
}
the first one just gives me (I assume) a memory address.
this is not an address, you (try to) compute a very great value, you have an overflow very quickly
for 3 it is already 6561 (3*3 = 9, 9*9 = 81, and finaly 81*81=6561)
for 4 the value is 2^32 too great in 32bits (4*4= 16, 16*16 = 256, 256*256 = 65536, and finally 65536*65536 = 4294967296 = 2^32)
for 5 the value is 23283064365386962890625 = 0x4EE2D6D415B85ACEF81 > 2^75 too great for 64b !

How to pass specific value to one thread?

I'm working through a thread exercise in C, it's a typical thread scheduling code many schools teach, a basic one can be seen here, my code is basically the same except for my altered runner method
http://webhome.csc.uvic.ca/~wkui/Courses/CSC360/pthreadScheduling.c
What I'm doing is basically altering the runner part so my code prints an array with random numbers within a certain range, instead of just printing some words. my runner code is here:
void *runner(void *param) {
int i, j, total;
int threadarray[100];
for (i = 0; i < 100; i++)
threadarray[i] = rand() % ((199 + modifier*100) + 1 - (100 + modifier*100)) + (100 + modifier*100);
/* prints array and add to total */
for (j = 0; j < 100; j += 10) {
printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", threadarray[j], threadarray[j+1], threadarray[j+2], threadarray[j+3], threadarray[j+4], threadarray[j+5], threadarray[j+6], threadarray[j+7], threadarray[j+8], threadarray[j+9]);
total = total + threadarray[j] + threadarray[j+1] + threadarray[j+2] + threadarray[j+3] + threadarray[j+4] + threadarray[j+5] + threadarray[j+6] + threadarray[j+7] + threadarray[j+8] + threadarray[j+9];
}
printf("Thread %d finished running, total is: %d\n", pthread_self(), total);
pthread_exit(0);
}
My question lies in the first for loop where I'm assigning random numbers to my array, I want this modifier to change based on which thread it is, but I can't figure out how to do it, for example if its the first thread the range will be 100-199, 2nd will be 200-299, etc and so on. I have tried to assign i to an value before doing pthread_create and assigning that value to an int in runner to use as the modifier, but since there are 5 concurrent threads it ends up assigning this number to all 5 threads, and they end up having the same modifier.
So I'm looking for a method to approach this where it will work for all the individual threads instead of assigning it to all of them, I have tried to change the parameters to something like (void *param, int modifier) but when I do this I have no idea how to reference runner, since by default it's refrenced like pthread_create(&tid[i],&attr,runner,NULL);
You want to make param point to a data structure or variable who's lifetime will exist longer than the thread lifetime. And you cast the void* parameter to the actual data type it was allocated as.
Easy example:
struct thread_data
{
int thread_index;
int start;
int end;
}
struct thread_info;
{
struct thread_data data;
pthread_t thread;
}
struct thread_info threads[10];
for (int x = 0; x < 10; x++)
{
struct thread_data* pData = (struct thread_data*)malloc(sizeof(struct thread_data)); // never pass a stack variable as a thread parameter. Always allocate it from the heap.
pData->thread_index = x;
pData->start = 100 * x + 1;
pData->end = 100*(x+1) - 1;
pthread_create(&(threads[x].thread), NULL, runner, pData);
}
Then your runner:
void *runner(void *param)
{
struct thread_data* data = (struct thread_data*)param;
int modifier = data->thread_index;
int i, j, total;
int threadarray[100];
for (i = 0; i < 100; i++)
{
threadarray[i] = ...
}

Multithreading pthread errors

Im trying to create a multithreaded application in C for Linux with pthreads library that makes an approximation of pi using infinite series with N+1 terms.Variable N and T are passed from the command line. I am using the Nilakantha approximation formula for pi. N is the upper limit of the number sequence to sum and T would be the # of child threads that calculate that sum. For example if I run command "./pie 100 4". The parent thread will create 4 child threads indexed 0 to 3. I have a global variable called vsum that is a double array allocated dynamically using malloc to hold values. So with 4 threads and 100 as the upper bound. My progam should compute:
Thread 0 computes the partial sum for i going from 0 to 24 stored to an element vsum[0]
Thread 1 computes the partial sum for i going from 25 to 49 stored to an element vsum[1]
Thread 2 computes the partial sum for i going from 50 to 74 stored to an element vsum[2]
Thread 3 computes the partial sum for i going from 75 to 99 stored to an element vsum[3]
After each thread makes calculations. The main thread will compute the sum by adding together all numbers from vsum[0] to vsum[T-1].
Im just starting to learn about threads and processes. Any help or advice would be appreciated. Thank you.
Code I wrote so far:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
double *vsum;
int N, T;
void *PI(void *sum) //takes param sum and gets close to pi
{
int upper = (int)sum;
double pi = 0;
int k = 1;
for (int i = (N/T)*upper; i <= (N/T)*(upper+1)-1; i++)
{
pi += k*4/((2*i)*(2*i+1)*(2*i+2));
if(i = (N/T)*(upper+1)-1)
{
vsum[upper] = pi;
}
k++;
}
pthread_exit(0);
}
int main(int argc, char*argv[])
{
T = atoi(argv[2]);
N = atoi(argv[1]);
if (N<T)
{
fprintf(stderr, "Upper bound(N) < # of threads(T)\n");
return -1;
}
int pie = 0;
pthread_t tid[T]; //thread identifier
pthread_attr_t attr; //thread attributes
vsum = (double *)malloc(sizeof(double));//creates dyn arr
//Initialize vsum to [0,0...0]
for (int i = 0; i < T; i++){
{
vsum[i] = 0;
}
if(argc!=2) //command line does not give proper # of values
{
fprintf(stderr, "usage: commandline error <integer values>\n");
return -1;
}
if (atoi(argv[1]) <0) //if its is negative/sum error
{
fprintf(stderr, "%d must be >=0\n", atoi(argv[1]));
return -1;
}
//CREATE A LOOP THAT MAKES PARAM N #OF THREADS
pthread_attr_init(&attr);
for(int j =0; j < T;j++)
{
int from = (N/T)*j;
int to = (N/T)*(j+1)-1;
//CREATE ARRAY VSUM TO HOLD VALUES FOR PI APPROX.
pthread_create(&tid[j],&attr,PI,(void *)j);
printf("Thread %d computes the partial sum for i going from %d to %d stored to an element vsum[%d]\n", j, from, to, j);
}
//WAITS FOR THREADS TO FINISH
for(int j =0; j <T; i++)
{
pthread_join(tid[j], NULL);
}
//LOOP TO ADD ALL THE vsum array values to get pi approximation
for(int i = 0; i < T; i++)
{
pie += vsum[i];
}
pie = pie +3;
printf("pi computed with %d terms in %d threads is %d\n",N,T,pie);
vsum = realloc(vsum, 0);
pthread_exit(NULL);
return 0;
}
Here is the error I dont see that I get on my program: What am I missing here?
^
pie.c:102:1: error: expected declaration or statement at end of input
}
When I try to run my program I get the following:
./pie.c: line 6: double: command not found
./pie.c: line 7: int: command not found
./pie.c: line 8: int: command not found
./pie.c: line 10: syntax error near unexpected token `('
./pie.c: line 10: `void *PI(void *sum) //takes param sum and gets close to pi'
I haven't looked at logic of your code, but I see following programming errors.
Change
pthread_create(&tid[j],&attr,PI,j);
to
pthread_create(&tid[j],&attr,PI,(void *)j);
pthread_create() takes 4th param as void * which is passed to the thread function.
Also fix your thread function PI to use passed parameter as int like
void *PI(void *sum) //takes param sum and gets close to pi
{
int upper = (int)sum; //don't use `atoi` as passed param is int.
...
//your existing code
}
The 3rd error is for line
realloc(vsum, 0);
By passing 0 to re-allocate, you are effectively just freeing vsum, so you can just use free(vsum). If you indeed want to reallocate you should take the new allocated memory returned by the function something like vsum = realloc(vsum, 0);
The Syntax of pthread is
pthread_create(threadId, threadAttribute, callingMethodName, parameters of calling method);
Ex:
void printLetter( void *p)
{
int i=0;
char c=(char *)p;
while (i<10000)
{
printf("%c",c);
}
}
int main()
{
pthread_t thread_id;
char c='x';
pthread_create (&thread_id, NULL, &printLetter, &c);
pthread_join (thread_id, NULL);
return 0;
}
}

Simulating round robin with pthreads

The task is to have 5 threads present at the same time, and the user assigns each a burst time. Then a round robin algorithm with a quantum of 2 is used to schedule the threads. For example, if I run the program with
$ ./m 1 2 3 4 5
The output should be
A 1
B 2
C 2
D 2
E 2
C 1
D 2
E 2
E 1
But for now my output shows only
A 1
B 2
C 2
Since the program errs where one thread does not end for the time being, I think the problem is that this thread cannot unlock to let the next thread grab the lock. My sleep() does not work, either. But I have no idea how to modify my code in order to fix them. My code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
double times[5];
char process[] = {'A', 'B', 'C', 'D', 'E'};
int turn = 0;
void StartNext(int tid) //choose the next thread to run
{
int i;
for(i = (tid + 1) % 5; times[i] == 0; i = (i + 1) % 5)
if(i == tid) //if every thread has finished
return;
turn = i;
}
void *Run(void *tid) //the thread function
{
int i = (int)tid;
while(times[i] != 0)
{
while(turn != i); //busy waiting till it is its turn
if(times[i] > 2)
{
printf("%c 2\n", process[i]);
sleep(2); //sleep is to simulate the actual running time
times[i] -= 2;
}
else if(times[i] > 0 && times[i] <= 2) //this thread will have finished after this turn
{
printf("%c %lf\n", process[i], times[i]);
sleep(times[i]);
times[i] = 0;
}
StartNext(i); //choose the next thread to run
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
pthread_t threads[5];
int i, status;
if(argc == 6)
{
for(i = 0; i < 5; i++)
times[i] = atof(argv[i + 1]); //input the burst time of each thread
for(i = 0; i < 5; i++)
{
status = pthread_create(&threads[i], NULL, Run, (void *)i); //Create threads
if(status != 0)
{
printf("While creating thread %d, pthread_create returned error code %d\n", i, status);
exit(-1);
}
pthread_join(threads[i], 0); //Join threads
}
}
return 0;
}
The program is directly runnable. Could anyone help me figure it out? Thanks!
Some things I've figured out reading your code:
1. At the beginning of the Run function, you convert tid (which is a pointer to void) directly to int. Shouldn't you dereference it?
It is better to make int turn volatile, so that the compiler won't make any assumptions about its value not changing.
When you call the function sleep the second time, you pass a parameter that has type double (times[i]), and you should pass an unsigned int parameter. A direct cast like (unsigned int) times[i] should solve that.
You're doing the pthread_join before creating the other threads. When you create thread 3, and it enters its busy waiting state, the other threads won't be created. Try putting the joins after the for block.

Resources