lookflying
lookflying

Reputation: 41

pthread_create returns EAGAIN when the main thread is set sched_deadline scheduling policy

I would like to let a process be scheduled under the new Linux SCHED_DEADLINE scheduling policy. Meanwhile, this process has to create some worker threads do to some other work. However, when I called pthread_create after a successful call of sched_setattr(which is to set the process scheduling policy), I got an EAGAIN. I know it might be a little strange to create a thread in a realtime process. Some problems such as "what scheduling policy of the new thread will be" may arise.

Despite of that , is there a way to create a new thread in a SCHED_DEADLINE process?

And how to define the scheduling policy of the new thread?

The code to reproduce my problem can be found at

https://github.com/lookflying/pthread_deadline/

Upvotes: 4

Views: 1200

Answers (2)

Claudio
Claudio

Reputation: 10947

When merging SCHED_DEADLINE, the kernel community explicitly discussed this topic in the list, and decided to not allow SCHED_DEADLINE tasks create other tasks (either by fork() or by pthread_create()).

Therefore, currently, there is no way of achieving such behavior. You have to create the tasks before setting the SCHED_DEADLINE priority.

Concerning the second question, unfortunately the glibc has not yet wrapped the sched_setattr() syscall (despite available since 4 years). Here is some code for creating a SCHED_DEADLINE task:

#define _GNU_SOURCE
#include <linux/kernel.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <time.h>
#include <linux/types.h>
#include <sched.h>
#include <linux/sched.h>
#include <sys/types.h>

#define SCHED_DEADLINE  6

/* __NR_sched_setattr number */
#ifndef __NR_sched_setattr
#ifdef __x86_64__
#define __NR_sched_setattr      314
#endif

#ifdef __i386__
#define __NR_sched_setattr      351
#endif

#ifdef __arm__
#define __NR_sched_setattr      380
#endif

#ifdef __aarch64__
#define __NR_sched_setattr      274
#endif
#endif

/* __NR_sched_getattr number */
#ifndef __NR_sched_getattr
#ifdef __x86_64__
#define __NR_sched_getattr      315
#endif

#ifdef __i386__
#define __NR_sched_getattr      352
#endif

#ifdef __arm__
#define __NR_sched_getattr      381
#endif

#ifdef __aarch64__
#define __NR_sched_getattr      275
#endif
#endif

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

Then, in the task code:

struct sched_attr attr;
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 = 10 * 1000 * 1000;
attr.sched_period = attr.sched_deadline = 30 * 1000 * 1000;

if (sched_setattr(0, &attr, flags) < 0) {
       perror("sched_setattr()");
}

Upvotes: 2

user3793679
user3793679

Reputation:

I think you will find that the default scheduling policy for a new pthread is PTHREAD_INHERIT_SCHED. To override this you need to pthread_attr_init() an explicit set of attributes, futz about with pthread_attr_setschedpolicy() and pthread_attr_setschedparam(), and then apply those attributes in pthread_create().

You could sched_getscheduler() and sched_getparam() before setting the process to SCHED_DEADLINE and feed those into the pthread_attr for use later.

Upvotes: 0

Related Questions