initially when I have only one sem_t *queue inside the struct, when I initialize it, the programs run without any errors and problems.
#include <semaphore.h>
typedef struct barrier {
int count;
sem_t *queue;
} barrier_t;
void barrier_init ( barrier_t *barrier, int count );
#include "barrier.h"
#include <stdlib.h>
// Initialise barrier here
void barrier_init ( barrier_t *barrier, int count )
{
barrier->count = count;
barrier->queue = malloc(sizeof(sem_t));
sem_init(barrier->queue, 0, 0);
}
however, when I have two sem_t in struct barrier when I initialize and run with Valgrind, it signals to me that there is an invalid write of size 8, even though the program runs and outputs normally.
#include "barrier.h"
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
typedef struct barrier {
int count;
sem_t *queue, *mutex;
} barrier_t;
void barrier_init ( barrier_t *barrier, int count )
{
barrier->count = count;
barrier->queue = malloc(sizeof(sem_t));
barrier->mutex = malloc(sizeof(sem_t));
sem_init(barrier->mutex, 0, 1);
sem_init(barrier->queue, 0, 0);
}
void barrier_wait ( barrier_t *barrier )
{
sem_wait(barrier->mutex);
barrier->count--;
sem_post(barrier->mutex);
if (barrier->count == 0) {
sem_post(barrier->queue);
}
sem_wait(barrier->queue);
sem_post(barrier->queue);
}
// Perform cleanup here if you need to
void barrier_destroy ( barrier_t *barrier )
{
sem_destroy(barrier->queue);
sem_destroy(barrier->mutex);
free(barrier->queue);
free(barrier->mutex);
}
The main function was a template given which should not have any issues. Valgrind has no issue with memory leaks as well only errors indicating invalid write and read of size 8. so here's the main function:
#include <pthread.h>
#include <semaphore.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "barrier.h"
sem_t *common_sem;
int waiting_at_barrier = 0;
typedef struct thread_task {
int thread_id;
barrier_t *barrier;
int thread_return;
int sleep_time;
} thread_task_t;
void* run_thread( void* task )
{
thread_task_t* thread_task = (thread_task_t*) task;
const int thread_id = thread_task->thread_id;
barrier_t *barrier = thread_task->barrier;
usleep( thread_task->sleep_time );
sem_wait( common_sem );
waiting_at_barrier++;
sem_post( common_sem );
printf ( "[Thread %2d] waiting on barrier\n", thread_id );
barrier_wait( barrier );
printf ( "[Thread %2d] exiting barrier\n", thread_id );
thread_task->thread_return = waiting_at_barrier;
pthread_exit(0);
}
int main ( int argc, char *argv[] )
{
if (argc < 2) {
printf("usage: %s threads [seed]\n", argv[0]);
exit(1);
}
if (argc > 2) {
srand(atoi(argv[2])); // [atoi] defaults to 0 if cannot be parsed.
}
const int total_threads = argc > 1 ? atoi(argv[1]) : 50;
// initialise common semaphore
common_sem = malloc(sizeof(sem_t));
sem_init( common_sem, 0, 1 );
barrier_t *barrier = malloc( sizeof(barrier_t) );
barrier_init( barrier, total_threads );
pthread_t threads[total_threads];
thread_task_t *thread_tasks = malloc(sizeof(thread_task_t) *
total_threads);
int i;
for (i = 0; i < total_threads; i++) {
thread_tasks[i].thread_id = i;
thread_tasks[i].barrier = barrier;
thread_tasks[i].sleep_time = (rand() % 500) * 1000;
pthread_create( &threads[i], NULL, run_thread, (void*)
&thread_tasks[i] );
}
// wait and collect the tasks
bool error_found = false;
for (i = 0; i < total_threads; i++) {
pthread_join( threads[i], NULL );
if (thread_tasks[i].thread_return < total_threads) {
error_found = true;
printf ( "[Thread %2d] exited with %d other tasks (expected:
%d)\n",i,thread_tasks[i].thread_return,
total_threads );
}
}
free(thread_tasks);
barrier_destroy(barrier);
free(barrier);
sem_destroy( common_sem );
free( common_sem );
if (error_found) {
printf ( "Incorrect executions found\n" );
exit(1);
}
return 0;
}
THis is part of the Valgrind errors:
Invalid write of size 8 at 0x1098BB: barrier_init (in /home/hzxin/work/2106/lab3/L3/ex1/ex1) by 0x10948F: main (in /home/hzxin/work/2106/lab3/L3/ex1/ex1) Address 0x4a730b0 is 0 bytes after a block of size 16 alloc'dat 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
main
. Please add relevant#include
s. Please create a full minimal reproducible example. The problem might be thatbarrier
is invalid pointer. – KamilCukCC=gcc CFLAGS=-Wall LDLIBS=-lpthread .PHONY: clean ex1: barrier.o ex1.o barrier.o: barrier.c barrier.h clean: rm barrier.o ex1.o ex1 .PHONY: all all: ex1
– Hzxin