I am implementing a stack pool to do some basic arithmetic in a specific number of threads.
here is the code:
int add(int a, int b) {return a b;}
int sub(int a, int b) {return a-b;}
int mul(int a, int b) {return a*b;}
sem_t sem_ops;
void* compute(void* arg){
Args *args = arg;
Operation* op = args->operation;
printOP(*op);
int * value = malloc ( sizeof ( int ) ) ;
* value = op->op(op->a, op->b);
args->is_complete = true;
sem_post(&sem_ops);
return value;
}
void push(Operation op , Queue* q){
q->operations[ (q->last)] = op;
}
Operation *pop(Queue *q){
q->first ;
return &q->operations[q->first];
}
int size(Queue *q){
return q->last - q->first;
}
bool read_operations(char* filename, Queue* ops){
printf("reading from file %s\n",filename);
FILE *fp = fopen(filename, "r");
if(fp == NULL )
{
printf("couldnt open");
return false;
}
int id,a,b;
while(!feof(fp)){
fscanf(fp,"%d %d %d\n",&id,&a,&b);
Operation op;
op.a = a;
op.b = b;
switch (id){
case 0:
op.op = add;
break;
case 1:
op.op = sub;
break;
case 2:
default:
op.op =mul;
break;
}
push(op,ops);
}
return true;
}
ArrayList* execute_thread_pool(char* filename, int poolSize){
sem_init(&sem_ops,0,poolSize);
//init return value
ArrayList* retval =malloc(sizeof(ArrayList));
int res [ TOTAL_OP_COUNT];
retval->results = res;
retval->count = 0;
// populate Q
Queue q;
Operation ops[TOTAL_OP_COUNT];
q.first = 0;
q.last = 0;
q.max = TOTAL_OP_COUNT;
q.operations = ops;
read_operations(filename,&q);
// thread tids
pthread_t threads[TOTAL_OP_COUNT];
//args for each thread
Args args[TOTAL_OP_COUNT];
int* result= NULL;
for(int i =0; i<poolSize; i){
sem_wait(&sem_ops);
args[i].operation = pop(&q);
args[i].is_complete=false;
pthread_create(&threads[i],NULL, compute,&args[i]);
}
for(int i =0; i<poolSize; i){
if(args[i].is_complete){
pthread_join(threads[i],(void**) result);
res[i] = *result; // line 88
}else --i;
}
return retval;
}
and the structs typedefs:
typedef struct _Operation{
int(*op) (int, int);
int a;
int b;
} Operation;
typedef struct _Args{
Operation* operation;
bool is_complete;
}Args;
typedef struct _Queue{
Operation* operations;
int last;
int first;
int max;
}Queue;
I tried using malloc at a few different places, but can't run away from segfault. this is the content of the main function:
ArrayList *al =malloc(sizeof(ArrayList)) ;
al = execute_thread_pool("bob.txt", 4);
in gdb the bt is as follow:
#0 0x0000555555555762 in execute_thread_pool (filename=0x555555556004 "bob.txt", poolSize=4) at pool.c:88
#1 0x00005555555552db in main (argc=1, argv=0x7fffffffda68) at main.c:5
I've been on this for a few hours, tried multiple ways, tried without semaphores and using not so fun loops and yet the same result. can anyone help me spot the issue?
CodePudding user response:
You misunderstand the pthread_join
call and how emulating pass-by-reference work in works.
You are supposed to pass a pointer to an int *
variable, using the pointer-to operator &
:
pthread_join(threads[i], &result);
You should also remember to free
the pointer result
, or you will have a memory leak.