lab: added solutions
This commit is contained in:
parent
8b3abe2dde
commit
a5c25c64f9
|
|
@ -3,32 +3,39 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
#define ITERATIONS 100000
|
||||
|
||||
// Shared variables
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
int signal_flag = 0; // 0 = LOW, 1 = HIGH
|
||||
int state_flag = 0; // 0 = LOW, 1 = HIGH
|
||||
int counter = 0;
|
||||
|
||||
void* high_thread(void* arg) {
|
||||
|
||||
void* high_thread() {
|
||||
while (1) {
|
||||
|
||||
pthread_mutex_lock(&lock);
|
||||
|
||||
if (counter >= ITERATIONS) {
|
||||
pthread_mutex_unlock(&lock);
|
||||
pthread_cond_signal(&cond);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Wait for turn
|
||||
while (signal_flag != 1) {
|
||||
while (state_flag != 1) {
|
||||
pthread_cond_wait(&cond, &lock);
|
||||
}
|
||||
|
||||
// Critical section
|
||||
if (counter >= ITERATIONS) {
|
||||
pthread_mutex_unlock(&lock);
|
||||
pthread_cond_signal(&cond);
|
||||
exit(0);
|
||||
}
|
||||
#if DEBUG
|
||||
printf("%d: HIGH\n", counter);
|
||||
#endif
|
||||
counter++;
|
||||
signal_flag = 0;
|
||||
state_flag = 0; // Switch to LOW
|
||||
|
||||
// Signal the other thread
|
||||
pthread_mutex_unlock(&lock);
|
||||
|
|
@ -37,24 +44,27 @@ void* high_thread(void* arg) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void* low_thread(void* arg) {
|
||||
void* low_thread() {
|
||||
while (1) {
|
||||
pthread_mutex_lock(&lock);
|
||||
|
||||
if (counter >= ITERATIONS) {
|
||||
pthread_mutex_unlock(&lock);
|
||||
pthread_cond_signal(&cond);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Wait for turn
|
||||
while (signal_flag != 0) {
|
||||
while (state_flag != 0) {
|
||||
pthread_cond_wait(&cond, &lock);
|
||||
}
|
||||
|
||||
// Critical section
|
||||
if (counter >= ITERATIONS) {
|
||||
pthread_mutex_unlock(&lock);
|
||||
pthread_cond_signal(&cond);
|
||||
exit(0);
|
||||
}
|
||||
#if DEBUG
|
||||
printf("%d: LOW\n", counter);
|
||||
#endif
|
||||
counter++;
|
||||
signal_flag = 1;
|
||||
state_flag = 1; // Switch to HIGH
|
||||
|
||||
// Signal the other thread
|
||||
pthread_mutex_unlock(&lock);
|
||||
|
|
@ -74,6 +84,11 @@ int main() {
|
|||
pthread_create(&high_tid, NULL, high_thread, NULL);
|
||||
pthread_create(&low_tid, NULL, low_thread, NULL);
|
||||
|
||||
|
||||
#if DEBUG
|
||||
printf("Start threads:\n");
|
||||
#endif
|
||||
|
||||
// Wait for threads to finish
|
||||
pthread_join(high_tid, NULL);
|
||||
pthread_join(low_tid, NULL);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#define DEBUG 1
|
||||
#define ITERATIONS 100000
|
||||
|
||||
sem_t high_sem, low_sem;
|
||||
int counter = 0;
|
||||
|
||||
void* high() {
|
||||
while (counter < ITERATIONS) {
|
||||
sem_wait(&high_sem);
|
||||
#if DEBUG
|
||||
printf("%d: HIGH\n", counter);
|
||||
#endif
|
||||
sem_post(&low_sem);
|
||||
counter++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* low() {
|
||||
while (counter < ITERATIONS) {
|
||||
sem_wait(&low_sem);
|
||||
#if DEBUG
|
||||
printf("%d: LOW\n", counter);
|
||||
#endif
|
||||
sem_post(&high_sem);
|
||||
counter++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main() {
|
||||
pthread_t high_thread, low_thread;
|
||||
|
||||
sem_init(&high_sem, 0, 1); // high_sem starts
|
||||
sem_init(&low_sem, 0, 0);
|
||||
|
||||
pthread_create(&high_thread, NULL, high, NULL);
|
||||
pthread_create(&low_thread, NULL, low, NULL);
|
||||
|
||||
pthread_join(high_thread, NULL);
|
||||
pthread_join(low_thread, NULL);
|
||||
|
||||
sem_destroy(&high_sem);
|
||||
sem_destroy(&low_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
// Description: This program uses semaphores to create a square wave between two threads.
|
||||
// The period of the square wave is timed and displayed after the threads have finished.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#define DEBUG 0
|
||||
#define NUM_PERIODS 100e3
|
||||
|
||||
sem_t high_sem, low_sem;
|
||||
|
||||
struct timespec start_time, end_time;
|
||||
|
||||
// Array to store timestamps of each period
|
||||
struct timespec timestamps[NUM_PERIODS];
|
||||
|
||||
void* high() {
|
||||
for (int i = 0; i < NUM_PERIODS; i++) {
|
||||
sem_wait(&high_sem);
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, ×tamps[i]) != 0) {
|
||||
perror("clock_gettime failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
printf("%d: HIGH\n", i);
|
||||
#endif
|
||||
sem_post(&low_sem);
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* low() {
|
||||
for (int i = 0; i < NUM_PERIODS; i++) {
|
||||
sem_wait(&low_sem);
|
||||
#if DEBUG
|
||||
printf("%d: LOW\n", i);
|
||||
#endif
|
||||
sem_post(&high_sem);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main() {
|
||||
pthread_t high_thread, low_thread;
|
||||
|
||||
sem_init(&high_sem, 0, 1); // high_sem starts
|
||||
sem_init(&low_sem, 0, 0);
|
||||
|
||||
pthread_create(&high_thread, NULL, high, NULL);
|
||||
pthread_create(&low_thread, NULL, low, NULL);
|
||||
|
||||
pthread_join(high_thread, NULL);
|
||||
pthread_join(low_thread, NULL);
|
||||
|
||||
sem_destroy(&high_sem);
|
||||
sem_destroy(&low_sem);
|
||||
|
||||
int period;
|
||||
int min_period;
|
||||
int max_period;
|
||||
int sum_of_periods = 0;
|
||||
|
||||
// Print periods for each iteration
|
||||
for (int i = 1; i < NUM_PERIODS; i++) {
|
||||
sum_of_periods += period;
|
||||
period = (timestamps[i].tv_sec - timestamps[i - 1].tv_sec) * 1e9 + (timestamps[i].tv_nsec - timestamps[i - 1].tv_nsec);
|
||||
if (i == 1) {
|
||||
min_period = period;
|
||||
max_period = period;
|
||||
} else {
|
||||
if (period < min_period) {
|
||||
min_period = period;
|
||||
}
|
||||
if (period > max_period) {
|
||||
max_period = period;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("Period %d: %lld nanoseconds\n", i, periods[i]);
|
||||
//printf("%lld\n", periods[i]);
|
||||
}
|
||||
printf("Minimum period: %d nanoseconds\n", min_period);
|
||||
printf("Maximum period: %d nanoseconds\n", max_period);
|
||||
printf("Average period: %f nanoseconds\n", (float)sum_of_periods / (NUM_PERIODS - 1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
// Description: This program uses semaphores to create a square wave between two threads.
|
||||
// The period of the square wave is timed and displayed after the threads have finished.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
|
||||
#define DEBUG 0
|
||||
#define NUM_PERIODS 100000
|
||||
|
||||
sem_t high_sem, low_sem;
|
||||
|
||||
struct timespec start_time, end_time;
|
||||
|
||||
// Array to store periods
|
||||
int periods[NUM_PERIODS];
|
||||
|
||||
void* high() {
|
||||
for (int i = 0; i < NUM_PERIODS; i++) {
|
||||
sem_wait(&high_sem);
|
||||
|
||||
if (i != 0) {
|
||||
// Calculate period
|
||||
clock_gettime(CLOCK_MONOTONIC, &end_time);
|
||||
periods[i] = (end_time.tv_sec - start_time.tv_sec) * 1e9 + (end_time.tv_nsec - start_time.tv_nsec);
|
||||
}
|
||||
clock_gettime(CLOCK_MONOTONIC, &start_time);
|
||||
|
||||
#if DEBUG
|
||||
printf("%d: HIGH\n", i);
|
||||
#endif
|
||||
sem_post(&low_sem);
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* low() {
|
||||
for (int i = 0; i < NUM_PERIODS; i++) {
|
||||
sem_wait(&low_sem);
|
||||
#if DEBUG
|
||||
printf("%d: LOW\n", i);
|
||||
#endif
|
||||
sem_post(&high_sem);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main() {
|
||||
pthread_t high_thread, low_thread;
|
||||
|
||||
sem_init(&high_sem, 0, 1); // high_sem starts
|
||||
sem_init(&low_sem, 0, 0);
|
||||
|
||||
pthread_create(&high_thread, NULL, high, NULL);
|
||||
pthread_create(&low_thread, NULL, low, NULL);
|
||||
|
||||
pthread_join(high_thread, NULL);
|
||||
pthread_join(low_thread, NULL);
|
||||
|
||||
sem_destroy(&high_sem);
|
||||
sem_destroy(&low_sem);
|
||||
|
||||
int min_period = periods[1];
|
||||
int max_period = periods[1];
|
||||
int sum_of_periods = 0;
|
||||
|
||||
// Print periods for each iteration
|
||||
for (int i = 1; i < NUM_PERIODS; i++) {
|
||||
if (periods[i] < min_period) {
|
||||
min_period = periods[i];
|
||||
}
|
||||
if (periods[i] > max_period) {
|
||||
max_period = periods[i];
|
||||
}
|
||||
sum_of_periods += periods[i];
|
||||
//printf("Period %d: %lld nanoseconds\n", i, periods[i]);
|
||||
//printf("%lld\n", periods[i]);
|
||||
}
|
||||
printf("Minimum period: %d nanoseconds\n", min_period);
|
||||
printf("Maximum period: %d nanoseconds\n", max_period);
|
||||
printf("Average period: %f nanoseconds\n", (float)sum_of_periods / (NUM_PERIODS - 1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
#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, ×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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue