#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #define gettid() syscall(__NR_gettid) #define SCHED_DEADLINE 6 /* XXX use the proper syscall numbers */ #ifdef __x86_64__ #define __NR_sched_setattr 314 #define __NR_sched_getattr 315 #endif #ifdef __i386__ #define __NR_sched_setattr 351 #define __NR_sched_getattr 352 #endif #ifdef __ppc64__ #define __NR_sched_setattr 355 #define __NR_sched_getattr 356 #endif #ifdef __s390x__ #define __NR_sched_setattr 345 #define __NR_sched_getattr 346 #endif static volatile int done; struct sched_attr { __u32 size; __u32 sched_policy; __u64 sched_flags; /* SCHED_NORMAL, SCHED_BATCH */ __s32 sched_nice; /* SCHED_FIFO, SCHED_RR */ __u32 sched_priority; /* SCHED_DEADLINE (nsec) */ __u64 sched_runtime; __u64 sched_deadline; __u64 sched_period; }; int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags) { return syscall(__NR_sched_setattr, pid, attr, flags); } int sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags) { return syscall(__NR_sched_getattr, pid, attr, size, flags); } pthread_mutex_t mutex_obj; pthread_mutexattr_t mutex_attr; int x = 0; static int decide(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); if (ts.tv_nsec & 1) return 1; else return 0; } static void mutex_init(void) { pthread_mutexattr_init(&mutex_attr); pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT); pthread_mutex_init(&mutex_obj, &mutex_attr); } static deadline_ndelay(unsigned int cnt) { unsigned int i; for (i = 0; i < 10000 * cnt; i++); } void *run_deadline_special(void *data) { struct sched_attr attr; int ret, take; unsigned int flags = 0; attr.size = sizeof(attr); attr.sched_flags = 0; attr.sched_nice = 0; attr.sched_priority = 0; /* This creates a 10ms/30ms reservation */ attr.sched_policy = SCHED_DEADLINE; attr.sched_runtime = 100 * 1000 * 1000; attr.sched_deadline = 200 * 1000 * 1000; attr.sched_period = 300 * 1000 * 1000; ret = sched_setattr(0, &attr, flags); if (ret < 0) { done = 0; perror("sched_setattr"); exit(-1); } printf("special deadline thread started [%ld]\n", gettid()); while (!done) { take = decide(); if (take) pthread_mutex_lock(&mutex_obj); x++; deadline_ndelay((unsigned long) attr.sched_runtime % 7); if (take) pthread_mutex_unlock(&mutex_obj); } printf("special deadline thread dies [%ld]\n", gettid()); return NULL; } void *run_deadline(void *data) { struct sched_attr attr; int ret, take; unsigned int flags = 0; static unsigned int delta = 0; attr.size = sizeof(attr); attr.sched_flags = 0; attr.sched_nice = 0; attr.sched_priority = 0; /* This creates a 10ms/30ms reservation */ delta += 1000 * 1000 * 2; attr.sched_policy = SCHED_DEADLINE; attr.sched_runtime = 20 * 1000 * 1000 + delta; attr.sched_deadline = 400 * 1000 * 1000; attr.sched_period = 400 * 1000 * 1000; ret = sched_setattr(0, &attr, flags); if (ret < 0) { done = 0; perror("sched_setattr"); exit(-1); } printf("deadline thread started [%ld]\n", gettid()); while (!done) { take = decide(); if (take) pthread_mutex_lock(&mutex_obj); x++; deadline_ndelay((unsigned long) attr.sched_runtime % 7); if (take) pthread_mutex_unlock(&mutex_obj); } printf("deadline thread dies [%ld]\n", gettid()); return NULL; } #define THREAD_NUM 10 int main (int argc, char **argv) { pthread_t thread[THREAD_NUM]; int i; mutex_init(); printf("main thread [%ld]\n", gettid()); for (i = 0; i < THREAD_NUM-1; i++) pthread_create(&thread[i], NULL, run_deadline, NULL); pthread_create(&thread[THREAD_NUM-1], NULL, run_deadline_special, NULL); sleep(3600*300); done = 1; for (i = 0; i < THREAD_NUM; i++) pthread_join(thread[i], NULL); printf("main dies [%ld]\n", gettid()); return 0; }