// 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); }