realtime/lab/square_wave_timed.c

115 lines
2.5 KiB
C

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define ITERATIONS 100000
// Shared variables
pthread_mutex_t lock;
pthread_cond_t cond;
int signal_flag = 0; // 0 = LOW, 1 = HIGH
int counter = 0;
// set up an array of timespec structs to store timestamps
struct timespec timestamps[ITERATIONS];
void* high_thread(void* arg) {
while (1) {
if (counter >= ITERATIONS) {
pthread_cond_signal(&cond);
return NULL;
}
pthread_mutex_lock(&lock);
// Wait for turn
while (signal_flag != 1) {
pthread_cond_wait(&cond, &lock);
}
#ifdef DEBUG
printf("%d: HIGH\n", counter);
#endif
counter++;
signal_flag = 0;
if (clock_gettime(CLOCK_MONOTONIC, &timestamps[counter]) != 0) {
perror("clock_gettime failed");
exit(1);
}
// Signal the other thread
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
}
return NULL;
}
void* low_thread(void* arg) {
while (1) {
if (counter >= ITERATIONS) {
pthread_cond_signal(&cond);
return NULL;
}
pthread_mutex_lock(&lock);
// Wait for turn
while (signal_flag != 0) {
pthread_cond_wait(&cond, &lock);
}
#ifdef DEBUG
printf("%d: LOW\n", counter);
#endif
counter++;
signal_flag = 1;
if (clock_gettime(CLOCK_MONOTONIC, &timestamps[counter]) != 0) {
perror("clock_gettime failed");
exit(1);
}
// Signal the other thread
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
}
return NULL;
}
int main() {
pthread_t high_tid, low_tid;
// Initialize synchronization primitives
pthread_mutex_init(&lock, NULL);
pthread_cond_init(&cond, NULL);
// Create threads
pthread_create(&high_tid, NULL, high_thread, NULL);
pthread_create(&low_tid, NULL, low_thread, NULL);
printf("Start threads:\n");
// Wait for threads to finish
pthread_join(high_tid, NULL);
pthread_join(low_tid, NULL);
// Cleanup
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
for (int i = 1; i < ITERATIONS; i++) {
printf("Period %zu: %ld.%09ld seconds\n",
i,
timestamps[i].tv_sec - timestamps[i-1].tv_sec,
timestamps[i].tv_nsec) - timestamps[i-1].tv_nsec;
}
return 0;
}