initial commit
This commit is contained in:
commit
8b3abe2dde
|
|
@ -0,0 +1,6 @@
|
|||
*
|
||||
!*.*
|
||||
!*/
|
||||
*.ova
|
||||
*.iso
|
||||
*.pdf
|
||||
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("Hello, World!\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h> // fork, sleep
|
||||
#include <stdlib.h> // exit
|
||||
#include <sys/wait.h> // 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h> // exit
|
||||
#include <unistd.h> // fork, sleep
|
||||
#include <sys/wait.h> // 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;
|
||||
}
|
||||
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
fork();
|
||||
fork();
|
||||
printf("test\n");
|
||||
}
|
||||
|
||||
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("I am the son.\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <number of children>\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;
|
||||
}
|
||||
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <ctype.h>
|
||||
|
||||
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 <filename>\n");
|
||||
exit(1);
|
||||
}
|
||||
for (i=1; i<argc; i++) {
|
||||
if ((dz=fopen(argv[i],"rb")) == NULL ) {
|
||||
fprintf(stderr,"Can't open file %s\n", argv[i]);
|
||||
exit(1);
|
||||
} else {
|
||||
hex_print(dz,argv[i]);
|
||||
fclose(dz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
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 <filename>\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;
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,117 @@
|
|||
// Compiler call: cc -o aufgabe1 aufgabe1.c -lpthread
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
//#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// 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++;
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
//#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <semaphore.h>
|
||||
//#include <limits.h>
|
||||
#include <sched.h>
|
||||
|
||||
#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; i<MAX_THREADS; i++) {
|
||||
if ( pthread_create( &(threads[counter]), &attr, thread_function, (void*)(i+1)) == 0 )
|
||||
counter++;
|
||||
}
|
||||
scanf("%d", &cancel_threads); // set cancel condition
|
||||
for (i=0;i<counter;i++) {
|
||||
pthread_join( threads[i], 0);
|
||||
}
|
||||
}
|
||||
sem_destroy( ®ion_semaphore);
|
||||
}
|
||||
printf("Main thread finished!\n");
|
||||
}
|
||||
|
||||
void* thread_function(void *ptr)
|
||||
{
|
||||
size_t threadid=(size_t)ptr;
|
||||
time_t t;
|
||||
|
||||
while( ! cancel_threads ){
|
||||
enter_region(threadid);
|
||||
t=time(0); // short wait (passive)
|
||||
usleep((localtime(&t)->tm_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<MAX_REGION_ENTRIES; i++)
|
||||
printf("%zu ", regionentries[i]);
|
||||
printf("\n");
|
||||
|
||||
for(i=0;i<1000000;i++) // short wait (active)
|
||||
i;
|
||||
}
|
||||
|
||||
|
||||
void enter_region(size_t id) {
|
||||
int i;
|
||||
sem_wait( ®ion_semaphore );
|
||||
|
||||
pthread_mutex_lock(®ion_mutex);
|
||||
for (i=0;i<MAX_REGION_ENTRIES;i++) {
|
||||
if ( regionentries[i]==0 ) {
|
||||
regionentries[i]=id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
print_region_entries();
|
||||
pthread_mutex_unlock(®ion_mutex);
|
||||
}
|
||||
|
||||
|
||||
void leave_region(size_t id)
|
||||
{
|
||||
int i;
|
||||
|
||||
pthread_mutex_lock(®ion_mutex);
|
||||
for (i=0;i<MAX_REGION_ENTRIES;i++) {
|
||||
if ( regionentries[i]==id )
|
||||
{ regionentries[i]=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
print_region_entries();
|
||||
pthread_mutex_unlock(®ion_mutex);
|
||||
|
||||
sem_post( ®ion_semaphore );
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
// Compiler call: gccc aufgabe1.c -lpthread
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
// Compiler call: gccc aufgabe1.c -lpthread
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
// Compiler call: cc -o aufgabe2 aufgabe2.c -lpthread
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <pthread.h> // pthread_*
|
||||
#include <sched.h> // cpu_set_t , CPU_SET
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> // strcat
|
||||
#include <time.h> // nanosleep
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
// Compiler call: cc -o aufgabe2 aufgabe2.c -lpthread
|
||||
// requires sudod to run
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <pthread.h> // pthread_*
|
||||
#include <sched.h> // cpu_set_t , CPU_SET
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> // strcat
|
||||
#include <time.h> // nanosleep
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// Compiler call: gcc -o aufgabe1 aufgabe1.c -lpthread
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
|
||||
Everything in <> is variable and depends on your system / your intention
|
||||
|
||||
The prompt is always shown in your shell:
|
||||
<user>@<host>:<path> $
|
||||
|
||||
<user> is the user that is running the shell (important if you work with multiple user accounts e.g. root and user)
|
||||
<host> is the hostname of the PC the shell is running on (important if you connect to remote machines)
|
||||
<path> 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 <command> show manual for the command <command>
|
||||
exit with 'q'
|
||||
|
||||
ls <options> list directory (mind the space between command and options, this is always the case)
|
||||
ls <options> is empty just list the directory
|
||||
ls -l <options> is '-l' list directory with more details (permissions owner group size date time filename)
|
||||
ls -a <options> is '-a' list directory including hidden files
|
||||
ls -a -l <options> are '-a -l' list directory (also hidden files) with more details (mind the space again)
|
||||
|
||||
cd <path> change directory (relative to your current directory)
|
||||
cd /<path> change directory (absolute [from the file system root])
|
||||
|
||||
mkdir <folder> create folder
|
||||
mkdir -p <path> create all folders to this path
|
||||
|
||||
rm <file> remove the file
|
||||
rm -r <folder> remove folder (recursive)
|
||||
|
||||
chmod <permissions> <file> 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 <file> make file executable for everyone (+w -> writable; +r -> readable)
|
||||
chmod -x <file remove the right to execute for everyone (-w -> writable; -r -> readable)
|
||||
chmod u+x <file> make file executable for the owner (u=owner, g=group, o=others a=all)
|
||||
chmod u-x <file remove the right to execute for the owner
|
||||
|
||||
cat <file> read file contents (prints the whole file to the terminal)
|
||||
less <file> read file contents (page by page) [exit with 'q']
|
||||
|
||||
echo <text> print <text> to the terminal
|
||||
echo <text> > <file> print <text> to the file <file> (note the '>' before <file> )
|
||||
using the operator '>' the output of every program can be written to a file
|
||||
what would 'ls -l > out' do?
|
||||
|
||||
nano <file> edit a file with the "nano" CLI text editor, creates the file if not existing
|
||||
|
||||
./<prog> executes a program in the current directory
|
||||
/.../<prog> executes a program in an absolute path (from root)
|
||||
|
||||
/.../<prog> & executes a program in background
|
||||
/.../<prog> &>/dev/null executes a program silently with stdout and stderr redirected to /dev/null
|
||||
/.../<prog> &>/dev/null & executes a program silently and in background
|
||||
|
||||
chrt -f <prio> <prog> starts <prog> directly with RT priority <prio>, sets policy SCHED_FIFO
|
||||
chrt -r <prio> <prog> starts <prog> directly with RT priority <prio>, sets policy SCHED_RR
|
||||
chrt -f -p <prio> <id> changes RT priority of running process/thread ID <id> to <prio>, sets policy SCHED_FIFO
|
||||
chrt -r -p <prio> <id> changes RT priority of running process/thread ID <id> to <prio>, sets policy SCHED_RR
|
||||
|
||||
sudo <cmd> executes <cmd> as root user
|
||||
|
||||
################################################################################
|
||||
Paths you need to know:
|
||||
################################################################################
|
||||
|
||||
/ the root of your file system tree
|
||||
/home/<user>/ the home directory of the currently logged in user <user>. Shorthand: '~'
|
||||
/sys/class/gpio/ access to the gpio pins (if available) - see sysfs
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue