7

Currently I'm running Ubuntu 16.04 with linux kernel version to be 4.16. I wrote a dummy program that changes its scheduler to SCHED_DEADLINE. But when I tried to compile it, it cannot find definition of structs and macros needed for SCHED_DEADLINE. Most of the code snippet was taken from here (page 24). Below is the test program:

#define _GNU_SOURCE
#include <pthread.h>
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sched.h> 


int main(int argc, char* argv[]) {

    struct sched_attr attr;
    attr.size = sizeof(attr);
    attr.sched_policy = SCHED_DEADLINE;
    attr.sched_runtime = 30000000;
    attr.sched_period = 100000000;
    attr.sched_deadline = attr.sched_period;
    if (sched_setattr(gettid(), &attr, 0))
        perror("sched_setattr()");

    return 0;
}

Here's the output of the compilation:

sched_deadline.c: In function ‘main’:
sched_deadline.c:11:20: error: storage size of ‘attr’ isn’t known
  struct sched_attr attr;
                    ^
sched_deadline.c:12:21: error: invalid application of ‘sizeof’ to incomplete type ‘struct attr’
  attr.size = sizeof(struct attr);
                     ^
sched_deadline.c:13:22: error: ‘SCHED_DEADLINE’ undeclared (first use in this function)
  attr.sched_policy = SCHED_DEADLINE;

My gcc version:

gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)

However, the sample code posted in the official website works for me, but the sample code manually defines all the needed macros and system calls in the program. My goal was to compile the application without adding those definitions, which should already be included in the newest kernel version. I have seen various places saying that SCHED_DEADLINE is officially supported after Linux 3.14.10, and upgrading the kernel would automatically solve this issue.

Things I've tried:

  • Recompiling 4.16 kernel. Previously I thought I need to turn on a switch in config file, but I was not able to find it.
  • Look into /usr/include/linux/sched.h. Clearly the macros are defined in this header file, but somehow my compiler cannot find it.

I also looked into other posts in the community, but all those questions are for older linux (pre 3.14.10).

Claudio
  • 10,614
  • 4
  • 31
  • 71
Pringles
  • 187
  • 10
  • This may help. It's not a dup per se: https://stackoverflow.com/questions/36739005/deadline-scheduling-policy-not-found – Craig Estey Apr 29 '18 at 04:44
  • @CraigEstey Thanks for the link. I actually saw this post before, but the best answer also used manually-defined structs. My previous goal was to use the EDF scheduling without any extra redundant definition, but it seems that even if the algorithm is already implemented in linux, glibc won't export that to userland because this algorithm and syscall is linux specific. – Pringles Apr 29 '18 at 17:04

1 Answers1

4

You need to include #include <linux/sched.h>

But for the definition of sched_setattr() and gettid(), see the link posted by @CraigEstey

The reason about that, it that glibc will not add function wrappers of linux specific syscall. For example for gettid(), in the manual we can read this:

Note: There is no glibc wrapper for this system call; see NOTES.

Glibc does not provide a wrapper for this system call; call it using syscall(2). The thread ID returned by this call is not the same thing as a POSIX thread ID

Have a look at this article: https://lwn.net/Articles/711058/

#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sched.h>
#include <linux/sched.h>
#include <sys/types.h>

struct sched_attr {
    uint32_t size;

    uint32_t sched_policy;
    uint64_t sched_flags;

    /* SCHED_NORMAL, SCHED_BATCH */
    int32_t sched_nice;

    /* SCHED_FIFO, SCHED_RR */
    uint32_t sched_priority;

    /* SCHED_DEADLINE (nsec) */
    uint64_t sched_runtime;
    uint64_t sched_deadline;
    uint64_t 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 main(int argc, char* argv[]) {

    struct sched_attr attr = {
        .size = sizeof(attr),
        .sched_policy = SCHED_DEADLINE,
        .sched_runtime = 30000000,
        .sched_period = 100000000,
        .sched_deadline = 100000000
    };

    pid_t tid = syscall(SYS_gettid);

    if (sched_setattr(tid, &attr, 0))
        perror("sched_setattr()");

    return 0;
}

Or a more shorter code, without the redefinition of struct sched_attr

#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/sched/types.h>
#include <linux/sched.h>
#include <sys/types.h>

int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags)
{
   return syscall(__NR_sched_setattr, pid, attr, flags);
}

int main(int argc, char* argv[]) {

    struct sched_attr attr = {
        .size = sizeof(attr),
        .sched_policy = SCHED_DEADLINE,
        .sched_runtime = 30000000,
        .sched_period = 100000000,
        .sched_deadline = 100000000
    };

    pid_t tid = syscall(SYS_gettid);

    if (sched_setattr(tid, &attr, 0))
        perror("sched_setattr()");

    return 0;
}

But this needs to be executed as root, otherwise I got sched_setattr(): Operation not permitted Or the application needs to have the right linux capabilities.

benjarobin
  • 4,410
  • 27
  • 21
  • hi @benjarobin, thanks for the reply. What do you mean by "glibc refuse to add linux specific functions interface"? Isn't sched_setattr() one of the system calls in linux (syscall number 314 in x86)? Doesn't standard library export it to user space? – Pringles Apr 29 '18 at 15:05
  • @Pringles I did edit my message. But to clarify glibc (and most of libc implementation) will not implements the wrapper of linux specific syscall. – benjarobin Apr 29 '18 at 16:51
  • That makes sense. Thanks a lot! – Pringles Apr 29 '18 at 16:59