From 2ca61c07de772d95a8d89c9b3ba0bb62742830f7 Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 19 Mar 2025 07:03:08 +0000 Subject: [PATCH] [CT420]: Merge bm1.c & bm2.c --- .../assignments/assignment2/code/merged.c | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 year4/semester2/CT420/assignments/assignment2/code/merged.c diff --git a/year4/semester2/CT420/assignments/assignment2/code/merged.c b/year4/semester2/CT420/assignments/assignment2/code/merged.c new file mode 100644 index 00000000..6b0686e4 --- /dev/null +++ b/year4/semester2/CT420/assignments/assignment2/code/merged.c @@ -0,0 +1,168 @@ +// Compile code with gcc -o bm1 bm1.c -lrt -Wall -O2 +// Execute code with sudo ./bm1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ITERATIONS 1000 +#define NS_PER_SEC 1000000000L + +timer_t timer_id; +volatile sig_atomic_t timer_expired = 0; +volatile sig_atomic_t signal_received = 0; +struct timespec start, end, sleep_time; + +void signal_handler(int signum) { + signal_received = 1; + clock_gettime(CLOCK_MONOTONIC, &end); +} + +void timer_handler(int signum) { + timer_expired = 1; + clock_gettime(CLOCK_MONOTONIC, &end); +} + +void configure_realtime_scheduling() { + struct sched_param param; + param.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (sched_setscheduler(0, SCHED_FIFO, ¶m) == -1) { + perror("sched_setscheduler"); + exit(EXIT_FAILURE); + } +} + +void lock_memory() { + if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { + perror("mlockall"); + exit(EXIT_FAILURE); + } +} + +void benchmark_nanosleep() { + // struct timespec start, end, sleep_time; + long long total_jitter = 0; + long long max_jitter = 0; + long long min_jitter = LLONG_MAX; + + sleep_time.tv_sec = 0; + sleep_time.tv_nsec = 1000000; // 1 ms + + for (int i = 0; i < ITERATIONS; i++) { + clock_gettime(CLOCK_MONOTONIC, &start); + nanosleep(&sleep_time, NULL); + clock_gettime(CLOCK_MONOTONIC, &end); + + long long elapsed = (end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec); + long long jitter = elapsed - sleep_time.tv_nsec; + + total_jitter += llabs(jitter); + if (jitter > max_jitter) max_jitter = jitter; + if (jitter < min_jitter) min_jitter = jitter; + } + + printf("Nanosleep Benchmark:\n"); + printf("Average jitter: %lld ns\n", total_jitter / ITERATIONS); + printf("Max jitter: %lld ns\n", max_jitter); + printf("Min jitter: %lld ns\n", min_jitter); +} + +void benchmark_signal_latency() { + long long total_latency = 0; + long long max_latency = 0; + long long min_latency = LLONG_MAX; + + signal(SIGUSR1, signal_handler); + + for (int i = 0; i < ITERATIONS; i++) { + clock_gettime(CLOCK_MONOTONIC, &start); + kill(getpid(), SIGUSR1); + while (!signal_received); + + long long latency = (end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec); + total_latency += latency; + if (latency > max_latency) max_latency = latency; + if (latency < min_latency) min_latency = latency; + + signal_received = 0; + } + + printf("\nSignal Latency Benchmark:\n"); + printf("Average latency: %lld ns\n", total_latency / ITERATIONS); + printf("Max latency: %lld ns\n", max_latency); + printf("Min latency: %lld ns\n", min_latency); +} + +void benchmark_timer() { + long long total_jitter = 0; + long long max_jitter = 0; + long long min_jitter = LLONG_MAX; + + struct sigevent sev; + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGRTMIN; + sev.sigev_value.sival_ptr = &timer_id; + + if (timer_create(CLOCK_MONOTONIC, &sev, &timer_id) == -1) { + perror("timer_create"); + exit(EXIT_FAILURE); + } + + struct itimerspec its; + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 1000000; // 1 ms + its.it_interval = its.it_value; + + signal(SIGRTMIN, timer_handler); + + if (timer_settime(timer_id, 0, &its, NULL) == -1) { + perror("timer_settime"); + exit(EXIT_FAILURE); + } + clock_gettime(CLOCK_MONOTONIC, &start); + for (int i = 0; i < ITERATIONS; i++) { + // while (!timer_expired); + + while (!timer_expired) { + struct timespec ts = {0, 100}; + nanosleep(&ts, NULL); + } + + clock_gettime(CLOCK_MONOTONIC, &end); + + long long elapsed = (end.tv_sec - start.tv_sec) * NS_PER_SEC + (end.tv_nsec - start.tv_nsec); + long long jitter = elapsed - its.it_interval.tv_nsec; + + total_jitter += llabs(jitter); + if (jitter > max_jitter) max_jitter = jitter; + if (jitter < min_jitter) min_jitter = jitter; + + timer_expired = 0; + start = end; + } + + printf("\nTimer Benchmark:\n"); + printf("Average jitter: %lld ns\n", total_jitter / ITERATIONS); + printf("Max jitter: %lld ns\n", max_jitter); + printf("Min jitter: %lld ns\n", min_jitter); + + timer_delete(timer_id); +} + +int main() { + configure_realtime_scheduling(); + lock_memory(); + + benchmark_nanosleep(); + benchmark_signal_latency(); + benchmark_timer(); + + return 0; +}