0

我正在使用障碍来同步我的两个线程,这两个线程将分别执行task_1task_2

同步后,我希望优先级较高的任务在优先级较低的任务之前开始执行。

我惊讶地注意到,即使task_2的优先级低于task_1有时task_2 task_1之前开始执行。

#include <pthread.h>
#include <sched.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>

#define MAX_PRIORITY 99
#define MIN_PRIORITY 1

pthread_t threads[2];
pthread_barrier_t barrier;

void set_priority(int priority, int t_id){
    int policy = SCHED_FIFO;
    struct sched_param param;

    param.sched_priority = priority;

    pthread_attr_t attr;
    pthread_attr_init (&attr);

    pthread_setschedparam(pthread_self(), policy, &param);

    pthread_getschedparam(pthread_self(), &policy, &param);
}

int set_core(int core_id) {
    int num_cores = sysconf(_SC_NPROCESSORS_ONLN);
    if (core_id < 0 || core_id >= num_cores)
        return EINVAL;

    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(core_id, &cpuset);

    pthread_t current_thread = pthread_self();
    return pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset);
}
void create_task(int task_number, void *task) {
    int rc = pthread_create(&threads[task_number - 1], NULL, task, NULL);
    if(rc != 0) {
        printf("pthread_create(%d) error %d\n", task_number - 1, rc);
        pthread_exit(0) ;
    }
}

void schedule_task(int task_number, int priority) {
    set_core(2); //running tasks only in 2nd processor core
    set_priority(priority, task_number);
}

void start_task_1() {
    printf("Task 1 Started \n");
    sleep(1); //do task 1
    printf("Task 1 Endeded\n");
}

void start_task_2() {
    printf("Task 2 Started \n");
    sleep(1); //do task 2
    printf("Task 2 Endeded\n");
}

void task_1(void *thread_param) {
    schedule_task(1, MAX_PRIORITY);
    pthread_barrier_wait(&barrier);

    start_task_1();

    pthread_exit(NULL);
}

void task_2(void *thread_param) {
    schedule_task(2, MIN_PRIORITY);
    pthread_barrier_wait(&barrier);

    start_task_2();

    pthread_exit(NULL);
}

int main() {
    pthread_barrier_init(&barrier, NULL, 2);

    create_task(1, task_1);
    create_task(2, task_2);

    for (int i = 0; i < 2; i++) {
        pthread_join(threads[i], NULL);
    } 

    pthread_barrier_destroy(&barrier);
}

这是 POSIX 线程中的预期行为吗?我能做些什么来强制task_1总是在task_2之前开始?

我以 root 身份执行程序,并确保已相应设置任务优先级。

4

2 回答 2

0

调度取决于操作系统中使用的调度算法。您正在尝试使用 FIFO,根据手册页,它仅在启用实时调度时才可用。

   Various "real-time" policies are also supported, for special time-
   critical applications that need precise control over the way in which
   runnable threads are selected for execution.  For the rules governing
   when a process may use these policies, see sched(7).  The real-time
   policies that may be specified in policy are:

        SCHED_FIFO    a first-in, first-out policy; and

        SCHED_RR      a round-robin policy.

如果您使用的是 Linux,则在内核编译期间会选择调度算法,不确定是否可以在引导期间或动态更改它们。

于 2018-05-16T12:38:24.200 回答
0

您正在创建两个不同的线程,并将它们限制为单独的内核。确实,其中一个具有比另一个更高的优先级设置,但两者都是SCHED_FIFO线程,这可能使每个线程都成为其各自核心上的最高优先级任务(至少在用户级任务中)。由于每个核心都有一个独立的可运行任务队列,调度策略只会影响同一个核心上的任务之间的比较。

因此,出于所有实际目的,这两个任务实际上处于相同的有效优先级。因此,没有理由期望在屏障等待之后任务 1 会比任务 2 更早开始执行。如果你想强制执行(同时仍然让它们在不同的核心上运行),你需要使用其他一些共享变量来让任务 1 告诉任务 2 可以开始。这可能是一个信号量、互斥保护标志,或者在大多数架构上,只是一个原子更新标志整数上的繁忙循环。

于 2018-05-16T17:48:03.613 回答