0

我正在尝试研究 Linux 中某些实时调度策略的行为。出于这个原因,我创建了 3 个周期性线程,每个线程都有一个虚拟工作负载。它们都具有相同的执行时间~5ms,它们的周期分别为 10ms、20ms 和 30ms。它们的优先级也分别是 95、50 和 25。

我试图了解 SCHED_RR 政策的工作原理,但我得到了一个奇怪的行为:

  1. 较低优先级的线程(线程#3)在其时间片的 20% 时被抢占。

  2. 更高优先级(线程#1)线程开始运行。

  3. 线程#1 结束。

  4. 线程 #1 继续运行另外 80% 的时间片,然后恢复线程 #3 的执行(有效地“吃掉”线程 #3 的剩余时间段)。

目前RR时隙定义为1ms。我正在使用 kernelshark 来可视化任务执行,所以我可以相当准确地知道哪里出了问题。

垂直线之间的部分约为 0.335 ms,而

使线程周期性的代码:

clock_gettime(CLOCK_REALTIME, &results[tid].thread_start_time); 
    
next = results[tid].thread_start_time;      // Init first next time to thread start time

    while (1)
    {
        // Define next arrival
        clock_gettime(CLOCK_REALTIME, &now);
        //trace_write("Current clock event: %ld.%ld", now.tv_sec, now.tv_nsec);
        timespec_add_us(&next, period * 1000);
        //trace_write("Next clock event: %ld.%ld", next.tv_sec, next.tv_nsec);

        // Stop. Hammertime.

        trace_write("SUSPENDING!: Thread_%d", tid);
        clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next, NULL);
        trace_write("WAKE: Thread_%d", tid);

        trace_write("RELEASE: Thread_%d", tid);

        // Perform workload
        workload(args->thread_number); // This produces a busy wait loop of ~5+/-100us milliseconds
        trace_write("FINISH: Thread_%d", tid);

    }

以及虚拟工作负载的功能:

static void workload(int tid)
{
    struct timespec ct; // Current time
    if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ct) != 0)
    {
        fprintf(stderr, "%s\n", "Error Fetching Clock Start Time.");
        return;
    }
    struct timespec workTimer = ct; // Workload timer - default 5ms
    struct timespec slotTimer = ct; // RR Slot timer

    unsigned int counter = 1;

    while (1)
    {
        long micro_ct = getMicroTime(&ct);
        long micro_work = getMicroTime(&workTimer);
        long micro_slot = getMicroTime(&slotTimer);
        
        if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ct) != 0)
        {
            fprintf(stderr, "%s\n", "Error Fetching Clock Start Time.");
            return;
        }

        // Check the total workload time
        if (micro_ct - micro_work >= DEFAULT_BUSY_WAIT_TIME)
            break;

        // Check the RR timeslot. Sa
        if (inputpolicy == SCHED_RR && ((micro_ct - micro_slot) >= DEFAULT_RR_LOOP_TIME))
        {
            trace_write("RTS_Thread_%d RR Slot: %d", tid, counter++);
            slotTimer.tv_sec = ct.tv_sec;
            slotTimer.tv_nsec = ct.tv_nsec;
        }
    }
}
4

0 回答 0