Compare commits
10 commits
a8a8cddae6
...
afa6fbd96f
| Author | SHA1 | Date | |
|---|---|---|---|
| afa6fbd96f | |||
| 32a6e07e56 | |||
| 3a0b8a5c3f | |||
| 009258d3cd | |||
| d4913ac8df | |||
| 433a4f2c0d | |||
| a0392134e2 | |||
| eb87fd068d | |||
| 0122c877ac | |||
| 95cd73423a |
1
.gitignore
vendored
|
|
@ -56,3 +56,4 @@ dkms.conf
|
||||||
|
|
||||||
# Nix related things
|
# Nix related things
|
||||||
.direnv/
|
.direnv/
|
||||||
|
result*/
|
||||||
|
|
|
||||||
3
README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# CS 3502 Operating Systems Assignments
|
||||||
|
|
||||||
|
This repository contains my work for CS 3502: Operating Systems.
|
||||||
22
assignment1/default.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
let
|
||||||
|
basic-c = name: { stdenv }:
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
inherit name;
|
||||||
|
src = ./.;
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
gcc part2/${name}.c -o ${name}
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out/bin
|
||||||
|
install ${name} $out/bin/
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
a1-hello = basic-c "hello";
|
||||||
|
a1-employee = basic-c "employee";
|
||||||
|
a1-logwriter = basic-c "logwriter";
|
||||||
|
}
|
||||||
BIN
assignment1/part1/neofetch.png
Normal file
|
After Width: | Height: | Size: 562 KiB |
BIN
assignment1/part1/nix_gcc.png
Normal file
|
After Width: | Height: | Size: 264 KiB |
34
assignment1/part2/employee.c
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// Character array to store name
|
||||||
|
// In C, strings are arrays of characters ending with '\0'
|
||||||
|
char name[50];
|
||||||
|
int employee_id;
|
||||||
|
float hours_worked;
|
||||||
|
|
||||||
|
printf("OwlTech Employee Registration\n");
|
||||||
|
printf("=============================\n");
|
||||||
|
|
||||||
|
printf("Enter your name: ");
|
||||||
|
// fgets reads a line including spaces
|
||||||
|
// stdin means "standard input" (keyboard)
|
||||||
|
fgets(name, sizeof(name), stdin);
|
||||||
|
|
||||||
|
// Remove newline that fgets includes
|
||||||
|
name[strcspn(name, "\n")] = '\0';
|
||||||
|
|
||||||
|
printf("Enter your employee ID: ");
|
||||||
|
// & means "address of" - scanf needs to know where to store the value
|
||||||
|
scanf("%d", &employee_id);
|
||||||
|
printf("Hours worked this week: ");
|
||||||
|
scanf("%f", &hours_worked);
|
||||||
|
|
||||||
|
printf("\nEmployee Summary:\n");
|
||||||
|
printf("Name: %s\n", name); // %s for string
|
||||||
|
printf("ID: %d\n", employee_id); // %d for integer
|
||||||
|
printf("Hours: %.2f\n", hours_worked); // %.2f for float with 2 decimals
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
assignment1/part2/employee.png
Normal file
|
After Width: | Height: | Size: 968 KiB |
8
assignment1/part2/hello.c
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("Welcome to OwlTech Industries!\n");
|
||||||
|
printf("Systems Programming Division\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
assignment1/part2/hello.png
Normal file
|
After Width: | Height: | Size: 192 KiB |
BIN
assignment1/part2/log.png
Normal file
|
After Width: | Height: | Size: 250 KiB |
39
assignment1/part2/logwriter.c
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
FILE *logfile; // Pointer to file structure
|
||||||
|
char message[100];
|
||||||
|
time_t current_time;
|
||||||
|
|
||||||
|
// Open file for appending ("a" mode)
|
||||||
|
// "w" would overwrite, "r" would read
|
||||||
|
logfile = fopen("owltech.log", "a");
|
||||||
|
|
||||||
|
// Always check if file opened successfully
|
||||||
|
if (logfile == NULL) {
|
||||||
|
printf("Error: Could not open log file\n");
|
||||||
|
return 1; // Return non-zero to indicate error
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Enter log message: ");
|
||||||
|
fgets(message, sizeof(message), stdin);
|
||||||
|
|
||||||
|
// Get current time
|
||||||
|
time(¤t_time);
|
||||||
|
|
||||||
|
// Write to file with timestamp
|
||||||
|
// fprintf works like printf but writes to a file
|
||||||
|
fprintf(logfile, "[%s] %s", ctime(¤t_time), message);
|
||||||
|
|
||||||
|
// Always close files when done
|
||||||
|
fclose(logfile);
|
||||||
|
printf("Log entry saved successfully!\n");
|
||||||
|
|
||||||
|
// Display the log file contents
|
||||||
|
printf("\n--- Current Log Contents ---\n");
|
||||||
|
system("cat owltech.log");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
assignment1/part2/logwriter.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
assignment1/part3/gitconfig.png
Normal file
|
After Width: | Height: | Size: 1 MiB |
1
assignment1/test.nix
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
||||||
26
assignment2/default.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
let
|
||||||
|
basic-c = subdir: name: { stdenv }:
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
inherit name;
|
||||||
|
src = ./.;
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
gcc ${subdir}/${name}.c -o ${name}
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out/bin
|
||||||
|
install ${name} $out/bin/
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
a2-p1-producer = basic-c "part1" "producer";
|
||||||
|
a2-p1-consumer = basic-c "part1" "consumer";
|
||||||
|
|
||||||
|
a2-p2-bidirectional = basic-c "part2" "bidirectional";
|
||||||
|
|
||||||
|
a2-p3-producer = basic-c "part3" "producer";
|
||||||
|
a2-p3-consumer = basic-c "part3" "consumer";
|
||||||
|
}
|
||||||
47
assignment2/part1/consumer.c
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int max_lines = -1; // -1 means unlimited
|
||||||
|
int verbose = 0;
|
||||||
|
|
||||||
|
// Parse arguments (-n max_lines, -v verbose)
|
||||||
|
char opt;
|
||||||
|
while ((opt = getopt(argc, argv, "n:v")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'n':
|
||||||
|
max_lines = atoi(optarg); break;
|
||||||
|
case 'v':
|
||||||
|
verbose = 1; break;
|
||||||
|
default:
|
||||||
|
printf("Usage: %s [-n max_lines] [-v]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read from stdin line by line
|
||||||
|
// Count lines and characters
|
||||||
|
// If verbose, echo lines to stdout
|
||||||
|
char buffer[256];
|
||||||
|
int lines = 0;
|
||||||
|
int chars = 0;
|
||||||
|
while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
|
||||||
|
int size = strlen(buffer);
|
||||||
|
if (verbose)
|
||||||
|
fwrite(buffer, sizeof(char), size, stdout);
|
||||||
|
chars += size;
|
||||||
|
if (size > 0 && buffer[size - 1] == '\n')
|
||||||
|
lines++;
|
||||||
|
if (lines == max_lines)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print statistics to stderr
|
||||||
|
fprintf(stderr, "Lines: %d\n", lines);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
44
assignment2/part1/producer.c
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
FILE *input = stdin;
|
||||||
|
int buffer_size = 4096;
|
||||||
|
|
||||||
|
// Parse command line arguments
|
||||||
|
// -f filename (optional)
|
||||||
|
// b buffer_size (optional)
|
||||||
|
char opt;
|
||||||
|
while ((opt = getopt(argc, argv, "f:b:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'f':
|
||||||
|
input = fopen(optarg, "r");
|
||||||
|
if (input == NULL) {
|
||||||
|
fprintf(stderr, "Error: Could not open input file\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
buffer_size = atoi(optarg); break;
|
||||||
|
default:
|
||||||
|
printf("Usage: %s [-f filename] [-b buffer_size]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate buffer
|
||||||
|
char *buffer = malloc(buffer_size);
|
||||||
|
|
||||||
|
// Read from input and write to stdout
|
||||||
|
while (fgets(buffer, buffer_size, input) != NULL) {
|
||||||
|
fwrite(buffer, sizeof(char), strlen(buffer), stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
47
assignment2/part1/test
Executable file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
echo "Building executables..."
|
||||||
|
|
||||||
|
cd "${FLAKE:-$(dirname $0)}"
|
||||||
|
if command -v nix; then
|
||||||
|
producer="$(nix build --no-link --print-out-paths .#a2-p1-producer)/bin/producer"
|
||||||
|
consumer="$(nix build --no-link --print-out-paths .#a2-p1-consumer)/bin/consumer"
|
||||||
|
else
|
||||||
|
gcc producer.c -o producer
|
||||||
|
gcc consumer.c -o consumer
|
||||||
|
producer="./producer"
|
||||||
|
consumer="./consumer"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\nTEST - Sanity Check"
|
||||||
|
|
||||||
|
out="$(seq -s " " 1 10 | "$producer" | "$consumer" -v)"
|
||||||
|
if test "$out" = "$(seq -s " " 1 10)"; then
|
||||||
|
echo "SUCCESS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\nTEST - Smaller Buffer Size"
|
||||||
|
|
||||||
|
out="$(seq -s " " 1 10 | "$producer" -b 16 | "$consumer" -v)"
|
||||||
|
if test "$out" = "$(seq -s " " 1 10)"; then
|
||||||
|
echo "SUCCESS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\nTEST - Large External File"
|
||||||
|
|
||||||
|
head -c 10000 </dev/urandom | od -An -tx >random.txt
|
||||||
|
out="$("$producer" -f random.txt | "$consumer" -v)"
|
||||||
|
if test "$out" = "$(cat random.txt)"; then
|
||||||
|
echo "SUCCESS"
|
||||||
|
fi
|
||||||
|
rm random.txt
|
||||||
|
|
||||||
|
|
||||||
|
echo -e "\nTEST - Maximum Lines (5)"
|
||||||
|
|
||||||
|
head -c 1000 </dev/urandom | od -An -tx >random.txt
|
||||||
|
out="$("$producer" -f random.txt | "$consumer" -v -n 5)"
|
||||||
|
if test "$out" = "$(cat random.txt | head -n 5)"; then
|
||||||
|
echo "SUCCESS"
|
||||||
|
fi
|
||||||
|
rm random.txt
|
||||||
56
assignment2/part2/bidirectional.c
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
int pipe1[2]; // Parent to child
|
||||||
|
int pipe2[2]; // Child to parent
|
||||||
|
|
||||||
|
// Create both pipes
|
||||||
|
if (pipe(pipe1) == -1 || pipe(pipe2) == -1) {
|
||||||
|
fprintf(stderr, "Could not open pipes");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fork process
|
||||||
|
pid_t pid = fork();
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
// Child process
|
||||||
|
|
||||||
|
// Close unused pipe ends
|
||||||
|
close(pipe1[1]) ; // Close write end of pipe1
|
||||||
|
close(pipe2[0]) ; // Close read end of pipe2
|
||||||
|
|
||||||
|
// Read message, send response
|
||||||
|
char *message = malloc(100);
|
||||||
|
read(pipe1[0], message, 100);
|
||||||
|
printf("%s", message);
|
||||||
|
free(message);
|
||||||
|
|
||||||
|
char response[] = "Response from child to parent\n";
|
||||||
|
write(pipe2[1], response, sizeof(response));
|
||||||
|
} else {
|
||||||
|
// Parent process
|
||||||
|
|
||||||
|
// Close unused pipe ends
|
||||||
|
close(pipe1[0]) ; // Close read end of pipe1
|
||||||
|
close(pipe2[1]) ; // Close write end of pipe2
|
||||||
|
|
||||||
|
// Send message, read response
|
||||||
|
char message[] = "Sending message from parent to child\n";
|
||||||
|
write(pipe1[1], message, sizeof(message));
|
||||||
|
|
||||||
|
char *response = malloc(100);
|
||||||
|
read(pipe2[0], response, 100);
|
||||||
|
printf("%s", response);
|
||||||
|
free(response);
|
||||||
|
|
||||||
|
// Wait for child process to terminate
|
||||||
|
waitpid(pid, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
20
assignment2/part2/test
Executable file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
echo "Building executable..."
|
||||||
|
|
||||||
|
cd "${FLAKE:-$(dirname $0)}"
|
||||||
|
if command -v nix; then
|
||||||
|
bidirectional="$(nix build --no-link --print-out-paths .#a2-p2-bidirectional)/bin/bidirectional"
|
||||||
|
else
|
||||||
|
gcc bidirectional.c -o bidirectional
|
||||||
|
bidirectional="./bidirectional"
|
||||||
|
fi
|
||||||
|
|
||||||
|
out="$("$bidirectional")"
|
||||||
|
read -r -d '' expected <<EOF
|
||||||
|
Sending message from parent to child
|
||||||
|
Response from child to parent
|
||||||
|
EOF
|
||||||
|
if test "$out" = "$expected"; then
|
||||||
|
echo "SUCCESS"
|
||||||
|
fi
|
||||||
88
assignment2/part3/consumer.c
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
volatile sig_atomic_t shutdown_flag = 0;
|
||||||
|
volatile sig_atomic_t stats_flag = 0;
|
||||||
|
|
||||||
|
void handle_sigint(int sig) {
|
||||||
|
shutdown_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_sigusr1(int sig) {
|
||||||
|
stats_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
struct sigaction sa_sigint;
|
||||||
|
sa_sigint.sa_handler = handle_sigint;
|
||||||
|
sigemptyset(&sa_sigint.sa_mask);
|
||||||
|
sa_sigint.sa_flags = 0;
|
||||||
|
sigaction(SIGINT, &sa_sigint, NULL);
|
||||||
|
|
||||||
|
struct sigaction sa_sigusr1;
|
||||||
|
sa_sigusr1.sa_handler = handle_sigusr1;
|
||||||
|
sigemptyset(&sa_sigusr1.sa_mask);
|
||||||
|
sa_sigusr1.sa_flags = 0;
|
||||||
|
sigaction(SIGUSR1, &sa_sigusr1, NULL);
|
||||||
|
|
||||||
|
int max_lines = -1; // -1 means unlimited
|
||||||
|
int verbose = 0;
|
||||||
|
|
||||||
|
// Parse arguments (-n max_lines, -v verbose)
|
||||||
|
char opt;
|
||||||
|
while ((opt = getopt(argc, argv, "n:v")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'n':
|
||||||
|
max_lines = atoi(optarg); break;
|
||||||
|
case 'v':
|
||||||
|
verbose = 1; break;
|
||||||
|
default:
|
||||||
|
printf("Usage: %s [-n max_lines] [-v]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_t start = clock();
|
||||||
|
|
||||||
|
// Read from stdin line by line
|
||||||
|
// Count lines and characters
|
||||||
|
// If verbose, echo lines to stdout
|
||||||
|
char buffer[256];
|
||||||
|
int lines = 0;
|
||||||
|
int chars = 0;
|
||||||
|
while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
|
||||||
|
int size = strlen(buffer);
|
||||||
|
if (verbose)
|
||||||
|
fwrite(buffer, sizeof(char), size, stdout);
|
||||||
|
chars += size;
|
||||||
|
if (size > 0 && buffer[size - 1] == '\n')
|
||||||
|
lines++;
|
||||||
|
if (lines == max_lines)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Handle shutdown
|
||||||
|
if (shutdown_flag) {
|
||||||
|
fprintf(stderr, "Cancelled\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print statistics to stderr (handle SIGUSR1)
|
||||||
|
if (stats_flag) {
|
||||||
|
clock_t end = clock();
|
||||||
|
double time = ((double)(end - start)) / CLOCKS_PER_SEC;
|
||||||
|
double throughput = (double)chars / 1024.0 / 1024.0 / time;
|
||||||
|
printf("Stats:\n");
|
||||||
|
printf("File Size: %d bytes\n", chars);
|
||||||
|
printf("Total Time: %.3f secs\n", time);
|
||||||
|
printf("Throughput: %.3f MB/s\n", throughput);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Lines: %d\n", lines);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
63
assignment2/part3/producer.c
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
volatile sig_atomic_t shutdown_flag = 0;
|
||||||
|
|
||||||
|
void handle_sigint(int sig) {
|
||||||
|
shutdown_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
struct sigaction sa;
|
||||||
|
sa.sa_handler = handle_sigint;
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
sigaction(SIGINT, &sa, NULL);
|
||||||
|
|
||||||
|
FILE *input = stdin;
|
||||||
|
int buffer_size = 4096;
|
||||||
|
|
||||||
|
// Parse command line arguments
|
||||||
|
// -f filename (optional)
|
||||||
|
// b buffer_size (optional)
|
||||||
|
char opt;
|
||||||
|
while ((opt = getopt(argc, argv, "f:b:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'f':
|
||||||
|
input = fopen(optarg, "r");
|
||||||
|
if (input == NULL) {
|
||||||
|
fprintf(stderr, "Error: Could not open input file\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
buffer_size = atoi(optarg); break;
|
||||||
|
default:
|
||||||
|
printf("Usage: %s [-f filename] [-b buffer_size]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate buffer
|
||||||
|
char *buffer = malloc(buffer_size);
|
||||||
|
|
||||||
|
// Read from input and write to stdout
|
||||||
|
while (fgets(buffer, buffer_size, input) != NULL) {
|
||||||
|
fwrite(buffer, sizeof(char), strlen(buffer), stdout);
|
||||||
|
|
||||||
|
// Handle shutdown
|
||||||
|
if (shutdown_flag) {
|
||||||
|
fprintf(stderr, "Cancelled\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
33
assignment2/part3/test
Executable file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
echo "Building executables..."
|
||||||
|
|
||||||
|
cd "${FLAKE:-$(dirname $0)}"
|
||||||
|
if command -v nix; then
|
||||||
|
producer="$(nix build --no-link --print-out-paths .#a2-p3-producer)/bin/producer"
|
||||||
|
consumer="$(nix build --no-link --print-out-paths .#a2-p3-consumer)/bin/consumer"
|
||||||
|
else
|
||||||
|
gcc producer.c -o producer
|
||||||
|
gcc consumer.c -o consumer
|
||||||
|
producer="./producer"
|
||||||
|
consumer="./consumer"
|
||||||
|
fi
|
||||||
|
|
||||||
|
seq 1 10000000 >large.txt
|
||||||
|
|
||||||
|
echo -e "\nTEST - Buffer size 1024"
|
||||||
|
"$producer" -b 1024 -f large.txt | "$consumer" &
|
||||||
|
kill -USR1 "$(pidof consumer)"
|
||||||
|
wait "$(jobs -rp)"
|
||||||
|
|
||||||
|
echo -e "\nTEST - Buffer size 4096"
|
||||||
|
"$producer" -b 4096 -f large.txt | "$consumer" &
|
||||||
|
kill -USR1 "$(pidof consumer)"
|
||||||
|
wait "$(jobs -rp)"
|
||||||
|
|
||||||
|
echo -e "\nTEST - Buffer size 16384"
|
||||||
|
"$producer" -b 16384 -f large.txt | "$consumer" &
|
||||||
|
kill -USR1 "$(pidof consumer)"
|
||||||
|
wait "$(jobs -rp)"
|
||||||
|
|
||||||
|
rm large.txt
|
||||||
12
assignment2/test.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
let
|
||||||
|
bash-test = subdir: { runCommandLocal }:
|
||||||
|
runCommandLocal "${subdir}-test" { FLAKE = ../.; }
|
||||||
|
''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
install ${subdir}/test $out/bin/
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
a2-p1 = bash-test "part1";
|
||||||
|
a2-p2 = bash-test "part2";
|
||||||
|
a2-p3 = bash-test "part3";
|
||||||
|
}
|
||||||
22
flake.nix
|
|
@ -7,11 +7,25 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, systems, ... }:
|
outputs = { self, nixpkgs, systems, ... }:
|
||||||
let eachSystem = nixpkgs.lib.genAttrs (import systems);
|
let
|
||||||
in {
|
subdirs = [
|
||||||
packages = eachSystem (system:
|
"assignment1"
|
||||||
|
"assignment2"
|
||||||
|
];
|
||||||
|
|
||||||
|
eachSystem = nixpkgs.lib.genAttrs (import systems);
|
||||||
|
|
||||||
|
importFromSubdirs = file: eachSystem (system:
|
||||||
let pkgs = nixpkgs.legacyPackages.${system};
|
let pkgs = nixpkgs.legacyPackages.${system};
|
||||||
in {});
|
in pkgs.lib.mergeAttrsList
|
||||||
|
(builtins.map (d:
|
||||||
|
builtins.mapAttrs
|
||||||
|
(_: v: pkgs.callPackage v {})
|
||||||
|
(import ./${d}/${file}))
|
||||||
|
subdirs));
|
||||||
|
in {
|
||||||
|
packages = importFromSubdirs "default.nix";
|
||||||
|
checks = importFromSubdirs "test.nix";
|
||||||
|
|
||||||
devShells = eachSystem (system:
|
devShells = eachSystem (system:
|
||||||
let pkgs = nixpkgs.legacyPackages.${system};
|
let pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,4 @@
|
||||||
{ pkgs }:
|
{ mkShell }:
|
||||||
pkgs.mkShell {}
|
|
||||||
|
# GCC is provided by default
|
||||||
|
mkShell {}
|
||||||
|
|
|
||||||