#include #include #include #include #include #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, ×tamps[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, ×tamps[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; }