From 8b3abe2dde39b6e03ba0dfaba4905e2a592577a6 Mon Sep 17 00:00:00 2001 From: Daniel Meiburg Date: Mon, 9 Dec 2024 09:43:14 +0100 Subject: [PATCH] initial commit --- .gitignore | 6 + ex01/aufgabe2.c | 36 ++++++ ex01/hello_world.c | 6 + ex01/manual_termination.c | 24 ++++ ex01/signal_termination.c | 39 +++++++ ex01/t03_schedule_counting.c | 40 +++++++ ex01/t04_external_program.c | 39 +++++++ ex01/t05_external_program.c | 44 ++++++++ ex01/zusatz1.c | 20 ++++ ex01/zusatz2.c | 28 +++++ ex02/aufgabe1_sohn.c | 19 ++++ ex02/aufgabe1_vater.c | 30 +++++ ex02/aufgabe2.c | 30 +++++ ex02/ex03_multiple_sons.c | 44 ++++++++ ex03/t01.c | 75 +++++++++++++ ex03/t03_sig_child.c | 48 ++++++++ ex03/t04_multiple_children_pipes.c | 94 ++++++++++++++++ ex03/testfile.zip | Bin 0 -> 184 bytes ex06/aufgabe1.c | 117 ++++++++++++++++++++ ex06/aufgabe2.c | 103 +++++++++++++++++ ex06/aufgabe3.c | 84 ++++++++++++++ ex06/aufgabe4.c | 103 +++++++++++++++++ ex07/aufgabe1.c | 63 +++++++++++ ex07/aufgabe1_improved.c | 63 +++++++++++ ex07/aufgabe2.c | 168 ++++++++++++++++++++++++++++ ex07/aufgabe2_gpt.c | 132 ++++++++++++++++++++++ ex07/aufgabe2_improved.c | 170 +++++++++++++++++++++++++++++ ex07/aufgabe5.c | 72 ++++++++++++ howto_shell_cheatsheet.txt | 80 ++++++++++++++ lab/square_wave.c | 87 +++++++++++++++ 30 files changed, 1864 insertions(+) create mode 100644 .gitignore create mode 100644 ex01/aufgabe2.c create mode 100644 ex01/hello_world.c create mode 100644 ex01/manual_termination.c create mode 100644 ex01/signal_termination.c create mode 100644 ex01/t03_schedule_counting.c create mode 100644 ex01/t04_external_program.c create mode 100644 ex01/t05_external_program.c create mode 100644 ex01/zusatz1.c create mode 100644 ex01/zusatz2.c create mode 100644 ex02/aufgabe1_sohn.c create mode 100644 ex02/aufgabe1_vater.c create mode 100644 ex02/aufgabe2.c create mode 100644 ex02/ex03_multiple_sons.c create mode 100644 ex03/t01.c create mode 100644 ex03/t03_sig_child.c create mode 100644 ex03/t04_multiple_children_pipes.c create mode 100644 ex03/testfile.zip create mode 100644 ex06/aufgabe1.c create mode 100644 ex06/aufgabe2.c create mode 100644 ex06/aufgabe3.c create mode 100644 ex06/aufgabe4.c create mode 100644 ex07/aufgabe1.c create mode 100644 ex07/aufgabe1_improved.c create mode 100644 ex07/aufgabe2.c create mode 100644 ex07/aufgabe2_gpt.c create mode 100644 ex07/aufgabe2_improved.c create mode 100644 ex07/aufgabe5.c create mode 100644 howto_shell_cheatsheet.txt create mode 100644 lab/square_wave.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8ca4edb --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +* +!*.* +!*/ +*.ova +*.iso +*.pdf diff --git a/ex01/aufgabe2.c b/ex01/aufgabe2.c new file mode 100644 index 0000000..287172c --- /dev/null +++ b/ex01/aufgabe2.c @@ -0,0 +1,36 @@ +////////////////////////////////////////////////////////////////////////////// +// Course: Real Time Systems +// Lecturer: Dr.-Ing. Frank Golatowski +// Exercise instructor: M.Sc. Michael Rethfeldt +// Exercise: 1 +// Task: 2 +// Name: aufgabe2.c +// Description: ? +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +int main(void) +{ + int status; + pid_t fork_pid; + + if ( (fork_pid=fork() ) == 0 ) + { + printf("* I am the son. *\n"); + exit(3); + } + else if (fork_pid == -1) + { + printf("fork() failed!\n"); + exit(2); + } + wait(&status); // wait for termination of son process + // status: hexa decimal output from son process + // (status>>8) & 0xff: second (higher byte) of the status + // status & 0xff: first (lower byte) of the status + printf("wait status: 0x%x | 0x%x | 0x%x |\n", status, (status>>8) & 0xff, status & 0xff); + return 0; +} diff --git a/ex01/hello_world.c b/ex01/hello_world.c new file mode 100644 index 0000000..f26b97c --- /dev/null +++ b/ex01/hello_world.c @@ -0,0 +1,6 @@ +#include + +int main() { + printf("Hello, World!\n"); + return 0; +} diff --git a/ex01/manual_termination.c b/ex01/manual_termination.c new file mode 100644 index 0000000..e871eba --- /dev/null +++ b/ex01/manual_termination.c @@ -0,0 +1,24 @@ +#include +#include // fork, sleep +#include // exit +#include // wait + +int main(){ + int status; + int pid; + + if ((pid = fork()) == 0) { + printf("I'm the son and going to sleep for 30s.\n"); + sleep(30); + exit(3); + } + else if (pid == -1) { + printf("fork() failed"); + exit(2); + } + + wait(&status); + + printf("wait status 0x%x | 0x%x | 0x%x\n", status, (status>>8) & 0xff, status & 0xff); + return 0; +} diff --git a/ex01/signal_termination.c b/ex01/signal_termination.c new file mode 100644 index 0000000..e734713 --- /dev/null +++ b/ex01/signal_termination.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +int main(void) +{ + int status; + pid_t fork_pid; + + if ( (fork_pid = fork()) == 0 ) + { + printf("* I am the son. About to terminate by signal... *\n"); + // Send SIGKILL to this process (self-termination with a signal) + raise(SIGKILL); // Alternatively, try SIGTERM, SIGSEGV, etc. + } + else if (fork_pid == -1) + { + printf("fork() failed!\n"); + exit(2); + } + + wait(&status); // wait for termination of child process + + // status: full status returned by wait() + // (status >> 8) & 0xff: higher byte (exit code in normal exit) + // status & 0xff: lower byte (termination signal or additional info) + printf("wait status: 0x%x | Exit code: 0x%x | Signal: 0x%x |\n", + status, (status >> 8) & 0xff, status & 0x7f); + + // Check if child terminated by signal + if (WIFSIGNALED(status)) + { + printf("Child was terminated by signal %d\n", WTERMSIG(status)); + } + + return 0; +} diff --git a/ex01/t03_schedule_counting.c b/ex01/t03_schedule_counting.c new file mode 100644 index 0000000..27d6c51 --- /dev/null +++ b/ex01/t03_schedule_counting.c @@ -0,0 +1,40 @@ +// Create a program that creates a child process using fork. +// The parent and child processes should count from 0 to N, printing every STEP. +// N and step are supplied via command line arguments. +#include +#include // exit +#include // fork, sleep +#include // wait + +int count(char *who, int n, int step){ + // count from 0 to print every step + for (int i = 0; i <= n; i++){ + if (i % step == 0) + printf("%s:\t%d\n", who, i); + } + return 0; +} + +int main(int argc, char *argv[]){ + if (argc != 3){ + printf("Usage: %s N STEP\n", argv[0]); + exit(1); + } + + int N = atoi(argv[1]); + int STEP = atoi(argv[2]); + int status; + int pid; + + if ((pid = fork()) == 0){ + count("child", N, STEP); + exit(0); + } + else if (pid == -1){ + printf("fork failed.\n"); + exit(2); + } + + count("parent", N, STEP); + return 0; +} diff --git a/ex01/t04_external_program.c b/ex01/t04_external_program.c new file mode 100644 index 0000000..f921329 --- /dev/null +++ b/ex01/t04_external_program.c @@ -0,0 +1,39 @@ +// This program creates a fork and uses execl to run the ls command +// in the child process. The parent process waits for the child to +// finish and then prints a message containing the child's exit status. + +#include +#include +#include +#include + +#define LS "/run/current-system/sw/bin/ls" +#define PATH "/home/dm" + +int main() { + pid_t pid; + int status; + + pid = fork(); + if (pid < 0) { + perror("fork"); + exit(1); + } + + if (pid == 0) { + // Child process + execl(LS, "ls", "-lasi", PATH, NULL); + // this line will only be reached if execl fails, meaning that it + // will not influence the status + perror("execl"); + exit(3); + } + + // Parent process + wait(&status); + printf("exit status: 0x%04x\n", status); + printf("Child exited with status %d\n", WEXITSTATUS(status)); + + return 0; +} + diff --git a/ex01/t05_external_program.c b/ex01/t05_external_program.c new file mode 100644 index 0000000..9a55d33 --- /dev/null +++ b/ex01/t05_external_program.c @@ -0,0 +1,44 @@ +// This program creates a fork and uses execl to run the ls command +// in the child process. The parent process waits for the child to +// finish and then prints a message containing the child's exit status. + +#include +#include +#include +#include + +#define LS "/run/current-system/sw/bin/ls" +#define PATH "/home/dm" + +int main() { + pid_t pid; + int status; + + pid = fork(); + if (pid < 0) { + perror("fork"); + exit(1); + } + + if (pid == 0) { + // Child process + printf("child: PID = %d, PPID = %d, GID = %d, PGID = %d\n", + getpid(), getppid(), getgid(), getpgid(getpid())); + execl(LS, "ls", "-lasi", PATH, NULL); + // this line will only be reached if execl fails, meaning that it + // will not influence the status + perror("execl"); + exit(3); + } + + printf("parent: PID = %d, PPID = %d, GID = %d, PGID = %d\n", + getpid(), getppid(), getgid(), getpgid(getpid())); + + // Parent process + wait(&status); + printf("exit status: 0x%04x\n", status); + printf("Child exited with status %d\n", WEXITSTATUS(status)); + + return 0; +} + diff --git a/ex01/zusatz1.c b/ex01/zusatz1.c new file mode 100644 index 0000000..c934659 --- /dev/null +++ b/ex01/zusatz1.c @@ -0,0 +1,20 @@ +////////////////////////////////////////////////////////////////////////////// +// Course: Real Time Systems +// Lecturer: Dr.-Ing. Frank Golatowski +// Exercise instructor: M.Sc. Michael Rethfeldt +// Exercise: 1 +// Task: zusatz1 +// Name: zusatz1.c +// Description: ? +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include + +int main(int argc, char *argv[]) +{ + fork(); + fork(); + printf("test\n"); +} + diff --git a/ex01/zusatz2.c b/ex01/zusatz2.c new file mode 100644 index 0000000..0bce69e --- /dev/null +++ b/ex01/zusatz2.c @@ -0,0 +1,28 @@ +////////////////////////////////////////////////////////////////////////////// +// Course: Real Time Systems +// Lecturer: Dr.-Ing. Frank Golatowski +// Exercise instructor: M.Sc. Michael Rethfeldt +// Exercise: 1 +// Task: zusatz2 +// Name: zusatz2.c +// Description: ? +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include + +int main(int argc, char *argv[]) +{ + switch ( fork() ) { + case 0: printf("Son created\n"); + break; + default: switch ( fork() ) { + case 0: printf("Son created\n"); + break; + default: printf("Father\n"); + break; + } + break; + } +} + diff --git a/ex02/aufgabe1_sohn.c b/ex02/aufgabe1_sohn.c new file mode 100644 index 0000000..b689834 --- /dev/null +++ b/ex02/aufgabe1_sohn.c @@ -0,0 +1,19 @@ +////////////////////////////////////////////////////////////////////////////// +// Course: Real Time Systems +// Lecturer: Dr.-Ing. Frank Golatowski +// Exercise instructor: M.Sc. Michael Rethfeldt +// Exercise: 2 +// Task: 1 +// Name: aufgabe1_sohn.c +// Description: Son process +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +int main(void) +{ + printf("I am the son.\n"); + return 0; +} diff --git a/ex02/aufgabe1_vater.c b/ex02/aufgabe1_vater.c new file mode 100644 index 0000000..ed135a3 --- /dev/null +++ b/ex02/aufgabe1_vater.c @@ -0,0 +1,30 @@ +////////////////////////////////////////////////////////////////////////////// +// Course: Real Time Systems +// Lecturer: Dr.-Ing. Frank Golatowski +// Exercise instructor: M.Sc. Michael Rethfeldt +// Exercise: 2 +// Task: 1 +// Name: aufgabe1_vater.c +// Description: Father process executes an external son process +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +int main(void) +{ int status; + pid_t fork_pid; + if ( (fork_pid=fork() ) == 0 ) + { execl("./son", "son", NULL); + printf("execl() failed!\n"); + exit(3); + } + else if (fork_pid == -1) + { printf("fork() failed!\n"); + exit(2); + } + wait(&status); // wait for termination of son + printf("wait status: 0x%x | 0x%x | 0x%x |\n", status, (status>>8) & 0xff, status & 0xff); + return 0; +} diff --git a/ex02/aufgabe2.c b/ex02/aufgabe2.c new file mode 100644 index 0000000..1cec39e --- /dev/null +++ b/ex02/aufgabe2.c @@ -0,0 +1,30 @@ +#include +#include +#include + +int main(void) +{ + int var = 0; + + printf("PID(Father)=%d, PPID=%d, var=%d\n", getpid(), getppid(), var); + + if ( fork() == -1 ) + { + fprintf( stderr, "fork() failed!\n" ); + } + else + { + var++; + printf("PID=%d, PPID=%d, var=%d\n", getpid(), getppid(), var); + if ( fork() == -1 ) + { + fprintf( stderr, "Error at 2nd fork()!\n"); + } + else + { + var++; + printf("PID=%d, PPID=%d, var=%d\n", getpid(), getppid(), var); + } + } + return 0; +} diff --git a/ex02/ex03_multiple_sons.c b/ex02/ex03_multiple_sons.c new file mode 100644 index 0000000..6337f72 --- /dev/null +++ b/ex02/ex03_multiple_sons.c @@ -0,0 +1,44 @@ +// create a number N of child processes specified via commandline argument +// each child sleeps for a random time between 1 and 5 seconds +// each child prints its PID and the time it slept +// the parent waits for all children to finish and then exits + +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + int n = atoi(argv[1]); + + for (int i = 0; i < n; i++) { + pid_t pid = fork(); + if (pid < 0) { + perror("fork"); + return 1; + } + + if (pid == 0) { + // child + srand(getpid()); + int sleep_time = 1 + rand() % 5; + printf("Child %d with PID %d will sleep for %d seconds\n", i, getpid(), sleep_time); + sleep(sleep_time); + printf("Child %d with PID %d slept for %d seconds\n", i, getpid(), sleep_time); + return 0; + } + } + + // parent + for (int i = 0; i < n; i++) { + int status; + wait(&status); + } + + return 0; +} diff --git a/ex03/t01.c b/ex03/t01.c new file mode 100644 index 0000000..2cf473d --- /dev/null +++ b/ex03/t01.c @@ -0,0 +1,75 @@ +////////////////////////////////////////////////////////////////////////////// +// Course: Real Time Systems +// Lecturer: Dr.-Ing. Frank Golatowski +// Exercise instructor: M.Sc. Michael Rethfeldt +// Exercise: 3 +// Task: 1 +// Name: aufgabe1.c +// Description: ? +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + +void hex_print(FILE *dz, char *s) +{ + int fd[2]; + + if (pipe(fd) != 0) { + fprintf(stderr, "Error while creating pipe!\n"); + exit(1); + } else { + printf("Hex print of %s\n\n",s); + switch(fork()) { + case -1:{ fprintf(stderr, "fork() failed\n"); + exit(1); + } + case 0:{ int i=1; + unsigned char read_char; + + close(fd[1]); + while (read(fd[0], &read_char, 1) > 0) { + printf(" %02x", read_char); + if (++i > 16) { + printf("\n"); + i=1; + } + } + printf("\n"); + close(fd[0]); + exit(0); + } + default:{ unsigned char c; + int status; + + close(fd[0]); + while (fread(&c,1,1,dz) > 0) + write(fd[1], &c, 1); + close(fd[1]); + wait(&status); + } + } + } +} + +int main(int argc, char *argv[]) +{ + FILE *dz; + int i; + + if (argc < 2) { + fprintf(stderr, "Call: aufgabe1 \n"); + exit(1); + } + for (i=1; i +#include +#include +#include +#include + +void handle_sigint(int sig) { + // Father ignores SIGINT + printf("Father process received SIGINT, but ignoring it.\n"); +} + +void handle_son_termination(int status) { + if (WIFEXITED(status)) { + printf("Son terminated with exit status %d.\n", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + printf("Son terminated by signal %d.\n", WTERMSIG(status)); + } else { + printf("Son terminated with unknown status.\n"); + } +} + +int main() { + pid_t pid = fork(); + + if (pid == -1) { + perror("fork failed"); + exit(EXIT_FAILURE); + } else if (pid == 0) { + // Son process + signal(SIGINT, SIG_DFL); // Allow son process to be terminated by SIGINT + + for (int i = 0; i < 10; ++i) { + printf("Son PID: %d\n", getpid()); + sleep(1); + } + printf("Son terminating after 10 seconds.\n"); + exit(0); + } else { + // Father process + signal(SIGINT, handle_sigint); // Ignore SIGINT in father + + int status; + waitpid(pid, &status, 0); // Wait for son's termination + handle_son_termination(status); + } + + return 0; +} diff --git a/ex03/t04_multiple_children_pipes.c b/ex03/t04_multiple_children_pipes.c new file mode 100644 index 0000000..ae982e4 --- /dev/null +++ b/ex03/t04_multiple_children_pipes.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include + +void writer_process(int fd_write, FILE *file) { + unsigned char c; + // Close the unused read end of the pipe + close(fd_write - 1); // fd[0] is read end, fd[1] is write end, so fd_write - 1 points to read end + + // Write the file data byte by byte to the pipe + while (fread(&c, 1, 1, file) > 0) { + write(fd_write, &c, 1); + } + + // Close the write end of the pipe after finishing + close(fd_write); + exit(0); // Exit after writing +} + +void reader_process(int fd_read) { + unsigned char read_char; + int i = 1; + + // Close the unused write end of the pipe + close(fd_read + 1); // fd[1] is write end, so fd_read + 1 points to write end + + // Read from the pipe and print in hexadecimal format + while (read(fd_read, &read_char, 1) > 0) { + printf(" %02x", read_char); + if (++i > 16) { // Print 16 bytes per line + printf("\n"); + i = 1; + } + } + printf("\n"); + + // Close the read end of the pipe after finishing + close(fd_read); + exit(0); // Exit after reading and printing +} + +int main(int argc, char *argv[]) { + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + + // Open the file in binary mode + FILE *file = fopen(argv[1], "rb"); + if (file == NULL) { + fprintf(stderr, "Can't open file %s\n", argv[1]); + exit(1); + } + + int fd[2]; + if (pipe(fd) != 0) { + fprintf(stderr, "Error while creating pipe!\n"); + exit(1); + } + + // Fork writer process + pid_t writer_pid = fork(); + if (writer_pid < 0) { + fprintf(stderr, "Failed to create writer process.\n"); + exit(1); + } else if (writer_pid == 0) { + // Writer process logic + writer_process(fd[1], file); + } + + // Close file in the parent after creating the writer + fclose(file); + + // Fork reader process + pid_t reader_pid = fork(); + if (reader_pid < 0) { + fprintf(stderr, "Failed to create reader process.\n"); + exit(1); + } else if (reader_pid == 0) { + // Reader process logic + reader_process(fd[0]); + } + + // In the father process: close both ends of the pipe + close(fd[0]); + close(fd[1]); + + // Wait for both children to finish + waitpid(writer_pid, NULL, 0); + waitpid(reader_pid, NULL, 0); + + return 0; +} diff --git a/ex03/testfile.zip b/ex03/testfile.zip new file mode 100644 index 0000000000000000000000000000000000000000..a6b4b33a4b24b8a01d69bc92740c29654cf6e113 GIT binary patch literal 184 zcmWIWW@Zs#U|`^2*cGI!*Hx!BQ3=RX0E;j%l%y7yq-Ex$CMTpMr6r~&KY#G#(X)q7 zABzi!2#E=b3QwOfWzw{XQzx@C1b8zt$ur|H1_ldm)2F)* dF{=H$kRR~*Je&^jW@Q6uV+6t|AngG*0|4#!EJ6SP literal 0 HcmV?d00001 diff --git a/ex06/aufgabe1.c b/ex06/aufgabe1.c new file mode 100644 index 0000000..38b22c7 --- /dev/null +++ b/ex06/aufgabe1.c @@ -0,0 +1,117 @@ +// Compiler call: cc -o aufgabe1 aufgabe1.c -lpthread +#include +#include +//#include +#include + +int make_new_item(void); +void consume_item(char a, int count); +void* reader_function(void*); +void writer_function(void); + +char buffer; +int buffer_has_item = 0; +pthread_mutex_t mutex; + +void cleanup_resources() { + pthread_mutex_destroy(&mutex); +} + +int main(int argc, char *argv[]){ + pthread_mutexattr_t mutex_attr; + pthread_attr_t attr; + pthread_t reader; + int ret; + + // Initialize mutex attributes + if ((ret = pthread_mutexattr_init(&mutex_attr)) != 0) { + fprintf(stderr, "Error initializing mutex attributes: %d\n", ret); + return 1; + } + + // Initialize mutex + if ((ret = pthread_mutex_init(&mutex, &mutex_attr)) != 0) { + fprintf(stderr, "Error initializing mutex: %d\n", ret); + return 1; + } + + // Initialize thread attributes + if ((ret = pthread_attr_init(&attr)) != 0) { + fprintf(stderr, "Error initializing thread attributes: %d\n", ret); + cleanup_resources(); + return 1; + } + + // Create reader thread + if ((ret = pthread_create(&reader, &attr, reader_function, 0)) != 0) { + fprintf(stderr, "Error creating thread: %d\n", ret); + cleanup_resources(); + return 1; + } + + writer_function(); + + // Wait for reader thread to finish + if ((ret = pthread_join(reader, 0)) != 0) { + fprintf(stderr, "Error joining thread: %d\n", ret); + cleanup_resources(); + return 1; + } + + cleanup_resources(); + printf("Main thread finished!\n"); + return 0; +} + +void writer_function(void){ + char a=0; + int count=0; + + while( a != 'q' ){ + pthread_mutex_lock( &mutex ); + + if ( !buffer_has_item ){ + a = make_new_item(); + buffer=a; + buffer_has_item = 1; + printf("Thread 1: buffer: '%c', loop count=%d\n", a, count); + count=0; + } + else + count++; + + pthread_mutex_unlock( &mutex ); + } +} + +void* reader_function(void *ptr){ + char a=0; + int count=0; + + while(a != 'q'){ + pthread_mutex_lock( &mutex ); + + if ( buffer_has_item ){ + a=buffer; + if ( a != 'q' ) + consume_item(a,count); + buffer_has_item = 0; + count=0; + } + else + count++; + + pthread_mutex_unlock(&mutex); + } + printf("Reader thread finished\n"); + return 0; +} + +int make_new_item(){ + static int buffer='a'; + return buffer++; +} + +void consume_item(char a, int count){ + printf("Thread 2: buffer read with '%c', loop count=%d\n", a, count); +} diff --git a/ex06/aufgabe2.c b/ex06/aufgabe2.c new file mode 100644 index 0000000..4113616 --- /dev/null +++ b/ex06/aufgabe2.c @@ -0,0 +1,103 @@ +#include +#include +#include + +// Function prototypes +int make_new_item(void); +void *reader_function(void *); +void writer_function(void); + +// Shared resources +char buffer; +int buffer_has_item = 0; +pthread_mutex_t mutex; +pthread_cond_t cond_buffer_empty; +pthread_cond_t cond_buffer_full; + +void cleanup_resources() { + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond_buffer_empty); + pthread_cond_destroy(&cond_buffer_full); +} + +int main(int argc, char *argv[]) { + pthread_mutexattr_t mutex_attr; + pthread_attr_t attr; + pthread_t reader; + int ret; + + // Initialize mutex and condition variables + pthread_mutexattr_init(&mutex_attr); + pthread_mutex_init(&mutex, &mutex_attr); + pthread_cond_init(&cond_buffer_empty, NULL); + pthread_cond_init(&cond_buffer_full, NULL); + pthread_attr_init(&attr); + + // Create reader thread + pthread_create(&reader, &attr, reader_function, 0); + + // Run writer function in the main thread + writer_function(); + + // Wait for reader thread to finish + pthread_join(reader, 0); + + // Clean up + cleanup_resources(); + printf("Main thread finished!\n"); + return 0; +} + +void writer_function(void) { + char a = 0; + + while (a != 'q') { + pthread_mutex_lock(&mutex); + + // Wait until the buffer is empty + while (buffer_has_item) { + pthread_cond_wait(&cond_buffer_empty, &mutex); + } + + a = make_new_item(); + buffer = a; + buffer_has_item = 1; + printf("Thread 1: buffer: '%c'\n", a); + + // Signal the reader that the buffer is full + pthread_cond_signal(&cond_buffer_full); + pthread_mutex_unlock(&mutex); + } +} + +void *reader_function(void *ptr) { + char a = 0; + + while (a != 'q') { + pthread_mutex_lock(&mutex); + + // Wait until the buffer is full + while (!buffer_has_item) { + pthread_cond_wait(&cond_buffer_full, &mutex); + } + + // Read the item from the buffer + a = buffer; + if (a != 'q') { + printf("Thread 2: buffer read with '%c'\n", a); + } + buffer_has_item = 0; + + // Signal the producer that the buffer is empty + pthread_cond_signal(&cond_buffer_empty); + pthread_mutex_unlock(&mutex); + } + + printf("Reader thread finished\n"); + return 0; +} + +int make_new_item() { + static int buffer = 'a'; + return buffer++; +} diff --git a/ex06/aufgabe3.c b/ex06/aufgabe3.c new file mode 100644 index 0000000..e0b6757 --- /dev/null +++ b/ex06/aufgabe3.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include + +// Function prototypes +int make_new_item(void); +void consume_item(char a, int count); +void *reader_function(void *); +void writer_function(void); + +// Shared resources +char buffer; +sem_t empty; // Tracks empty slots +sem_t full; // Tracks filled slots + +void cleanup_resources() { + sem_destroy(&empty); + sem_destroy(&full); +} + +int main(int argc, char *argv[]) { + pthread_attr_t attr; + pthread_t reader; + + // Initialize semaphores + // first 0 is for shared between threads, second 0 is for the initial value + // first 1 would mean that the semaphore is shared between processes + sem_init(&empty, 0, 1); // Initially, buffer is empty (1 empty slot) + sem_init(&full, 0, 0); // Initially, buffer is not full (0 filled slots) + pthread_attr_init(&attr); + + pthread_create(&reader, &attr, reader_function, 0); + + writer_function(); + + pthread_join(reader, 0); + + cleanup_resources(); + printf("Main thread finished!\n"); + return 0; +} + +void writer_function(void) { + char a = 0; + + while (a != 'q') { + sem_wait(&empty); + + a = make_new_item(); + buffer = a; + printf("Thread 1: buffer: '%c'\n", a); + + // Signal that the buffer is full + sem_post(&full); + } +} + +void *reader_function(void *ptr) { + char a = 0; + + while (a != 'q') { + sem_wait(&full); + + a = buffer; + if (a != 'q') { + consume_item(a, 0); + } + + sem_post(&empty); + } + + printf("Reader thread finished\n"); + return 0; +} + +int make_new_item() { + static int buffer = 'a'; + return buffer++; +} + +void consume_item(char a, int count) { + printf("Thread 2: buffer read with '%c'\n", a); +} diff --git a/ex06/aufgabe4.c b/ex06/aufgabe4.c new file mode 100644 index 0000000..61bb589 --- /dev/null +++ b/ex06/aufgabe4.c @@ -0,0 +1,103 @@ +#include +#include +//#include +#include +#include +#include +//#include +#include + +#define MAX_THREADS 50 +#define MAX_REGION_ENTRIES 10 + +void* thread_function(void *ptr); +void enter_region(size_t id); +void leave_region(size_t id); + +int cancel_threads = 0; +sem_t region_semaphore; +pthread_mutex_t region_mutex = PTHREAD_MUTEX_INITIALIZER; +size_t regionentries[MAX_REGION_ENTRIES]; + +int main(int argc, char *argv[]) { + pthread_attr_t attr; + pthread_t threads[MAX_THREADS]; + size_t i, counter = 0; + + // 0=local process, MAX_REGION_ENTRIES=initial state + if ( sem_init( ®ion_semaphore, 0, MAX_REGION_ENTRIES ) == 0 ) { + if ( pthread_attr_init( &attr ) == 0 ) { + for (i=0; itm_sec+localtime(&t)->tm_min)*1000 ); + leave_region(threadid); + sched_yield(); // yield CPU + } + printf("Thread %zu finished!\n", threadid); + return 0; +} + +void print_region_entries() { + int i; + printf("Threads in region: "); + for (i=0; i +#include +#include +#include + +#define LOOPCOUNT 200 +void* reader_function(void*); +void writer_function(void); + +int buffer_a, buffer_b; +pthread_mutex_t mutex_a, mutex_b; + +int main(int argc, char* argv[]) { + pthread_mutexattr_t mutex_attr; + pthread_attr_t attr; + pthread_t reader; + + if (pthread_mutexattr_init(&mutex_attr) == 0) { + if (pthread_mutex_init(&mutex_a, &mutex_attr) == 0) { + if (pthread_mutex_init(&mutex_b, &mutex_attr) == 0) { + if (pthread_attr_init(&attr) == 0) { + if (pthread_create(&reader, &attr, reader_function, 0) == 0) { + writer_function(); + pthread_join(reader, 0); + } + } + pthread_mutex_destroy(&mutex_b); + } + pthread_mutex_destroy(&mutex_a); + } + } + printf("Main thread finished!\n"); + return 0; +} + +void writer_function(void) { + int i; + for (i = 0; i < LOOPCOUNT; i++) { + pthread_mutex_lock(&mutex_a); + buffer_a = i; + printf("Writer: Buffer a is : %d,\n", buffer_a); + pthread_mutex_lock(&mutex_b); + buffer_b = buffer_a; + printf("Writer: Buffer b is : %d,\n", buffer_b); + pthread_mutex_unlock(&mutex_b); + pthread_mutex_unlock(&mutex_a); + } +} + +void* reader_function(void* ptr) { + int i; + for (i = 0; i < LOOPCOUNT; i++) { + pthread_mutex_lock(&mutex_b); + printf("Reader: Buffer a is : %d,\n", buffer_a); + pthread_mutex_lock(&mutex_a); + printf("Reader: Buffer a+b is : %d,\n", buffer_b + buffer_a); + pthread_mutex_unlock(&mutex_a); + pthread_mutex_unlock(&mutex_b); + } + printf("Reader thread finished\n"); + return 0; +} diff --git a/ex07/aufgabe1_improved.c b/ex07/aufgabe1_improved.c new file mode 100644 index 0000000..fc00ddd --- /dev/null +++ b/ex07/aufgabe1_improved.c @@ -0,0 +1,63 @@ +// Compiler call: gccc aufgabe1.c -lpthread +#include +#include +#include +#include + +#define LOOPCOUNT 200 +void* reader_function(void*); +void writer_function(void); + +int buffer_a, buffer_b; +pthread_mutex_t mutex_a, mutex_b; + +int main(int argc, char* argv[]) { + pthread_mutexattr_t mutex_attr; + pthread_attr_t attr; + pthread_t reader; + + if (pthread_mutexattr_init(&mutex_attr) == 0) { + if (pthread_mutex_init(&mutex_a, &mutex_attr) == 0) { + if (pthread_mutex_init(&mutex_b, &mutex_attr) == 0) { + if (pthread_attr_init(&attr) == 0) { + if (pthread_create(&reader, &attr, reader_function, 0) == 0) { + writer_function(); + pthread_join(reader, 0); + } + } + pthread_mutex_destroy(&mutex_b); + } + pthread_mutex_destroy(&mutex_a); + } + } + printf("Main thread finished!\n"); + return 0; +} + +void writer_function(void) { + int i; + for (i = 0; i < LOOPCOUNT; i++) { + pthread_mutex_lock(&mutex_a); + buffer_a = i; + printf("Writer: Buffer a is : %d,\n", buffer_a); + pthread_mutex_lock(&mutex_b); + buffer_b = buffer_a; + printf("Writer: Buffer b is : %d,\n", buffer_b); + pthread_mutex_unlock(&mutex_b); + pthread_mutex_unlock(&mutex_a); + } +} + +void* reader_function(void* ptr) { + int i; + for (i = 0; i < LOOPCOUNT; i++) { + pthread_mutex_lock(&mutex_a); + printf("Reader: Buffer a+b is : %d,\n", buffer_b + buffer_a); + pthread_mutex_unlock(&mutex_a); + pthread_mutex_lock(&mutex_b); + printf("Reader: Buffer a is : %d,\n", buffer_a); + pthread_mutex_unlock(&mutex_b); + } + printf("Reader thread finished\n"); + return 0; +} diff --git a/ex07/aufgabe2.c b/ex07/aufgabe2.c new file mode 100644 index 0000000..3bfe373 --- /dev/null +++ b/ex07/aufgabe2.c @@ -0,0 +1,168 @@ +// Compiler call: cc -o aufgabe2 aufgabe2.c -lpthread + +#define _GNU_SOURCE +#include // pthread_* +#include // cpu_set_t , CPU_SET +#include +#include +#include // strcat +#include // nanosleep +#include + + +#define LOOPCOUNT 15 + +void* tH(void*); +void* tL(void*); + +void set_cpu_affinity(); + +pthread_mutex_t mutex_dbg; // buffer mutex (debug output) +pthread_mutex_t mutex_cs; // crit. section mutex + +char buffer[10000] = ""; + + +int main(int argc, char* argv[]) { + pthread_mutexattr_t mutex_attr; + + pthread_t thread_H, thread_L; + pthread_attr_t attr_H, attr_L; + struct sched_param param_H, param_L; + + int policy_father; + struct sched_param param_father; + + int i, j; + + set_cpu_affinity(); // bind to CPU core 0 + + // Father sched + pthread_getschedparam(pthread_self(), &policy_father, ¶m_father); + param_father.sched_priority = sched_get_priority_min(SCHED_RR); + pthread_setschedparam(pthread_self(), SCHED_RR, ¶m_father); + + if (pthread_mutexattr_init(&mutex_attr) == 0) { + if (pthread_mutex_init(&mutex_dbg, &mutex_attr) == 0) { + if (pthread_mutex_init(&mutex_cs, &mutex_attr) == 0) { + if (pthread_attr_init(&attr_H) == 0) { + if (pthread_attr_init(&attr_L) == 0) { + // T_H sched + pthread_attr_setschedpolicy(&attr_H, SCHED_RR); + pthread_attr_getschedparam(&attr_H, ¶m_H); + param_H.sched_priority = sched_get_priority_min(SCHED_RR); + pthread_attr_setschedparam(&attr_H, ¶m_H); + pthread_attr_setinheritsched(&attr_H, PTHREAD_EXPLICIT_SCHED); + + // T_L sched + pthread_attr_setschedpolicy(&attr_L, SCHED_RR); + pthread_attr_getschedparam(&attr_L, ¶m_L); + param_L.sched_priority = sched_get_priority_min(SCHED_RR) + 1; + pthread_attr_setschedparam(&attr_L, ¶m_L); + pthread_attr_setinheritsched(&attr_L, PTHREAD_EXPLICIT_SCHED); + + if (pthread_create(&thread_L, &attr_L, tL, 0) == 0) { + nanosleep((const struct timespec[]){{0, 10000000L}}, NULL); + + if (pthread_create(&thread_H, &attr_H, tH, 0) == 0) { + pthread_join(thread_H, 0); + } + pthread_join(thread_L, 0); + } + } + } + pthread_mutex_destroy(&mutex_dbg); + pthread_mutex_destroy(&mutex_cs); + } + } + } + printf("%s", buffer); + return 0; +} + + +void* tH(void* ptr) { + set_cpu_affinity(); // bind to CPU core 0 + + int i, j; + + // Thread T_H + + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_H. Attempting to lock mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + + pthread_mutex_lock(&mutex_cs); + // + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_H has locked mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + // + for (i = 0; i < LOOPCOUNT; i++) { + for (j = 0; j < 1000000; j++) { + ; + } // busy wait + + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "I am Thread T_H!\n"); + pthread_mutex_unlock(&mutex_dbg); + } + // + pthread_mutex_unlock(&mutex_cs); + + return 0; +} + +void* tL(void* ptr) { + set_cpu_affinity(); // bind to CPU core 0 + + int i, j; + + // Thread T_L + + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_L. Attempting to lock mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + + pthread_mutex_lock(&mutex_cs); + // + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_L has locked mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + // + for (i = 0; i < LOOPCOUNT; i++) { + for (j = 0; j < 1000000; j++) { + ; + } // busy wait + + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "I am Thread T_L!\n"); + pthread_mutex_unlock(&mutex_dbg); + } + // + pthread_mutex_unlock(&mutex_cs); + + return 0; +} + + +void set_cpu_affinity() { + // we can set one or more bits here, each one representing a single CPU + cpu_set_t cpuset; + + // the CPU we whant to use (core 0) + int cpu = 1; + + CPU_ZERO(&cpuset); // clears the cpuset + CPU_SET(cpu, &cpuset); // set CPU 0 on cpuset + + /* + * cpu affinity for the calling thread + * first parameter is the pid, 0 = calling thread + * second parameter is the size of your cpuset + * third param is the cpuset in which your thread will be + * placed. Each bit represents a CPU + */ + sched_setaffinity(0, sizeof(cpuset), &cpuset); + // pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset); +} diff --git a/ex07/aufgabe2_gpt.c b/ex07/aufgabe2_gpt.c new file mode 100644 index 0000000..222cd5a --- /dev/null +++ b/ex07/aufgabe2_gpt.c @@ -0,0 +1,132 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#define LOOPCOUNT 15 + +void* tH(void*); +void* tL(void*); + +void set_cpu_affinity(int cpu); + +pthread_mutex_t mutex_dbg; // buffer mutex (debug output) +pthread_mutex_t mutex_cs; // critical section mutex + +char buffer[10000] = ""; + +int main(int argc, char* argv[]) { + pthread_mutexattr_t mutex_attr; + + pthread_t thread_H, thread_L; + pthread_attr_t attr_H, attr_L; + struct sched_param param_H, param_L; + + int policy_father; + struct sched_param param_father; + + set_cpu_affinity(0); // bind to CPU core 0 + + // Father sched + pthread_getschedparam(pthread_self(), &policy_father, ¶m_father); + param_father.sched_priority = sched_get_priority_min(SCHED_RR); + pthread_setschedparam(pthread_self(), SCHED_RR, ¶m_father); + + if (pthread_mutexattr_init(&mutex_attr) == 0) { + pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT); // Enable priority inheritance + + if (pthread_mutex_init(&mutex_dbg, &mutex_attr) == 0) { + if (pthread_mutex_init(&mutex_cs, &mutex_attr) == 0) { + if (pthread_attr_init(&attr_H) == 0) { + if (pthread_attr_init(&attr_L) == 0) { + // T_H sched + pthread_attr_setschedpolicy(&attr_H, SCHED_RR); + param_H.sched_priority = sched_get_priority_max(SCHED_RR); // Higher priority + pthread_attr_setschedparam(&attr_H, ¶m_H); + pthread_attr_setinheritsched(&attr_H, PTHREAD_EXPLICIT_SCHED); + + // T_L sched + pthread_attr_setschedpolicy(&attr_L, SCHED_RR); + param_L.sched_priority = sched_get_priority_min(SCHED_RR); // Lower priority + pthread_attr_setschedparam(&attr_L, ¶m_L); + pthread_attr_setinheritsched(&attr_L, PTHREAD_EXPLICIT_SCHED); + + if (pthread_create(&thread_L, &attr_L, tL, NULL) == 0) { + nanosleep((const struct timespec[]){{0, 10000000L}}, NULL); + + if (pthread_create(&thread_H, &attr_H, tH, NULL) == 0) { + pthread_join(thread_H, NULL); + } + pthread_join(thread_L, NULL); + } + } + } + pthread_mutex_destroy(&mutex_dbg); + pthread_mutex_destroy(&mutex_cs); + } + } + } + printf("%s", buffer); + return 0; +} + +void* tH(void* ptr) { + set_cpu_affinity(0); // bind to CPU core 0 + + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_H. Attempting to lock mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + + pthread_mutex_lock(&mutex_cs); + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_H has locked mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + + for (int i = 0; i < LOOPCOUNT; i++) { + for (int j = 0; j < 1000000; j++) { + ; // busy wait + } + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "I am Thread T_H!\n"); + pthread_mutex_unlock(&mutex_dbg); + } + pthread_mutex_unlock(&mutex_cs); + + return NULL; +} + +void* tL(void* ptr) { + set_cpu_affinity(0); // bind to CPU core 0 + + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_L. Attempting to lock mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + + pthread_mutex_lock(&mutex_cs); + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_L has locked mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + + for (int i = 0; i < LOOPCOUNT; i++) { + for (int j = 0; j < 1000000; j++) { + ; // busy wait + } + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "I am Thread T_L!\n"); + pthread_mutex_unlock(&mutex_dbg); + } + pthread_mutex_unlock(&mutex_cs); + + return NULL; +} + +void set_cpu_affinity(int cpu) { + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(cpu, &cpuset); + sched_setaffinity(0, sizeof(cpuset), &cpuset); +} diff --git a/ex07/aufgabe2_improved.c b/ex07/aufgabe2_improved.c new file mode 100644 index 0000000..a2f1b93 --- /dev/null +++ b/ex07/aufgabe2_improved.c @@ -0,0 +1,170 @@ +// Compiler call: cc -o aufgabe2 aufgabe2.c -lpthread +// requires sudod to run + +#define _GNU_SOURCE +#include // pthread_* +#include // cpu_set_t , CPU_SET +#include +#include +#include // strcat +#include // nanosleep +#include + + +#define LOOPCOUNT 15 + +void* tH(void*); +void* tL(void*); + +void set_cpu_affinity(); + +pthread_mutex_t mutex_dbg; // buffer mutex (debug output) +pthread_mutex_t mutex_cs; // crit. section mutex + +char buffer[10000] = ""; + + +int main(int argc, char* argv[]) { + pthread_mutexattr_t mutex_attr; + + pthread_t thread_H, thread_L; + pthread_attr_t attr_H, attr_L; + struct sched_param param_H, param_L; + + int policy_father; + struct sched_param param_father; + + int i, j; + + set_cpu_affinity(); // bind to CPU core 0 + + // Father sched + pthread_getschedparam(pthread_self(), &policy_father, ¶m_father); + param_father.sched_priority = sched_get_priority_min(SCHED_RR); + pthread_setschedparam(pthread_self(), SCHED_RR, ¶m_father); + + if (pthread_mutexattr_init(&mutex_attr) == 0) { + pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT); // Enable priority inheritance + if (pthread_mutex_init(&mutex_dbg, &mutex_attr) == 0) { + if (pthread_mutex_init(&mutex_cs, &mutex_attr) == 0) { + if (pthread_attr_init(&attr_H) == 0) { + if (pthread_attr_init(&attr_L) == 0) { + // T_H sched + pthread_attr_setschedpolicy(&attr_H, SCHED_RR); + pthread_attr_getschedparam(&attr_H, ¶m_H); + param_H.sched_priority = sched_get_priority_min(SCHED_RR) + 1; + pthread_attr_setschedparam(&attr_H, ¶m_H); + pthread_attr_setinheritsched(&attr_H, PTHREAD_EXPLICIT_SCHED); + + // T_L sched + pthread_attr_setschedpolicy(&attr_L, SCHED_RR); + pthread_attr_getschedparam(&attr_L, ¶m_L); + param_L.sched_priority = sched_get_priority_min(SCHED_RR); + pthread_attr_setschedparam(&attr_L, ¶m_L); + pthread_attr_setinheritsched(&attr_L, PTHREAD_EXPLICIT_SCHED); + + if (pthread_create(&thread_L, &attr_L, tL, 0) == 0) { + nanosleep((const struct timespec[]){{0, 10000000L}}, NULL); + + if (pthread_create(&thread_H, &attr_H, tH, 0) == 0) { + pthread_join(thread_H, 0); + } + pthread_join(thread_L, 0); + } + } + } + pthread_mutex_destroy(&mutex_dbg); + pthread_mutex_destroy(&mutex_cs); + } + } + } + printf("%s", buffer); + return 0; +} + + +void* tH(void* ptr) { + set_cpu_affinity(); // bind to CPU core 0 + + int i, j; + + // Thread T_H + + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_H. Attempting to lock mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + + pthread_mutex_lock(&mutex_cs); + // + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_H has locked mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + // + for (i = 0; i < LOOPCOUNT; i++) { + for (j = 0; j < 1000000; j++) { + ; + } // busy wait + + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "I am Thread T_H!\n"); + pthread_mutex_unlock(&mutex_dbg); + } + // + pthread_mutex_unlock(&mutex_cs); + + return 0; +} + +void* tL(void* ptr) { + set_cpu_affinity(); // bind to CPU core 0 + + int i, j; + + // Thread T_L + + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_L. Attempting to lock mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + + pthread_mutex_lock(&mutex_cs); + // + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "Thread T_L has locked mutex_cs!\n"); + pthread_mutex_unlock(&mutex_dbg); + // + for (i = 0; i < LOOPCOUNT; i++) { + for (j = 0; j < 1000000; j++) { + ; + } // busy wait + + pthread_mutex_lock(&mutex_dbg); + strcat(buffer, "I am Thread T_L!\n"); + pthread_mutex_unlock(&mutex_dbg); + } + // + pthread_mutex_unlock(&mutex_cs); + + return 0; +} + + +void set_cpu_affinity() { + // we can set one or more bits here, each one representing a single CPU + cpu_set_t cpuset; + + // the CPU we whant to use (core 0) + int cpu = 1; + + CPU_ZERO(&cpuset); // clears the cpuset + CPU_SET(cpu, &cpuset); // set CPU 0 on cpuset + + /* + * cpu affinity for the calling thread + * first parameter is the pid, 0 = calling thread + * second parameter is the size of your cpuset + * third param is the cpuset in which your thread will be + * placed. Each bit represents a CPU + */ + sched_setaffinity(0, sizeof(cpuset), &cpuset); + // pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset); +} diff --git a/ex07/aufgabe5.c b/ex07/aufgabe5.c new file mode 100644 index 0000000..41d8d9c --- /dev/null +++ b/ex07/aufgabe5.c @@ -0,0 +1,72 @@ +// Compiler call: gcc -o aufgabe1 aufgabe1.c -lpthread +#include +#include +#include +#include + +#define LOOPCOUNT 200 +void* reader_function(void*); +void writer_function(void); + +int buffer_a, buffer_b; +pthread_mutex_t mutex_a, mutex_b; + +int main(int argc, char* argv[]) { + pthread_mutexattr_t mutex_attr; + pthread_attr_t attr; + pthread_t reader; + + // Initialize mutex attributes + if (pthread_mutexattr_init(&mutex_attr) == 0) { + // Set the mutex protocol to PCP + pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_PROTECT); + + // Set the priority ceiling for each mutex + pthread_mutexattr_setprioceiling(&mutex_attr, 10); // Example priority ceiling + + if (pthread_mutex_init(&mutex_a, &mutex_attr) == 0) { + if (pthread_mutex_init(&mutex_b, &mutex_attr) == 0) { + if (pthread_attr_init(&attr) == 0) { + // Create the reader thread + if (pthread_create(&reader, &attr, reader_function, 0) == 0) { + writer_function(); + pthread_join(reader, 0); + } + } + pthread_mutex_destroy(&mutex_b); + } + pthread_mutex_destroy(&mutex_a); + } + } + printf("Main thread finished!\n"); + return 0; +} + +void writer_function(void) { + int i; + for (i = 0; i < LOOPCOUNT; i++) { + pthread_mutex_lock(&mutex_a); + buffer_a = i; + printf("Writer: Buffer a is : %d,\n", buffer_a); + pthread_mutex_lock(&mutex_b); + buffer_b = buffer_a; + printf("Writer: Buffer b is : %d,\n", buffer_b); + pthread_mutex_unlock(&mutex_b); + pthread_mutex_unlock(&mutex_a); + } +} + +void* reader_function(void* ptr) { + int i; + for (i = 0; i < LOOPCOUNT; i++) { + pthread_mutex_lock(&mutex_a); + printf("Reader: Buffer a+b is : %d,\n", buffer_b + buffer_a); + pthread_mutex_unlock(&mutex_a); + pthread_mutex_lock(&mutex_b); + printf("Reader: Buffer a is : %d,\n", buffer_a); + pthread_mutex_unlock(&mutex_b); + } + printf("Reader thread finished\n"); + return 0; +} + diff --git a/howto_shell_cheatsheet.txt b/howto_shell_cheatsheet.txt new file mode 100644 index 0000000..0954ecf --- /dev/null +++ b/howto_shell_cheatsheet.txt @@ -0,0 +1,80 @@ + +Everything in <> is variable and depends on your system / your intention + +The prompt is always shown in your shell: +@: $ + + is the user that is running the shell (important if you work with multiple user accounts e.g. root and user) + is the hostname of the PC the shell is running on (important if you connect to remote machines) + is the path where you are currently located at + +As soon as the prompt is shown you can enter any command. +The 'TAB' key autocompletes commands and paths as soon as there is no ambiguity. +If multiple possibilities exist 2x'TAB' will diplay them. + +################################################################################ +Commands you should know: +################################################################################ + +man show manual for the command + exit with 'q' + +ls list directory (mind the space between command and options, this is always the case) +ls is empty just list the directory +ls -l is '-l' list directory with more details (permissions owner group size date time filename) +ls -a is '-a' list directory including hidden files +ls -a -l are '-a -l' list directory (also hidden files) with more details (mind the space again) + +cd change directory (relative to your current directory) +cd / change directory (absolute [from the file system root]) + +mkdir create folder +mkdir -p create all folders to this path + +rm remove the file +rm -r remove folder (recursive) + +chmod change file permissions (read, write, execute) for owner, group and others + Permissions are typically shown this way: rwxrwxrwx + first entry (rwx) is for the owner of the file/folder + second entry (rwx) is for the group this file/folder belongs to + third entry (rwx) is for all others + missing permissions are shown with a dash '-' + rwxr-xr-- means the owner can do anything; the group can read and execute; all others can only read + +chmod +x make file executable for everyone (+w -> writable; +r -> readable) +chmod -x writable; -r -> readable) +chmod u+x make file executable for the owner (u=owner, g=group, o=others a=all) +chmod u-x read file contents (prints the whole file to the terminal) +less read file contents (page by page) [exit with 'q'] + +echo print to the terminal +echo > print to the file (note the '>' before ) + using the operator '>' the output of every program can be written to a file + what would 'ls -l > out' do? + +nano edit a file with the "nano" CLI text editor, creates the file if not existing + +./ executes a program in the current directory +/.../ executes a program in an absolute path (from root) + +/.../ & executes a program in background +/.../ &>/dev/null executes a program silently with stdout and stderr redirected to /dev/null +/.../ &>/dev/null & executes a program silently and in background + +chrt -f starts directly with RT priority , sets policy SCHED_FIFO +chrt -r starts directly with RT priority , sets policy SCHED_RR +chrt -f -p changes RT priority of running process/thread ID to , sets policy SCHED_FIFO +chrt -r -p changes RT priority of running process/thread ID to , sets policy SCHED_RR + +sudo executes as root user + +################################################################################ +Paths you need to know: +################################################################################ + +/ the root of your file system tree +/home// the home directory of the currently logged in user . Shorthand: '~' +/sys/class/gpio/ access to the gpio pins (if available) - see sysfs \ No newline at end of file diff --git a/lab/square_wave.c b/lab/square_wave.c new file mode 100644 index 0000000..4ca5ec0 --- /dev/null +++ b/lab/square_wave.c @@ -0,0 +1,87 @@ +#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; + +void* high_thread(void* arg) { + while (1) { + pthread_mutex_lock(&lock); + + // Wait for turn + while (signal_flag != 1) { + pthread_cond_wait(&cond, &lock); + } + + // Critical section + if (counter >= ITERATIONS) { + pthread_mutex_unlock(&lock); + pthread_cond_signal(&cond); + exit(0); + } + printf("%d: HIGH\n", counter); + counter++; + signal_flag = 0; + + // Signal the other thread + pthread_mutex_unlock(&lock); + pthread_cond_signal(&cond); + } + return NULL; +} + +void* low_thread(void* arg) { + while (1) { + pthread_mutex_lock(&lock); + + // Wait for turn + while (signal_flag != 0) { + pthread_cond_wait(&cond, &lock); + } + + // Critical section + if (counter >= ITERATIONS) { + pthread_mutex_unlock(&lock); + pthread_cond_signal(&cond); + exit(0); + } + printf("%d: LOW\n", counter); + counter++; + signal_flag = 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); + + // Wait for threads to finish + pthread_join(high_tid, NULL); + pthread_join(low_tid, NULL); + + // Cleanup + pthread_mutex_destroy(&lock); + pthread_cond_destroy(&cond); + + return 0; +} +