linux – Priority scheduling with pthreads and SCHED_FIFO

Question: Question:

I am wondering if I can simulate an RTOS program with the Linux API. The purpose is to test the same code on a PC, and I don't really care about real-timeness.
Looking at the man page etc., there was a description that if SCHED_FIFO is specified in the scheduling policy, low priority threads will be blocked unless high priority threads are blocked. So I tried the sample code below, but it didn't work as expected.

Specifically, the expected behavior is that the printf of the low priority thread will not be executed forever because the high priority thread is infinitely looping in the while statement. Why does this sample code switch threads?

In response to @ user20098's comment, add kernel version etc.
I have installed and tested Ubuntu 16.04 (AMD64) with VirtualBox on Windows 10 (64bit).

$ uname -a
Linux vagrant 4.4.0-87-generic #110-Ubuntu SMP Tue Jul 18 12:55:35 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>


static void* prio_high(void* arg)
{
    volatile int i = 0;
    while (1)
        i++;

    return NULL;
}

static void* prio_low(void* arg)
{
    unsigned int i = 0;
    while (1)
    {
        printf("i = %d\n", i++);
    }
    return NULL;
}

int main(int argc, char *argv[])
{
    struct sched_param param1;
    struct sched_param param2;
    pthread_attr_t attr1;
    pthread_attr_t attr2;
    pthread_t th1;
    pthread_t th2;
    int ret;

    ret = pthread_attr_init(&attr1);
    assert(ret == 0);
    ret = pthread_attr_init(&attr2);
    assert(ret == 0);

    ret = pthread_attr_setschedpolicy(&attr1, SCHED_FIFO);
    assert(ret == 0);
    ret = pthread_attr_setschedpolicy(&attr2, SCHED_FIFO);
    assert(ret == 0);

    param1.sched_priority = 9;
    ret = pthread_attr_setschedparam(&attr1, &param1);
    assert(ret == 0);
    param2.sched_priority = 10;
    ret = pthread_attr_setschedparam(&attr2, &param2);
    assert(ret == 0);

    ret = pthread_create(&th1, &attr1, prio_low, NULL);
    assert(ret == 0);
    ret = pthread_create(&th2, &attr2, prio_high, NULL);
    assert(ret == 0);

    while (1)
        sleep(1);

    return 0;
}

Answer: Answer:

The sample code given in the question requires pthread_attr_setinheritsched() . (Same answer as @masm)
Without it, the child thread will take over the schedule policy of the parent thread.

/* 記述例 */
pthread_attr_setinheritsched(&attr1, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setinheritsched(&attr2, PTHREAD_EXPLICIT_SCHED);

Also, the Linux pthread implementation requires root privileges to specify SHCED_FIFO, so
You need to run the program as the root user.

However, even in this situation, if the CPU configuration of the VirtualBox virtual machine is a multiCPU environment,
Both threads in the sample code will work because the CPU will be allocated to the lower priority threads as well.

# This applies not only to virtual machines, but also to physical machines.

If you are running in a multi-CPU configuration environment, you can run the sample program with the number of CPUs set to "1" or the number of CPUs used in the taskset command limited to "1", and it will work as expected. I expect it to be ( printf() will not be printed).


Whether or not the schedule policy of the sample program is FIFO is determined.

/proc/<PID>/task/<TID>/sched

You can see it by checking the pseudo file. ( <TID> is the Linux thread ID)
(If the value of the policy line is "1", it should be a FIFO. (* The comment description ( priority ) is incorrect and the policy is correct.)

Scroll to Top