169 lines
4.5 KiB
C
169 lines
4.5 KiB
C
// 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);
|
|
}
|