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.
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.
I am trying to create a producer consumer queue, using mutex locks, creating busy waiting between threads. My Main file takes X amount of integer arguments, pushes them onto a BOUNDED BUFFER of size 50. I am using a while loop to do this since you do not know the amount before hand. I am not sure when and where to create my producer thread.
NOTE: Main is a "producer" in the sense it fills the buffer, but my actual producer function is going to pass onto my consumer function later in my code, so disregard the names. Main is going to "Produce" numbers by pushing and producer is going to pop those numbers for later use. My question is where and when do I make my Pthread_create in my code for producer and am I using the Mutex locks correctly to have synchronization between the two threads?
#include <pthread.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#define BUFFER_SIZE (50)
typedef struct {
int buffer[BUFFER_SIZE];
int count;
int top;
int next;
pthread_mutex_t count_lock;
} prodcons;
void pc_init(prodcons *pc);
int pc_pop(prodcons *pc);
void pc_push(prodcons *pc, int val);
void factor2pc(prodcons *pc, int number);
void *producer(void *data);
void *consumer(void *data);
int main(int argc, char *argv[])
{
int index = 1;
int num;
prodcons pc_nums;
//pthread_t tid[argc - 1];
pthread_t tid;
pthread_attr_t attr;
if (argc < 2) {
fprintf(stderr, "usage: No arguments\n");
return -1;
}
if (atoi(argv[1]) <= 0)
{
fprintf(stderr, "%d not > 0 or you must provide a positive integer.\n", atoi(argv[1]));
return -1;
}
pthread_attr_init(&attr);
pc_init(&pc_nums);
//DO I PUT THIS HERE or WHILE LOOP?
pthread_create(&tid, &attr, *producer, &pc_nums);
while (index < argc)
{
num = atoi(argv[index]);
pc_push(&pc_nums, num);
index++;
}
}
void *producer(void *data)
{
prodcons *dataStruct = data;
while (dataStruct->count < BUFFER_SIZE)
{
number = pc_pop(data);
//This print is just here to make sure I am correctly "poping" from buffer
printf("%d\n", number);
}
}
void pc_init(prodcons *pc)
{
pc->count = 0;
pc->top = 0;
pc->next = 0;
if (pthread_mutex_init(&pc->count_lock, NULL) != 0)
{
printf("\n mutex init has failed\n");
}
}
int pc_pop(prodcons *pc)
{
int val;
pthread_mutex_lock(&pc->count_lock);
if (pc->count > pc->top)
{
val = pc->buffer[pc->count];
printf("%d\n", val);
pc->buffer[pc->count] = 0;
pc->count--;
}
pthread_mutex_unlock(&pc->count_lock);
return val;
}
void pc_push(prodcons *pc, int val)
{
pthread_mutex_lock(&pc->count_lock);
if (pc->count < BUFFER_SIZE)
{
pc->buffer[pc->count] = val;
pc->count++;
}
pthread_mutex_unlock(&pc->count_lock);
}
My question is where and when do I make my Pthread_create in my code for producer and am I using the Mutex locks correctly to have synchronization between the two threads?
As long as all is properly initialized and synchronized, you can put the pthread_create() call wherever you want, including where it's placed in the given program. But at least two things are wrong:
pc_pop() behaves undefined (by return of an uninitialized value) if there is no number in the buffer to pop.
Since dataStruct->count is accessed by producer() without locking, the declaration should be _Atomic(int) count;.
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);
}
}
So i implemented a hashtable with separate chaining for a struct called Objective, so that i could perform some operations on said Objectives. Currently i have this:
Hashtable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*Using separate chaining to store the obejctives*/
typedef struct Objective{
char name [8000];
unsigned long id, duration, deps [9000];
int hasDeps;
}*pObjective;
typedef struct nodehash{ /*Node of list*/
pObjective obj;
struct nodehash*next;
}*link;
void Init(int M);
int search(unsigned long id);
void insert(pObjective o);
void delete(unsigned long id);
link insertBegin(link h, pObjective obj);
int searchList(link h, unsigned long id);
link removeList(link h, unsigned long id);
pObjective searchObj(unsigned long id);
pObjective searchObjAux(link h, unsigned long id);
#endif
Objectives.c:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "OBJECTIVES.h"
/*Checks if all inserted dependencies already exist*/
int existDeps(unsigned long dep[9000]){
int i, count = 0;
for(i = 0; i < 9000; i++){
if(search(dep[i]) != 0)
count++;
}
return count;
}
/ *Adds objective with dependencies*/
void addObj(unsigned long id, char name [8000], unsigned long duration,
unsigned long dep[9000]){
int i;
pObjective obj = malloc(sizeof(pObjective));
obj->id = id;
obj->duration = duration;
obj->hasDeps = 1;
strcpy(name, obj->name);
for(i = 0; i < 9000; i++){
obj->deps[i] = dep[i];
}
if(search(id) != 0)
printf("id already exists\n");
else if(existDeps(dep) != 0)
printf("no such task\n");
else
insert(obj);
free(obj);
}
/*Adds objective with no dependencies*/
void addNoDeps(unsigned long id, char name [8000], unsigned long
duration){
pObjective obj = malloc(sizeof(pObjective));
obj->id = id;
obj->duration = duration;
obj->hasDeps = 1;
strcpy(name, obj->name);
if(search(id) != 0)
printf("id already exists\n");
else
insert(obj);
free(obj);
}
/*Removes objective with no dependencies*/
void removeObj(unsigned long id){
int res = search(id);
pObjective obj = searchObj(id);
if(res == 0)
printf("no such task\n");
else if(obj->hasDeps == 1)
printf("task with dependencies\n");
else
delete(id);
}
Objectives.h:
#ifndef OBJECTIVES_H
#define OBJECTIVES_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "HASHTABLE.h"
/*Functions to work with objectives*/
int existDeps(unsigned long dep[9000]);
void addObj(unsigned long id, char name [8000], unsigned long duration,
unsigned long dep[9000]);
void addNoDeps(unsigned long id, char name [8000], unsigned long
duration);
void removeObj(unsigned long id);
#endif
Hashtable.c:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "HASHTABLE.h"
#define hash(A,B) (A%B) /*Hash function*/
static link *heads;
static int M;
/*Initiates hashtable with size m*/
void Init(int m){
int i;
M = m;
heads = (link*)malloc(M*sizeof(link));
for(i = 0; i < M; i++)
heads[i] = NULL;
}
/*Searches objective with said id*/
int search(unsigned long id){
int i = hash(id, M);
return searchList(heads[i], id);
}
/*Inserts objective into hashtable*/
void insert(pObjective o){
int i = hash(o->id, M);
heads[i] = insertBegin(heads[i], o);
}
/*Deletes objective using it's id*/
void delete(unsigned long id){
int i = hash(id, M);
heads[i] = removeList(heads[i], id);
}
/*Returns objective with said id*/
pObjective searchObj(unsigned long id){
int i = hash(id, M);
return searchObjAux(heads[i], id);
}
/*Inserts objective into list*/
link insertBegin(link h, pObjective obj){
link new = (link)malloc(sizeof(struct nodehash));
new->obj = obj;
new->next = h;
return new;
}
/*Searches objective by id in a list*/
int searchList(link h, unsigned long id){
link t;
int count = 0;
for(t = h; t != NULL; t = t->next){
if(t->obj->id == id)
count++;
}
return count++;
}
/*Removes objective from list*/
link removeList(link h, unsigned long id){
link t, x, z;
for(t = h; t != NULL; t = t->next){
if(t->next->obj->id == id)
x = t;
}
z = x->next;
x->next = z->next;
free(z);
return h;
}
/*Returns objetive from said id from list*/
pObjective searchObjAux(link h, unsigned long id){
link t, x;
for(t = h; t != NULL; t = t->next){
if(t->obj->id == id)
x = t;
}
return x->obj;
}
I'm quick testing the funcions addObj (adds an objective with dependencies) and addNoDeps (adds an objective with no dependencies) on my main:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "OBJECTIVES.h"
int main(){
unsigned long array [1] = {3};
Init(11);
addNoDeps(1, "tarefa1", 20);
addObj(2, "tarefa2", 20, array);
return 0;
}
But i keep getting segmentation fault(core dumped) and i can't figure out why. Is my implementation wrong? Are the functions wrong? I can't get to the problem, can someone help me?
I can't run your code right now so I can't analyze the core dump, but I believe what is happening is that you are trying to access memory that has already been freed. At the end of addNoDeps, you free the pObjective after putting it into the list. Then, when you addObj after, you search the list and check to make sure that the links object associated with it is not null. Specifically this code:
for(t = h; t != NULL; t = t->next){
if(t->obj->id == id)
count++;
You only check to see that the t (links pointer) is not null, but since you freed the previous object, the t->obj pointer is not pointing to initialized memroy. Therefore trying to access it via t->obj->id is accessing uninitialized memory. If you remove the free(obj) at the end of your addNoDeps and addObj functions you should be fine. You may also want to add checks to make sure that t->obj is not null as well. In general segmentation faults are caused by accessing uninitialized memory, so when debugging check for accessing pointers after a free, double frees, and other things. Also learning to use GDB can help a lot in these situations.
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.