Multithreading in C, Fibonacci Program - c

I have newly started studying operating systems and creating processes/threads on Linux system by using C programming language(thats what is expected us to use) but I have some problems on the code that I've been trying to write:
Here is my code written on an Ubuntu system:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
int total = 0;
typedef struct
{
int start;
int end;
int threadNo;
}THREAD_PARAMETERS;
void *work(void *parameters);
int threadCount;
int main(int argc, char* argv[])
{
printf("please give the number of terms you want to diplay..");
scanf("%d", &threadCount);
pthread_t tid[threadCount];
pthread_attr_t attr[threadCount];
THREAD_PARAMETERS* lpParameter;
int n;
lpParameter = malloc(sizeof(THREAD_PARAMETERS)* threadCount);
int i=0;
for(i=0; i<threadCount; i++)
{
lpParameter[i].start = 0;
lpParameter[i].end = 1;
lpParameter[i].threadNo = i + 1;
pthread_attr_init(&attr[i]);
pthread_create(&tid[i],&attr[i],work,&lpParameter[i]);
}
for(i=0; i<threadCount; i++)
{
pthread_join(tid[i],NULL);
}
return 1;
}
void fibonacci(int a)
{
int prev_term = 0, current_term = 1, next_term = 0;
if(a==0){
printf("%d\n",prev_term);
}
else if(a==1){
next_term=current_term+prev_term;
printf("%d\n",current_term);
prev_term=current_term;
current_term=next_term;
void *work(void * parameters)
{
THREAD_PARAMETERS* param = (THREAD_PARAMETERS*)parameters;
fibonacci(threadCount);
pthread_exit(0);
}
The problem is the program counts with the threadCount variable but what the program prints is just threadCount times zeros.
And the main question is how can I make each of the threads write "only one term" of the Fibonacci series depending on the number of terms (which is at the same time the number of threads) entered by the user? Is there any other more logical way to implement this kind of program?

You are using lpParameter[i] as the argument to each thread's work, but then ignore its contents when calling fibonacci.

Related

Can I use pthreads over the same function on C?

I have a doubt that might be silly guys. I am having a function to calculate some mathematical formulas as an example.
# include <stdio.h>
# include <time.h>
# include <stdlib.h>
# include <pthread.h>
# include <unistd.h>
# include <math.h>
pthread_mutex_t a_mutex = PTHREAD_MUTEX_INITIALIZER;
volatile long int a = 0;
void threadOne(void *arg)
{
int i;
long int localA = 0;
for (i = 1; i < 50000000; i++)
{
localA = localA + i*a*sqrt(a);
}
pthread_mutex_lock(&a_mutex);
a = a + localA;
pthread_mutex_unlock(&a_mutex);
}
void threadTwo(void *arg)
{
int i;
long int localA = 0;
for (i = 50000000; i <= 100000000; i++)
{
localA = localA + i*a*sqrt(a);
}
pthread_mutex_lock(&a_mutex);
a = a + localA;
pthread_mutex_unlock(&a_mutex);
}
int main (int argc, char **argv)
{
pthread_t one, two;
int i;
pthread_create(&one, NULL, (void*)&threadOne, NULL);
pthread_create(&two, NULL, (void*)&threadTwo, NULL);
pthread_join(one, NULL);
pthread_join(two, NULL);
}
Now this is an example I found, I am having two functions with a thread each one, so one is calculated on a different thread. But can I have just one function and then have two threads to one function, so the function runs twice with different data?. My idea is this one: I am having just one function that can have two different sets of data, then the function can run with the first set or the second set depending on the thread is running.
But is this possible even?. I want to avoid something as copying the function twice as here.
Lets use say that I only keep the function
void threadOne(void *arg)
But I run it twice using different threads at same time with different data, this can be achieved or I am just being silly?.
Yes, this can be done by making use of the argument to the thread function.
Each thread needs to loop over a range of values. So create a struct definition to contain the min and max values:
struct args {
int min;
int max;
};
Define a single thread function which converts the void * argument to a pointer to this type and reads it:
void *thread_func(void *arg)
{
struct args *myargs = arg;
int i;
long int localA = 0;
for (i = myargs->min; i < myargs->max; i++)
{
localA = localA + i*a*sqrt(a);
}
pthread_mutex_lock(&a_mutex);
a = a + localA;
pthread_mutex_unlock(&a_mutex);
return NULL;
}
(Note that the function needs to return a void * to conform to the interface pthread_create expects.)
Then in your main function create an instance of this struct for each set of arguments, and pass that to pthread_create:
int main (int argc, char **argv)
{
pthread_t one, two;
struct args args1 = { 1, 50000000 };
struct args args2 = { 50000000 , 100000000 };
pthread_create(&one, NULL, thread_func, &args1);
pthread_create(&two, NULL, thread_func, &args2);
pthread_join(one, NULL);
pthread_join(two, NULL);
}

Pthread Programming Short Example

I am having some trouble understanding this code since I am new to pthread programming. From what I understand, we create N threads and execute the run function on them, which only prints the thread number. Am I missing something?
Is there any advantage of using snprintf (with buffers) over printf in this particular case? Could this program be improved any further?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static int N = 5;
static void* run(void *arg)
{
int *i = (int *) arg;
char buf[123];
snprintf(buf, sizeof(buf), "thread %d", *i);
return buf;
}
int main(int argc, char *argv[])
{
int i;
pthread_t *pt = NULL;
for (i = 0; i < N; i++) {
pthread_create(pt, NULL, run, &i);
}
return EXIT_SUCCESS;
}
First of all, your threads return garbage. Deferencing the pointer returned would be Undefined Behaviour because it points to storage that no longer exists after the function returns. Good thing nothing used the pointer.
Next, the threads don't print anything because snprintf outputs to an array, not stdout.
Furthermore, the threads would print garbage if you switched to printf because the same pointer is passed to to all threads.
And that's assuming the threads have a chance to run since main doesn't wait for the threads to finish. You gotta join them.
Fixed:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define N 5
static void *run(void *arg) {
size_t job = *(size_t*)arg;
printf("Job %zu\n", job);
return NULL;
}
int main(int argc, char *argv[]) {
size_t jobs[N];
pthread_t threads[N];
for (size_t i=0; i<N; ++i) {
jobs[i] = i;
pthread_create(threads+i, NULL, run, jobs+i);
}
for (size_t i=0; i<N; ++i) {
pthread_join(threads[i]);
}
return EXIT_SUCCESS;
}
It's also common to pass an integer cast to a pointer.
#include <inttypes.h>
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
static void *run(void *arg) {
size_t job = *(uintptr_t*)arg;
printf("Job %" PRIuPTR "\n", job);
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t threads[N];
for (uintptr_t i=0; i<N; ++i) {
pthread_create(threads+i, NULL, run, (void*)i);
}
for (uintptr_t i=0; i<N; ++i) {
pthread_join(threads[i]);
}
return EXIT_SUCCESS;
}

How can I pass an array as a return value through a thread?

I am working on a function that creates a thread and calculates the Fibonacci sequence to a certain user inputted value. For example, if a user enters 5, the output will be: 0 1 1 2 3 5
However, the sequence must be calculated in the created thread, and the results have to be printed out after the thread is exited.
I can create the thread and calculate the sequence, but I need to pass the array fibSequence[] back to the original thread using pthread_exit and pthread_join. I am having trouble figuring out the syntax and can't find any examples of people passing arrays through.
What I have so far:
I created a function fib_runner() that is called by a newly created thread. The Fibonacci sequence is created and placed into the array fibSequence[]. I need to pass this back through to the main function. I am temporarily printing out the sequence in the function, but it should be printed in the main.
Thank you!
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* fib_runner(void* arg)
{
int *limit_ptr = (int*) arg;
int limit = *limit_ptr;
int fibSequence[limit];
int size = sizeof(fibSequence)/sizeof(fibSequence[0]);
printf("Size: %d\n", size);
fibSequence[0] = 0;
fibSequence[1] = 1;
for (int i = 2; i <= size; i++)
{
fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
}
for (int i = 0; i <= size; i++)
{
printf("%d ", fibSequence[i]);
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
int limit;
printf("Enter Number: ");
scanf("%d", &limit);
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fib_runner, &limit);
pthread_join(tid, NULL);
}
Currently, the array is a local variable, so it would go out of scope when the function exits. You need to dynamically allocate memory for it instead:
int *fibSequence = malloc(sizeof(int) * limit);
Then return this pointer from the function:
return fibSequence;
In your main function, you then pass the address of a pointer to receive this value. Then you can print the content of the array. When you're done, be sure to free it:
int *fibSequence;
pthread_join(tid, (void **)&fibSequence);
for (int i = 0; i < limit; i++)
{
printf("%d ", fibSequence[i]);
}
free(fibSequence);
Also, you don't need size in your thread function, since it is the same as limit, and the way you currently calculate it won't work anyway since you now have a pointer instead of an array. Your loop limit in fib_runner also goes one past the end of the array. The exit condition should be i < size, not i <= size.
you have to pass in a value of void * to pthread_exit which is pthread_exit(( void * ) &fibSequence, once that function is called the passed in value will populate the second argument to pthread_join, the second argument will be a pointer to a pointer void ** it will hold the values passed in to pthred_exit
All the threads running within a process share the same address space, file descriptors, stack and other process related attributes.
Threads are sharing memory by definition, they do not own anything except stack and local variables;
If you make fibSequence[limit] global then all threads will have access to it.
You can also declare fibSequence[limit] on the stack in main and pass pointer to it to your thread.
To pass multiple arguments it is convenient to wrap them up in a structure.
The solutions below employ:
struct arg_struct {
int limit;
int *ptrFib;
}args;
Program:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct arg_struct {
int limit;
int *ptrFib;
}args;
void* fib_runner(void* arg)
{
struct arg_struct *a = (struct arg_struct *) arg;
int size = a->limit;
int * fibSequence = a->ptrFib;
fibSequence[0] = 0;
fibSequence[1] = 1;
for (int i = 2; i <= size; i++){
fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
int limit;
printf("Enter Number: ");
scanf("%d", &limit);
int fibSequence[limit];
struct arg_struct argF;
argF.limit = limit;
argF.ptrFib = fibSequence;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fib_runner, &argF);
pthread_join(tid, NULL);
for (int i = 0; i <= limit; i++){
printf("%d ", fibSequence[i]);
}
}
Output:
Enter Number: 5
0 1 1 2 3 5
The solution with global variable argF is of course possible but it is less elegant.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct arg_struct {
int limit;
int *ptrFib;
}args;
struct arg_struct argF;
void* fib_runner()
{
int size = argF.limit;
int * fibSequence = argF.ptrFib;
fibSequence[0] = 0;
fibSequence[1] = 1;
for (int i = 2; i <= size; i++){
fibSequence[i] = fibSequence[i-1] + fibSequence[i-2];
}
pthread_exit(0);
}
int main(int argc, char **argv)
{
int limit;
printf("Enter Number: ");
scanf("%d", &limit);
int fibSequence[limit];
argF.limit = limit;
argF.ptrFib = fibSequence;
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, fib_runner, NULL);
pthread_join(tid, NULL);
for (int i = 0; i <= limit; i++){
printf("%d ", fibSequence[i]);
}
}

How can I have a shared counter in multithreading using structs?

I'm pretty new with multithreading and I was trying to increment a shared counter whithout using global variables, my goal is try to maximize the concurrency among the different threads and increment the variable until a number I give in arguments... Sorry if is a lame question, but I would like a help here, when I compile my code and run it i get a segmentation fault... I think the error is in the variable count that I create and the shared counter!
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex;
typedef struct {
long *cnt; /* pointer to shared counter */
long n; /* no of times to increment */
int nr;
pthread_t id; /* application-specific thread-id */
} targ_t;
void *sfun(void *arg) {
targ_t *est = (targ_t *) arg;
here:
pthread_mutex_lock(&mutex);
(*(est->cnt))++;
pthread_mutex_unlock(&mutex);
if(*(est->cnt)<est->n)
goto here;
return NULL;
}
int main(int argc, char *argv[]){
targ_t real[3];
int c=0;
long count=0;
real[0].cnt=&count;
pthread_mutex_init(&mutex, NULL);
for(c=0;c<3;c++){
real[c].n=atoi(argv[1]);
real[c].nr=c+1;
pthread_create(&real[c].id,NULL,&sfun,&real[c]);
}
for(c=0;c<3;c++){
pthread_join(real[c].id,NULL);
}
pthread_mutex_destroy(&mutex);
printf("OVERALL %lu\n", count);
return 0;
}
TY in advance.
There are a number of problems identified in the comments:
Writing out loops with a label here: and a goto here; is not a particularly good idea. There are occasions (some, but not many, occasions) when it is appropriate to use goto — this is not one of those rare occasions.
You don't actually validate that your code was given an argv[1] to convert; could it be that you forgot to pass that argument?
However, your primary problem is that you initialize real[0].cnt but you do not initialize real[1].cnt or real[2].cnt, so those threads are accessing who knows what memory — it might be that they're using null pointers, or they might be pointers to anywhere in memory, allocated or not, aligned or not, writable or not.
You're also missing <stdlib.h>
You're testing *(est->cnt) outside the scope of mutual exclusion.
This code fixes those and some other issues:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
typedef struct
{
long *cnt; /* pointer to shared counter */
long n; /* no of times to increment */
int nr;
pthread_t id; /* application-specific thread-id */
} targ_t;
static void *sfun(void *arg)
{
targ_t *est = (targ_t *)arg;
while (1)
{
pthread_mutex_lock(&mutex);
long cval = *est->cnt;
if (cval < est->n)
++*est->cnt;
pthread_mutex_unlock(&mutex);
if (cval >= est->n)
break;
}
return NULL;
}
int main(int argc, char *argv[])
{
targ_t real[3];
long count = 0;
if (argc != 2)
{
fprintf(stderr, "Usage: %s count\n", argv[0]);
return(EXIT_FAILURE);
}
for (int c = 0; c < 3; c++)
{
real[c].cnt = &count;
real[c].n = atoi(argv[1]);
real[c].nr = c + 1;
if (pthread_create(&real[c].id, NULL, &sfun, &real[c]) != 0)
break;
}
for (int c = 0; c < 3; c++)
pthread_join(real[c].id, NULL);
pthread_mutex_destroy(&mutex);
printf("OVERALL %lu\n", count);
return 0;
}
When run (for example, the program is pth59):
$ pth59 100
OVERALL 100
$
Before moving the test (now on cval) so that the read of *est->cnt was done inside the scope of the mutex, I got an output OVERALL 102 from the same command line. It is important to access shared variables with proper mutual exclusion, even if it is read-only access.

Multi-threaded random number generator keeps getting a SegFault at initstate_r function

I'm trying to develop a program in C that will generate a given number of random integers. It is supposed to use a given number of threads to speed this up. I found out that the regular random function won't work with threads and am now using random_r instead. I keep getting a SegFault at the initstate_r function, which doesn't make sense because I'm trying to initialize variables, not access them. Can anyone tell me what I'm doing wrong here? (The initstate_r function needs to stay in the generateRandomNumbers function.)
Here is the code:
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h> // must include stdio for pvm3.h to compile correctly
#include <sys/times.h> /* for times system call */
#include <sys/time.h> /* for gettimeofday system call */
#include <pthread.h>
/*#define DEBUG 1*/
#define RANDOM_SEED 12345678
//The main work routine
//void generateRandomNumbers(long long);
void *generateRandomNumbers(void *);
double getMilliSeconds();
/* The main work routine */
//void generateRandomNumbers(long long int count)
void *generateRandomNumbers(void *arg)
{
struct random_data buf;
int32_t result;
char rand_statebuf;
printf("hold 1\n");
// This is the function that gives me a SegFault
initstate_r(RANDOM_SEED, &rand_statebuf, 128, &buf);
printf("hold 2\n");
long long int* count = (long long int*) arg;
//printf("Count for thread ID# %ld is %lld\n", pthread_self(), *count);
long long int i;
//long int x;
srandom_r(RANDOM_SEED, &buf);
for (i = 0; i < *count; i++) {
random_r(&buf, &result);
#ifdef DEBUG
printf("%ld\n", result);
#endif
}
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
long long int count, newCount;
int numThreads;
//pthread_t *tids;
double timeStart = 0;
double timeElapsed = 0;
if (argc < 3) {
fprintf(stderr, "Usage: %s <n>\n" ,argv[0]);
exit(1);
}
sscanf(argv[1],"%lld",&count); /* lld for long long int */
sscanf(argv[2],"%d",&numThreads);
pthread_t tids[numThreads];
newCount = count/numThreads;
timeStart = getMilliSeconds(); //And we are off
int i;
for (i=0; i<numThreads; i++)
{
pthread_create(&tids[i], NULL, generateRandomNumbers, (void *) &newCount);
//pthread_join(tids[i], NULL);
}
int j;
for (j=0; j<numThreads; j++)
{
pthread_join(tids[j], NULL);
}
//generateRandomNumbers(count);
printf("generated %lld random numbers\n", count);
timeElapsed = getMilliSeconds() - timeStart;
printf("Elapsed time: %lf seconds\n",(double)(timeElapsed/1000.0));
fflush(stdout);
exit(0);
}
The problem is, initstate_r's second param is supposed to be a char*,
You do:
char rand_statebuf;
printf("hold 1\n");
// This is the function that gives me a SegFault
initstate_r(RANDOM_SEED, &rand_statebuf, 128, &buf);
You pass it a pointer to 1 character which meets the requirement for a character pointer, however you need much more space than just one character. It should be:
char rand_statebuf[128];
initstate_r(RANDOM_SEED,rand_statebuf,sizeof(rand_statebuf),&buf);

Resources