Sorry to put this as an answer. (I can't comment.) your programs with a little bit of changes works fine for me.
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
// Semaphore initialization for writer and reader
sem_t wrt;
sem_t rd;
// Mutex 1 blocks other readers, mutex 2 blocks other writers
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;
// Value the writer is changing, we are simply multiplying this value by 2
int cnt = 2;
int numreader = 0;
int numwriter = 0;
void *writer(void *wno)
{
pthread_mutex_lock(&mutex2);
numwriter++;
if (numwriter == 1) {
sem_wait(&rd);
}
pthread_mutex_unlock(&mutex2);
sem_wait(&wrt);
// Writing Section
cnt = cnt * 2;
printf("Writer %d modified cnt to %d\n", *((int *)wno), cnt);
sem_post(&wrt);
pthread_mutex_lock(&mutex2);
numwriter--;
if (numwriter == 0) {
sem_post(&rd);
}
pthread_mutex_unlock(&mutex2);
return NULL; // Correctly return a void pointer
}
void *reader(void *rno)
{
sem_wait(&rd);
pthread_mutex_lock(&mutex1);
numreader++;
if (numreader == 1) {
sem_wait(&wrt);
}
pthread_mutex_unlock(&mutex1);
sem_post(&rd);
// Reading Section
printf("Reader %d: read cnt as %d\n", *((int *)rno), cnt);
pthread_mutex_lock(&mutex1);
numreader--;
if (numreader == 0) {
sem_post(&wrt);
}
pthread_mutex_unlock(&mutex1);
return NULL; // Correctly return a void pointer
}
int main()
{
pthread_t read[10], write[5];
pthread_mutex_init(&mutex1, NULL);
pthread_mutex_init(&mutex2, NULL);
sem_init(&wrt, 0, 1);
sem_init(&rd, 0, 1);
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // Just used for numbering the writer and reader
for (int i = 0; i < 5; i++) {
pthread_create(&write[i], NULL, writer, &a[i]); // No explicit casting
}
for (int i = 0; i < 10; i++) {
pthread_create(&read[i], NULL, reader, &a[i]); // No explicit casting
}
for (int i = 0; i < 5; i++) {
pthread_join(write[i], NULL);
}
for (int i = 0; i < 10; i++) {
pthread_join(read[i], NULL);
}
pthread_mutex_destroy(&mutex1);
pthread_mutex_destroy(&mutex2);
sem_destroy(&wrt);
sem_destroy(&rd);
return 0;
}
here is the proof: