lab: added solutions
This commit is contained in:
parent
8b3abe2dde
commit
a5c25c64f9
|
|
@ -3,32 +3,39 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define DEBUG 1
|
||||||
|
|
||||||
#define ITERATIONS 100000
|
#define ITERATIONS 100000
|
||||||
|
|
||||||
// Shared variables
|
// Shared variables
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
int signal_flag = 0; // 0 = LOW, 1 = HIGH
|
int state_flag = 0; // 0 = LOW, 1 = HIGH
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
|
||||||
void* high_thread(void* arg) {
|
|
||||||
|
void* high_thread() {
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
pthread_mutex_lock(&lock);
|
pthread_mutex_lock(&lock);
|
||||||
|
|
||||||
|
if (counter >= ITERATIONS) {
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
pthread_cond_signal(&cond);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for turn
|
// Wait for turn
|
||||||
while (signal_flag != 1) {
|
while (state_flag != 1) {
|
||||||
pthread_cond_wait(&cond, &lock);
|
pthread_cond_wait(&cond, &lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Critical section
|
// Critical section
|
||||||
if (counter >= ITERATIONS) {
|
#if DEBUG
|
||||||
pthread_mutex_unlock(&lock);
|
|
||||||
pthread_cond_signal(&cond);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
printf("%d: HIGH\n", counter);
|
printf("%d: HIGH\n", counter);
|
||||||
|
#endif
|
||||||
counter++;
|
counter++;
|
||||||
signal_flag = 0;
|
state_flag = 0; // Switch to LOW
|
||||||
|
|
||||||
// Signal the other thread
|
// Signal the other thread
|
||||||
pthread_mutex_unlock(&lock);
|
pthread_mutex_unlock(&lock);
|
||||||
|
|
@ -37,24 +44,27 @@ void* high_thread(void* arg) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* low_thread(void* arg) {
|
void* low_thread() {
|
||||||
while (1) {
|
while (1) {
|
||||||
pthread_mutex_lock(&lock);
|
pthread_mutex_lock(&lock);
|
||||||
|
|
||||||
|
if (counter >= ITERATIONS) {
|
||||||
|
pthread_mutex_unlock(&lock);
|
||||||
|
pthread_cond_signal(&cond);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for turn
|
// Wait for turn
|
||||||
while (signal_flag != 0) {
|
while (state_flag != 0) {
|
||||||
pthread_cond_wait(&cond, &lock);
|
pthread_cond_wait(&cond, &lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Critical section
|
// Critical section
|
||||||
if (counter >= ITERATIONS) {
|
#if DEBUG
|
||||||
pthread_mutex_unlock(&lock);
|
|
||||||
pthread_cond_signal(&cond);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
printf("%d: LOW\n", counter);
|
printf("%d: LOW\n", counter);
|
||||||
|
#endif
|
||||||
counter++;
|
counter++;
|
||||||
signal_flag = 1;
|
state_flag = 1; // Switch to HIGH
|
||||||
|
|
||||||
// Signal the other thread
|
// Signal the other thread
|
||||||
pthread_mutex_unlock(&lock);
|
pthread_mutex_unlock(&lock);
|
||||||
|
|
@ -74,6 +84,11 @@ int main() {
|
||||||
pthread_create(&high_tid, NULL, high_thread, NULL);
|
pthread_create(&high_tid, NULL, high_thread, NULL);
|
||||||
pthread_create(&low_tid, NULL, low_thread, NULL);
|
pthread_create(&low_tid, NULL, low_thread, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
printf("Start threads:\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Wait for threads to finish
|
// Wait for threads to finish
|
||||||
pthread_join(high_tid, NULL);
|
pthread_join(high_tid, NULL);
|
||||||
pthread_join(low_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