Given these methods:
void* thread1Func(void* p) {
while(1) {
printf("A ");
}
}
void* thread2Func(void* p) {
while(1) {
printf("B ");
}
}
void* thread3Func(void* p) {
while(1) {
printf("C ");
}
}
Assuming thread1 runs thread1Func, same for thread2 and 3,
We're required to only add semaphores/semaphore methods/thread methods(creation, execution) such that the printed pattern will be A A B C A A B C A A B C A A B C ...
I've got code printing out the correct pattern, with no errors:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
sem_t semaphoreA, semaphoreB, semaphoreC;
void* thread1Func(void* p) {
while (1) {
sem_wait(&semaphoreA); // Wait for semaphoreA
printf("A ");
sem_post(&semaphoreA); // Signal semaphoreA for the second 'A'
sem_wait(&semaphoreA); // Wait for semaphoreA again
printf("A ");
sem_post(&semaphoreB); // Signal semaphoreB for 'B'
}
}
void* thread2Func(void* p) {
while (1) {
sem_wait(&semaphoreB); // Wait for semaphoreB
printf("B ");
sem_post(&semaphoreC); // Signal semaphoreC for 'C'
}
}
void* thread3Func(void* p) {
while (1) {
sem_wait(&semaphoreC); // Wait for semaphoreC
printf("C ");
sem_post(&semaphoreA); // Signal semaphoreA for the next 'A'
}
}
int main() {
pthread_t thread1, thread2, thread3;
// Initialize semaphores
sem_init(&semaphoreA, 0, 1); // semaphoreA starts unlocked
sem_init(&semaphoreB, 0, 0); // semaphoreB starts locked
sem_init(&semaphoreC, 0, 0); // semaphoreC starts locked
// Create threads
pthread_create(&thread1, NULL, thread1Func, NULL);
pthread_create(&thread2, NULL, thread2Func, NULL);
pthread_create(&thread3, NULL, thread3Func, NULL);
// Wait for threads to finish (which they won't in this case due to while(1))
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_join(thread3, NULL);
// Destroy semaphores
sem_destroy(&semaphoreA);
sem_destroy(&semaphoreB);
sem_destroy(&semaphoreC);
return 0;
}
However this solution involves adding another print statement, which is not allowed.
I've tried different approachs to incrementing/decrementing the semaphores yet all either fail/ print the pattern
A B C A B C A B C A B C ...
I've played around with the wait/post methods, and also with the semaphore initial value, I've got this code that got me the correct pattern, however I am unsure on why this is working:
(added just the parts where I've changed values)
sem_t semaphoreA, semaphoreB, semaphoreC;
void* thread1Func(void* p) {
while (1) {
sem_wait(&semaphoreA); // Wait for semaphoreA
printf("A "); // Print 'A'
sem_post(&semaphoreB); // Signal semaphoreB for 'B'
sem_post(&semaphoreC); // Signal semaphoreC for 'C'
}
}
void* thread2Func(void* p) {
while (1) {
sem_wait(&semaphoreB); // Wait for semaphoreB
sem_wait(&semaphoreB);
printf("B "); // Signal semaphoreA for the next 'A'
}
}
void* thread3Func(void* p) {
while (1) {
sem_wait(&semaphoreC); // Wait for semaphoreC
sem_wait(&semaphoreC);
printf("C "); // Print 'C' and newline
sem_post(&semaphoreA); // Signal semaphoreA for the next 'A'
sem_post(&semaphoreA);
}
}
int main() {
// Initialize semaphores
sem_init(&semaphoreA, 0, 2); // semaphoreA starts unlocked
sem_init(&semaphoreB, 0, -1); // semaphoreB starts locked
sem_init(&semaphoreC, 0, -1); // semaphoreC starts locked
// ...
}
You're overthinking the problem. First, think about what has to happen at each logical step.
Your A thread only cares about its turn and unblocking B, so start there.
void* thread1Func(void* p) {
while (1) {
sem_wait(&semaphoreA); // Wait for semaphoreA
printf("A ");
sem_post(&semaphoreB); // Signal semaphoreB for 'B'
}
}
Now to make B work, it needs to wait twice, since we always need two As.
void* thread2Func(void* p) {
while (1) {
sem_wait(&semaphoreB); // Wait for semaphoreB
sem_wait(&semaphoreB); // Wait for semaphoreB
printf("B ");
sem_post(&semaphoreC); // Signal semaphoreC for 'C'
}
}
Lastly, C needs to signal A twice since we want two prints.
void* thread3Func(void* p) {
while (1) {
sem_wait(&semaphoreC); // Wait for semaphoreC
printf("C ");
sem_post(&semaphoreA); // Signal semaphoreA for the next 'A'
sem_post(&semaphoreA); // Signal semaphoreA for the next 'A'
}
}
The only other thing you need to change is the initial value of semaphoreA
to 2 (sem_init(&semaphoreA, 0, 2)
) so that its loop will execute twice.