为什么pthread_barrier_wait没有考虑线程优先级?

时间:2018-05-16 12:15:51

标签: c multithreading pthreads posix pthread-barriers

我正在使用障碍来同步我的两个线程,这两个线程将分别执行 task_1 task_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身份执行程序,并确保已相应地设置任务优先级。

2 个答案:

答案 0 :(得分:0)

调度取决于OS中使用的调度算法。您正在尝试使用FIFO,只有在启用实时调度时,manpage才可用。

   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,则在内核编译期间选择调度算法,不确定是否可以在引导期间或动态更改它们。

答案 1 :(得分:0)

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

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