linux FIFO调度的一些实验

具体来说,就是我想知道:

  • 如果优先级一样,那么当线程A由于在等待某个锁而进入阻塞时,如果此时线程B在运行的过程中释放了这个锁,那么线程A会马上抢占B的运行吗? 答案是不会,除非B自己阻塞或运行完毕。
  • 如果A的优先级比较高,那么A会抢占B吗? 会的

测试代码:
运行命令:
sudo ./main FIFO 1 1 3 1
最后面一个1,表示只有一个cpu来运行这个测试
前面两个1 表示线程1 和 2 的优先级
线程3 没用到,这里不管。

#define _GNU_SOURCE      //for CPU_ZERO CPU_SET
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

long counter = 1000000;
long sum = 0;
int policy;
int policy;
int prio[3];
pthread_attr_t attr;
pthread_t thread1, thread2, thread3;
pthread_barrier_t barrier;
struct sched_param param[3];
sem_t mutex,mutex2;
int cpunum;

void *test_func(void *id) {
    int count = 0;
    int my_policy, my_id;
    char polstr[128];
    int i;
    my_id = *(int*) id;
    struct sched_param param;

    //获取线程绑定cpu
    cpu_set_t cpuset;
    if (pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),&cpuset) == 0){
         for (i=0; i<cpunum; i++) {
             if (CPU_ISSET(i, &cpuset)){
                 printf("%d : CPU %d\n", my_id, i);
             }
         }
    }

    if(my_id == 1){
        sem_wait(&mutex);
        printf("thread 1 get the lock\n"); 
    }
    if(my_id == 2){
        sem_wait(&mutex2);
        printf("thread 2 get the lock\n");         
    }

    // 设置所有线程从此点开始执行
    int rc = pthread_barrier_wait(&barrier);
    if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD)
    {
           printf("[%d] Could not wait on barrier\n", my_id);
           return (void*) NULL;
    }

    if (policy == SCHED_OTHER) {
        nice(prio[my_id-1]);
    }
    // 显示线程的调度策略和优先级
    pthread_getschedparam(pthread_self(), &my_policy, &param);

    if (my_policy == SCHED_FIFO) {
        strcpy(polstr, "FIFO");
    } else if (my_policy == SCHED_RR) {
        strcpy(polstr, "RR");
    } else if (my_policy == SCHED_OTHER) {
        strcpy(polstr, "OTHER");
    }
     else
        strcpy(polstr, "Unkown");

    if (my_policy != SCHED_OTHER){
       printf("thread  %d: scheduled at %s, priority %d\n",
                       my_id, polstr, param.sched_priority);
    }else{
       printf("thread  %d: scheduled at %s, nice %d\n",
                       my_id, polstr, prio[my_id-1]);
    }

    if(my_id == 2){
        sem_post(&mutex2);
        printf("thread 2 release lock\n");
       //sem_wait(&mutex);
       for(int i=0;i<100000;++i){}
       printf("thread 2 get lock and exit\n");
       //sem_post(&mutex);
    }

    if(my_id == 1){
        printf("thread 1 waiting for lock\n");
        sem_wait(&mutex2);
        for(int i=0;i<100000;++i){}
        printf("thread 1, finished caculate.\n");
        sem_post(&mutex);
        printf("thread 1, release lock\n"); 
    }

    return NULL;
}

int main(int argc, char **argv){

    int id_1 =1, id_2=2, id_3=3, sch_min, sch_max, onecpu=1;
    if (argc !=6 ){
       printf("Usage: %s <schedule-policy> <td-1-pri> <td-2-pir> <td-3-pri>\n",
                argv[0]);
       printf(" schedule-policy = FIFO | RR | OTHER\n");
       printf(" td-?-pri = integer\n");
       printf(" if policy == OTHER td-?-pri is a nice number\n");
       printf(" Otherwise: td-?-pri is between min and max of allowed prios\n");
       return 0;
    }
    if (!strcmp(argv[1], "RR")) {
        policy = SCHED_RR;
    }
    else if (!strcmp(argv[1], "FIFO")) {
        policy = SCHED_FIFO;
    }
    else
        policy = SCHED_OTHER;

    //获取当前调度策略优先级最大最小值 
    sch_max= sched_get_priority_max(policy);
    sch_min= sched_get_priority_min(policy);
    printf("Scheduling policy %s max = %d, min = %d\n\n", argv[1], sch_max, sch_min);
    fflush(stdout);

    cpunum = sysconf(_SC_NPROCESSORS_CONF);
    printf("CPU NUM =  %d\n", cpunum);

    cpu_set_t mask;
    CPU_ZERO(&mask);

    // 仅在一个cpu上运行
    if (!strcmp(argv[5], "1")) {
       CPU_SET(0, &mask);
    }
    else {
        int i;
        for (i=0;i<cpunum;i++){
            CPU_SET(i, &mask);
        }
    }

    if (sched_setaffinity (0, sizeof (mask), &mask) == -1)
    {
        printf ("warning: could not set CPU affinity, continuing.../n");
        return 1;
    }

    //初始化barrier变量使线程到达同一点开始运行
    if (pthread_barrier_init(&barrier, NULL, 3)) {
         printf("Count not create barrier\n");
         return 1;
    }

    sem_init (&mutex, 0, 1);
    sem_init (&mutex2, 0, 1);
    prio[0] = param[0].sched_priority = atoi (argv[2]);
    prio[1] = param[1].sched_priority = atoi (argv[3]);
    prio[2] = param[2].sched_priority = atoi (argv[4]);

    //设置线程属性
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    pthread_attr_setschedpolicy(&attr, policy);

    //注意这里要设置PTHREAD_EXPLICIT_SCHED ,默认为PTHREAD_INHERIT_SCHED
    //将集成创建者的调度策略
    pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED);

    //设置优先级进行开始运行
    pthread_attr_setschedparam (&attr, &param[0]);
    pthread_create(&thread1, &attr, test_func, (void*)&id_1);
    pthread_attr_setschedparam (&attr, &param[1]);
    pthread_create(&thread2, &attr, test_func, (void*)&id_2);
    pthread_attr_setschedparam (&attr, &param[2]);
    pthread_create(&thread3, &attr, test_func, (void*)&id_3);

    pthread_exit(NULL);
    return 0;
}

发表评论