I need to write a parallel quick sort in c using pthreads. This is what I did so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h> // sleep()
#include <stdio.h>
#include <stdlib.h> // EXIT_SUCCESS
#include <string.h> // strerror()
#include <errno.h>
#define SIZE_OF_DATASET 6
void* quickSort( void* data);
int partition( int* a, int, int);
struct info {
int start_index;
int* data_set;
int end_index;
};
int main(int argc, char **argv)
{
int a[] = { 7, 12, 1, -2,8,2};
pthread_t thread_id;
struct info *info = malloc(sizeof(struct info));
info->data_set=malloc(sizeof(int)*SIZE_OF_DATASET);
info->data_set=a;
info->start_index=0;
info->end_index=SIZE_OF_DATASET-1;
if (pthread_create(&thread_id, NULL, quickSort, info)) {
fprintf(stderr, "No threads for you.\n");
return 1;
}
pthread_join(thread_id, NULL);
printf("\n\nSorted array is: ");
int i;
for(i = 0; i < SIZE_OF_DATASET; ++i)
printf(" %d ", info->data_set[i]);
return 0;
}
void* quickSort( void *data)
{
struct info *info = data;
int j,l,r;
l = info->start_index;
r = info->end_index;
pthread_attr_t attr;
pthread_t thread_id1;
pthread_t thread_id2;
pthread_attr_init(&attr);
if( l < r )
{
j = partition( info->data_set, l, r);
info->start_index=l;
info->end_index=j-1;
if(info->end_index<0)info->end_index=0;
if (pthread_create(&thread_id1, NULL, quickSort, info)) {
fprintf(stderr, "No threads for you.\n");
return NULL;
}
info->start_index=j+1;
info->end_index=r;
if (pthread_create(&thread_id2, NULL, quickSort, info)) {
fprintf(stderr, "No threads for you.\n");
return NULL;
}
pthread_join(thread_id1, NULL);
pthread_join(thread_id2, NULL);
}
return NULL;
}
int partition( int* a, int l, int r) {
int pivot, i, j, t;
pivot = a[l];
i = l; j = r+1;
while( 1)
{
do ++i; while( a[i] <= pivot && i <= r );
do --j; while( a[j] > pivot );
if( i >= j ) break;
t = a[i]; a[i] = a[j]; a[j] = t;
}
t = a[l]; a[l] = a[j]; a[j] = t;
return j;
}
But inside quick sort function only call first thread only. Cant understand what is been happening here.
Note : serial version of code has been tested. no issue with that
UPDATE:
This is modified version based on John Bollinger's solution. But still second half of array which is taken by newly created thread inside quicksort is not sorted.
int main(int argc, char **argv)
{
int a[] = { 7, 12, 1, -2, 0, 15, 4, 11, 9,5,3,24,5,23,3,1,56,8,4,34,23,51};
struct info *info = malloc(sizeof(struct info));
info->data_set=malloc(sizeof(int)*SIZE_OF_DATASET);
info->data_set=a;
info->start_index=0;
info->end_index=SIZE_OF_DATASET-1;
quickSort(info);
printf("\n\nSorted array is: ");
int i;
for(i = 0; i < SIZE_OF_DATASET; ++i)
printf(" %d ", info->data_set[i]);
return 0;
}
void* quickSort( void *data)
{
struct info *info = data;
struct info *info1 = data;
int j,l,r;
l = info->start_index;
r = info->end_index;
pthread_attr_t attr;
pthread_t thread_id1;
pthread_attr_init(&attr);
if( l < r )
{
j = partition( info->data_set, l, r);
info1->start_index=j+1;
info1->end_index=r;
info1->data_set = info->data_set;
if(info1->end_index<0)info1->end_index=0;
if (pthread_create(&thread_id1, NULL, quickSort, info1)) {
fprintf(stderr, "No threads for you.\n");
return NULL;
}
info->start_index=l;
info->end_index=j-1;
if(info->end_index < 0) info->end_index = 0;
quickSort(info); /* don't care about the return value */
pthread_join(thread_id1, NULL);
}
return NULL;
}
The program is incorrect because your threads all share the same struct info structure describing the sub-problem they are supposed to be working on. They run concurrently (or may do, anyway) and they modify that structure as they proceed, so the values that any particular thread sees are indeterminate.
To resolve this, each quickSort frame must create at least one new struct info, so that the two quickSort() calls it makes in different threads each has its own. As a matter of efficiency, it would also be better to spawn only one additional thread in each quickSort() call. For example:
void* quickSort( void *data)
{
struct info *info = data;
struct info other_info;
/* ... */
/* launch a new thread to handle one partition: */
other_info.start_index = j + 1;
other_info.end_index = r;
other_info.data_set = info->data_set;
if (pthread_create(&thread_id1, NULL, quickSort, &other_info)) {
fprintf(stderr, "No threads for you.\n");
return NULL;
}
/* handle the other partition in the current thread: */
info->start_index = l;
info->end_index = j - 1;
if(info->end_index < 0) info->end_index = 0;
quickSort(info); /* don't care about the return value */
/* after this thread is done, wait for the other thread to finish, too */
pthread_join(thread_id1, NULL);
/* ... */
}
Note that this does not ensure that any particular pair of threads runs concurrently, neither in a multi-core sense nor in a time-slicing sense. That's up to the OS. Certainly, however, the multi-core sense of parallelism applies only where there are in fact multiple cores available on the host machine on which the OS is willing to schedule your process.
Related
#include <math.h>
#include <pthread.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define TASK_LENGHT pow(10, 5) /* 0.1s */
#define TASK_COUNT 100
#define THREADS_CAP 1
struct fifo {
size_t out;
size_t in;
size_t size;
size_t len;
pthread_spinlock_t lock;
char data[1];
};
struct fifo *
fifo_alloc(size_t size)
{
struct fifo *fifo;
fifo = malloc(offsetof(struct fifo, data) + size);
fifo->out = fifo->in = 0;
fifo->size = size;
fifo->len = 0;
pthread_spin_init(&fifo->lock, PTHREAD_PROCESS_PRIVATE);
return fifo;
}
void
fifo_free(struct fifo *fifo)
{
pthread_spin_destroy(&fifo->lock);
free(fifo);
}
size_t
fifo_in(struct fifo *fifo, const void *data, size_t len)
{
size_t total, remaining, l;
pthread_spin_lock(&fifo->lock);
total = remaining = MIN(len, fifo->size - fifo->len);
while (remaining > 0) {
l = MIN(remaining, fifo->size - fifo->in);
memcpy(fifo->data + fifo->in, data, l);
fifo->in = (fifo->in + l) % fifo->size;
fifo->len += l;
data = (char *)data + l;
remaining -= l;
}
pthread_spin_unlock(&fifo->lock);
return total;
}
size_t
fifo_out(struct fifo *fifo, void *data, size_t len)
{
size_t total, remaining, out, l;
pthread_spin_lock(&fifo->lock);
total = remaining = MIN(len, fifo->len);
while (remaining > 0) {
l = MIN(remaining, fifo->size - fifo->out);
memcpy(data, fifo->data + fifo->out, l);
fifo->out = (fifo->out + l) % fifo->size;
data = (char *)data + l;
remaining -= l;
}
fifo->len -= total;
pthread_spin_unlock(&fifo->lock);
return total;
}
int
fifo_is_empty(struct fifo *fifo)
{
int empty;
pthread_spin_lock(&fifo->lock);
empty = fifo->len == 0;
pthread_spin_unlock(&fifo->lock);
return empty;
}
void *
process_task(void *datap)
{
struct fifo *tasks = datap;
int data;
while (1) {
puts("it blocks there");
if (!fifo_is_empty(tasks)) {
puts("this code never execute");
fifo_out(tasks, &data, sizeof(data));
if (data == -1) pthread_exit(0);
printf("%lu => %d\n", pthread_self(), data);
usleep(TASK_LENGHT);
}
puts("this code never execute");
}
}
int
main(void) {
pthread_t threads[THREADS_CAP];
struct fifo *tasks;
int data;
size_t i;
tasks = fifo_alloc(128);
for (i = 0; i < THREADS_CAP; i++)
pthread_create(threads + i, NULL, process_task, &tasks);
for (i = 0; i < TASK_COUNT; i++)
fifo_in(tasks, &i, sizeof(i));
for (i = 0; i < THREADS_CAP; i++) {
data = -1;
fifo_in(tasks, &data, sizeof(i));
}
puts("wait for threads to process all tasks");
for (i = 0; i < THREADS_CAP; i++) {
pthread_join(threads[i], NULL);
}
fifo_free(tasks);
}
I debugged my program and it turned out that it blocks at the pthread_spin_lock in fifo_is_empty. I was trying to recreate this problem with the minimum code needed like this:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define THREADS_CAP 10000
struct test {
pthread_spinlock_t lock;
};
pthread_barrier_t barrier;
int counter = 0;
void *
foo(void *data) {
struct test *test = data;
pthread_barrier_wait(&barrier);
pthread_spin_lock(&test->lock);
counter++;
pthread_spin_unlock(&test->lock);
return 0;
}
int main() {
struct test *test;
pthread_t threads[THREADS_CAP];
size_t i;
test = malloc(sizeof(test));
pthread_barrier_init(&barrier, NULL, THREADS_CAP);
pthread_spin_init(&test->lock, PTHREAD_PROCESS_PRIVATE);
for (i = 0; i < THREADS_CAP; i++)
pthread_create(threads + i, NULL, foo, test);
for (i = 0; i < THREADS_CAP; i++)
pthread_join(threads[i], NULL);
printf("%d\n", counter);
pthread_spin_destroy(&test->lock);
pthread_barrier_destroy(&barrier);
return 0;
}
but i was not able to. I just works for some reason in contrast to my previous code.
Does anyone have an idea what is causing there problem and how to fix it?
The problem took me a while to sort out, but I arrived there through working on a minimal reproducible example. I ultimately cut out everything related to managing the FIFO data, some unneeded functions, and all of the looping, but I found that the failure behavior did not manifest if I changed the definition of struct fifo.
Finally, I realized that the problem is here:
struct fifo *tasks;
// ...
pthread_create(threads + i, NULL, process_task, &tasks);
in conjunction with
void *process_task(void *datap) {
struct fifo *tasks = datap;
Bottom line: you are passing the address of your tasks pointer, a pointer to a pointer, but then your thread function tries to interpret it as a single pointer. Undefined behavior results.
The correction is to pass tasks itself to the thread, not &tasks:
pthread_create(threads + i, NULL, process_task, tasks);
Your program has other problems, but that resolves the one you asked about.
Say I have a array of array of struct pollfds
int Pipes = 2;
struct pollfd pollFD[nArguments][nPipes];
nArguments is a variable that is determined inside the main, I can't know it's value before run time and I need to place this array of pollfd inside a struct to pass it as an argument to a thread.
How can I convert it to
struct pollfd **pollFDConverted;
Edit: I found the solution at this link:Malloc a 2D array in C
One can do something like this:
#include <stdio.h>
#include <pthread.h>
#include <poll.h>
#include <stdlib.h>
struct pollFDWrapper {
struct pollfd ** arr;
size_t nRows;
size_t nCols;
};
static void* thread_handler(void *arg)
{
struct pollFDWrapper * wrapper = arg;
for(size_t i = 0; i < wrapper->nRows; ++i)
for(size_t j = 0; j < wrapper->nCols; ++j) {
(void) wrapper->arr[i][j];
}
return NULL;
}
int main(void)
{
struct pollFDWrapper * arg = malloc(sizeof *arg);
//Dimensions can be obtained as required, just for demonstration
arg->nRows = 3;
arg->nCols = 5;
arg->arr = calloc(sizeof arg->arr[0], arg->nRows); //create array of pointers
for(size_t i = 0; i < arg->nRows; ++i) {
arg->arr[i] = calloc(sizeof arg->arr[i][0], arg->nCols); //crate array
}
pthread_t thread;
if (pthread_create(&thread, NULL, thread_handler, arg) != 0)
{
perror("pthread_create");
exit(EXIT_FAILURE);
}
if (pthread_join(thread, NULL) != 0)
{
perror("pthread_join");
exit(EXIT_FAILURE);
}
for(size_t i = 0; i < arg->nRows; ++i) {
free(arg->arr[i]); //free array
}
free(arg->arr); //free ptr to array
free(arg); //free the encapsualting struct
return 0;
}
struct pollFDWrapper encapsulates the information needed for manipulating the struct pollfd ** arr, including the dimensions of the 2-D array and can be passed around, even to a thread, just like a regular pointer.
How can I convert it to
struct pollfd **pollFDConverted;
You don't want to do that, the compiler needs to know the number of elements of the last dimension, on the other hand a thread handler uses a pointer to void as parameter and you can pass whatever you want to it (except a pointer to function).
Just convert to the proper type (in this case I'm reading a 2D array of ints via a pointer to an array of n ints, you can adapt this to your struct):
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
enum {rows = 2, cols = 3};
static void *thread_handler(void *arg)
{
int (*arr)[cols] = arg;
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
printf("%d ", arr[row][col]);
}
printf("\n");
}
return NULL;
}
int main(void)
{
int arr[rows][cols] = {{1, 2, 3}, {4, 5, 6}};
pthread_t thread;
if (pthread_create(&thread, NULL, thread_handler, arr) != 0)
{
perror("pthread_create");
exit(EXIT_FAILURE);
}
if (pthread_join(thread, NULL) != 0)
{
perror("pthread_join");
exit(EXIT_FAILURE);
}
return 0;
}
I can't figure out what I am doing wrong with my pointers. It is causing a segmentation fault. I am convinced the problem is rooted in my use of the array of pointers I have and the pthread_join I am using.
The goal is to read multiple integers into a gcc compiler, then print out the integer with all its factors, like this, 12: 2 2 3
I created a struct containing an int array to store the factors of each integer as the factor function pulls it apart and a counter(numfact) to store how many factors there are stored in the array.
I commented out the section at the bottom that prints out the factors.
I think the problem is how I am trying to store the output from the pthread_join in the pointer array, ptr[]. Whenever I comment it out, it does not get the segmentation error.
Either I have my pointers screwed up in a way I don't understand or I can't use an array of pointers. Either way, after many hours, I am stuck.
Please help.
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <stdlib.h>
struct intfact
{
long int factors[100];
int numfact;
};
struct intfact *factor(long int y)
{
struct intfact threadfact;
threadfact.numfact = 0;
// Store in struct the number of 2s that divide y
while (y % 2 == 0)
{
threadfact.factors[threadfact.numfact] = 2;
threadfact.numfact++;
y = y/2;
}
// Store in struct the odds that divide y
for (int i = 3; i <= floor(sqrt(y)); i = i+2)
{
while (y % i == 0)
{
threadfact.factors[threadfact.numfact] = i;
threadfact.numfact++;
y = y/i;
}
}
// Store in struct the primes > 2
if (y > 2)
{
threadfact.factors[threadfact.numfact] = y;
threadfact.numfact++;
}
struct intfact *rtnthred = &threadfact;
return rtnthred;
}
/* Trial Division Function */
void *divde(void *n)
{
long int *num = (long int *) n;
struct intfact *temp = factor(*num);
return temp;
}
/* Main Function */
int main(int argc, char *argv[])
{
pthread_t threads[argc-1];
void *ptr[argc-1];
/* loop to create all threads */
for(int i=0; i < argc; i++)
{
long temp = atol(argv[i+1]);
pthread_create(&threads[i], NULL, divde, (void *) temp);
}
/* loop to join all threads */
for(int i=0; i < argc; i++)
{
pthread_join(threads[i],(void *) ptr[i]); //THIS POINTER IS THE PROBLEM
}
/* loops to print results of each thread using pointer array*/
//for(int i = 0; i < argc; i++)
//{
// printf("%s: ", argv[i+1]); /* print out initial integer */
// struct intfact *temp = (struct intfact *) ptr[i]; //cast void pointer ptr as struct intfact pointer
// printf("%d", temp->numfact);
//for(int j = 0; j < temp->numfact; j++) /*(pull the numfact(count of factors) from the struct intfact pointer??)*/
//{
// printf("%d ", temp->factors[j]); /* print out each factor from thread struct */
//}
}
}
In my Linux) terminal this code is stored in p3.c
"./p3 12" should yeild "12: 2 2 3"
For starters:
Here
long temp = atol(argv[i+1]);
pthread_create(&threads[i], NULL, divde, (void *) temp);
you define a long int and pass it as argument to the thread. For example 12
Inside the thread function then
void *divde(void *n)
{
long int *num = (long int *) n;
you treat the long int passed in as pointer to long int.
And then here dereference it
... = factor(*num);
So this *num for example would become *12. That is referencing memory address 12 to read out its content and pass it to factor). Aside the fact that this mostly likely is an invalid address, there would be nothing relevant store, at least nothing your code defined.
To (more or less fix) this do
void *divde(void *n)
{
long int num = (long int) n;
... = factor(num);
The second issues is mentioned in the comment: Multiple threads to find prime factors of integers, segmentation fault
The problem you are trying to solve is a special case of parallel programming, namely that the tasks to be run in parallel are completely independent. In such cases it makes sense to give each task its own context. Here such a context would include the
thread-id,
the thread specific input
as well as its specific output.
In C grouping variables can be done using structures, as your implementation already comes up with for the output of the tasks:
struct intfact
{
long int factors[100];
int numfact;
};
So what is missing is thread-id and input. Just add those for example like this.
/* group input and output: */
struct inout
{
long int input;
struct intfact output;
};
/* group input/output with thread-id */
struct context
{
pthread_t thread_id;
struct inout io;
};
Now before kicking off the threads define as many contexts as needed:
int main(int argc, char *argv[])
{
size_t num_to_process = argv - 1;
struct context ctx[num_to_process];
then create the threads passing in what is needed, that is input along with space/memory for the output:
for (size_t i = 0; i < num_to_process ; i++)
{
ctx[i].io.input = atol(argv[i]);
pthread_create(&ctx[i].thread_id, NULL, divide, &ctx[i].io);
}
Inside the thread function convert the void-pointer received back to its real type:
void *divide(void * pv)
{
struct inout * pio = pv; /* No cast needed in C. */
Define the processing function to take a pointer to the context specific input/output variables:
void factor(struct inout * pio) /* No need to return any thing */
{
/* Initialise the output: */
pio->output.numfact = 0;
/* set local copy of input: */
long int y = pio->input; /* One could also just use pio->input directly. */
Replace all other occurrences of threadfact by pio->output.
Use
return;
}
to leave the processing function.
Then inside the thread function call the processing function:
factor(pio);
Use
return NULL;
}
to leave the thread function.
In main() join without expecting any result from the threads:
/* loop to join all threads */
for (size_t i = 0; i < num_to_process; i++)
{
pthread_join(ctx[i].thread_id, NULL);
}
Putting this all together:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <math.h>
struct intfact
{
long int factors[100];
size_t numfact;
};
/* group input and output: */
struct inout
{
long int input;
struct intfact output;
};
/* group input/output with thread-id */
struct context
{
pthread_t thread_id;
struct inout io;
};
void factor(struct inout * pio)
{
/* Initialise the output: */
pio->output.numfact = 0;
/* set local copy of input: */
long int y = pio->input; /* One could also just use pinout->input directly. */
if (0 == y)
{
return; /* Nothing to do! */
}
// Store in struct the number of 2s that divide y
while (y % 2 == 0)
{
pio->output.factors[pio->output.numfact] = 2;
pio->output.numfact++;
y = y/2;
}
// Store in struct the odds that divide y
for (int i = 3; i <= floor(sqrt(y)); i = i+2)
{
while (y % i == 0)
{
pio->output.factors[pio->output.numfact] = i;
pio->output.numfact++;
y = y/i;
}
}
// Store in struct the primes > 2
if (y > 2)
{
pio->output.factors[pio->output.numfact] = y;
pio->output.numfact++;
}
return;
}
void *divide(void * pv)
{
struct inout * pio = pv; /* No cast needed in C. */
factor(pio);
return NULL;
}
int main(int argc, char *argv[])
{
size_t num_to_process = argc - 1;
struct context ctx[num_to_process];
for (size_t i = 0; i < num_to_process; i++)
{
ctx[i].io.input = atol(argv[i+1]);
if (!ctx[i].io.input)
{
fprintf(stderr, "COnversion to integer failed or 0 for '%s'\n", argv[i]);
}
pthread_create(&ctx[i].thread_id, NULL, divide, &ctx[i].io);
}
/* loop to join all threads */
for (size_t i=0; i < num_to_process; i++)
{
pthread_join(ctx[i].thread_id, NULL);
}
/* loops to print results of each thread using pointer array*/
for(size_t i = 0; i < num_to_process; i++)
{
printf("%ld: ", ctx[i].io.input); /* print out initial integer */
printf("%zu factors --> ", ctx[i].io.output.numfact);
for(size_t j = 0; j < ctx[i].io.output.numfact; j++)
{
printf("%ld ", ctx[i].io.output.factors[j]); /* print out each factor from thread struct */
}
putc('\n', stdout);
}
}
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]);
}
}
I'm trying to create a thread for the function *producer, but the line for creating the thread is showing in error. I starred the line, but I'm having trouble figuring out what is wrong with it...
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#define TOTALLOOPS 100 /*Num of loops run*/
#define NUMOFPAIRS 4 /*For each 1 it produces 1 consumer and 1 producer*/
typedef struct {
int q[NUMOFPAIRS];
int head;
int tail;
int full;
int empty;
pthread_mutex_t mut; /*Creates a mutex Lock*/
pthread_cond_t notFull; /*Creates conditional*/
}Queue;
int main(void)
{
Queue buf; /* Declare and initialize parts of struct */
buf.head = 0;
buf.tail = 0;
buf.full = 0;
buf.empty = 0;
pthread_mutex_init(&buf.mut, NULL);/*intitializes mutex for struct*/
//pthread_cond_init(&buf.nutFull, NULL);
pthread_t pro;
**pthread_create(&pro, NULL, producer, &buf);**
pthread_mutex_destroy(&buf.mut);
return 0;
}
void *producer(int x, Queue *buf){
int id = x;
int i;
for(i = 0; i < TOTALLOOPS; i++){
while(buf->full == 1){
//do nothing
}
mClock();
printf(" - Producer%d:\n", id);
}
}
void* consumer(int x, Queue *buf){
int id = x;
int i;
for(i = 0; i < TOTALLOOPS; i++){
while(buf->empty == 1){
//do nothing
}
mClock();
printf(" - Consumer%d:\n", id);
}
}
void addToQueue(Queue *buf, int x){
//Checks if empty flag is triggered, if so un triggers
if(buf->empty) buf->empty = 0;
buf->q[buf->tail] = x;
if(buf->tail == 3) buf->tail = 0; /*Resets to beginning if at end*/
else buf->tail += 1; /*else just moves to next*/
//Checks if full flag needs to be triggered, if so triggers
if(buf->tail == buf->head) buf->full = 1;
}
int removeFromQueue(Queue *buf){
int t; /*return value from queue*/
//Checks if full flag is triggered, if so un triggers
if(buf->full == 1)buf->full = 0;
t = buf->q[buf->head];
if(buf->head == 3) buf->head = 0; /*Resets to beginning if at end*/
else buf->head += 1; /*else just moves to next*/
//Checks if full flag needs to be triggered, if so triggers
if(buf->tail == buf->head) buf->empty = 1;
return t;
}
void mClock(){
struct timeval tv;
gettimeofday(&tv,NULL);
long time_in_micros = 1000000 * tv.tv_sec + tv.tv_usec;
printf("%u", time_in_micros);
}
You have to declare producer before the pthread_create call.
void *producer(int x, Queue *buf);
should show up first.
Likewise, mClock has to be declared first.
Also, the function should only take one argument
I don't see where you're calling the initializers for pthread_mutex_t mut and pthread_cond_t notFull in your structure anywhere.
PTHREAD_MUTEX
PTHREAD_COND
Also, you need to change the order of declaration of your functions, or add prototypes to the top of the file.