0%

linux-kernel-scheduling-policies

Linux Scheduling 有三种调度策略

  • SCHED_FIFO,实时调度策略,先到先服务。一旦占用cpu则一直运行。一直运行直到有更高优先级任务到达或自己放弃
  • SCHED_RR,实时调度策略,时间片轮转。当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。放在队列尾保证了所有具有相同优先级的RR任务的调度公平
  • SCHED_OTHER,分时调度策略,不支持优先级使用

SCHED_OTHER

分时调度策略,不支持有限使用,Linux默认采用这种调度策略

SCHED_RR

实时调度策略,支持优先级。

Function

查询并设置调度策略

pthread 库,文件为 <pthread.h>

#include <pthread.h>
#include <sched.h>

static int get_thread_policy(pthread_attr_t *attr)
{
    int policy;
    int rs = pthread_attr_getschedpolicy(attr, &policy);
    switch (policy)
    {
        case SCHED_FIFO:
            printf("policy = SCHED_FIFO\n");
            break;
        case SCHED_RR:
            printf("policy = SCHED_RR\n");
            break;
        case SCHED_OTHER:
            printf("policy = SCHED_OTHER\n");
            break;
        default:
            printf("policy = SCHED_UNKNOW\n");
            break;
    }
    return policy;
}

main(void)
{
    pthread_attr_t attr;
    int rs;
    rs = pthread_attr_init(&attr);
    int policy = get_thread_policy(&attr);
    pthread_attr_setschedpolicy(&attr, SCHED_RR);
    policy = get_thread_policy(&attr);
    pthread_attr_destroy(&attr);
}

设置优先级

pthread_attr_t attr;
struct sched_param param;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
param.sched_priority = 10;
pthread_attr_setschedparam(&attr, &param);
pthread_create(xxx, &attr, xxx, xxx);
pthread_attr_destory(&attr);

Example

#ifdef LINUX_RR_SUPPORT
    return _ThreadCreate(thread_name, thread_id, entry_func, arg, stack_size, priority, SCHED_RR, PTHREAD_CREATE_JOINABLE);
#else
    return _ThreadCreate(thread_name, thread_id, entry_func, arg, stack_size, priority, SCHED_OTHER,PTHREAD_CREATE_JOINABLE);
#endif

static int32_t _ThreadCreate(const char *thread_name, handle_t *thread_id,
         void(*entry_func)(void *), void *arg,
         uint32_t stack_size,
         uint32_t priority,
         uint32_t sched_policy,
         uint32_t detach_state)
{
    int                  return_code = 0;
    pthread_attr_t       custom_attr ;
    struct sched_param   priority_holder ;
    int32_t ret = 0;
    uint32_t             local_stack_size;
    ThreadRecord* thread_rec;

#ifdef ASSERT_DEBUG
    assert(thread_id);
    assert(entry_func);
    assert(priority <= MAX_PRIORITY);
#endif

    thread_exit();

    /* Check for NULL pointers */
    if( entry_func == NULL || thread_id == NULL)
        return INVALID_POINTER;

    /* Check for bad priority */
    if (priority > MAX_PRIORITY)
        return INVALID_PRIORITY;

    thread_rec = THREAD_NEW();
    if (thread_rec == NULL)
        return ERR_NO_FREE_IDS;

    /* Set stack size */
    if (pthread_attr_init(&custom_attr)) {
        printf("pthread_attr_init error in ThreadCreate, Pthread ID = %u\n", thread_rec->handle);
        goto err;
    }

    local_stack_size = stack_size <= PTHREAD_STACK_MIN ? PTHREAD_STACK_MIN : stack_size;
    if (pthread_attr_setstacksize(&custom_attr, (size_t)local_stack_size)) {
        printf("pthread_attr_setstacksize error in ThreadCreate, Pthread ID = %u\n", thread_rec->handle);
        goto err;
    }

    if (sched_policy == SCHED_RR) {
        /* Set priority */
        if (UpUserPermissions() != true) {
            printf("upuserpermissions err in ThreadCreate, Pthread ID = %u\n", thread_rec->handle);
            goto err;
        }
        pthread_attr_setschedpolicy(&custom_attr, SCHED_RR);
        ret = pthread_attr_setinheritsched(&custom_attr, PTHREAD_EXPLICIT_SCHED);
        if(ret != 0)
        {
            printf("pthread_attr_setinheritsched error in ThreadCreate, Pthread ID = %u\n", thread_rec->handle);
            DownUserPermissions();
            goto err;
        }
        priority_holder.sched_priority = sched_get_priority_max(SCHED_RR) - priority;
        ret = pthread_attr_setschedparam(&custom_attr, &priority_holder);
        if(ret != 0) {
            printf("pthread_attr_setschedparam error in ThreadCreate, Pthread ID = %u\n", thread_rec->handle);
            DownUserPermissions();
            goto err;
        }
        DownUserPermissions();
    }

    if (detach_state == PTHREAD_CREATE_DETACHED) {
        ret = pthread_attr_setdetachstate(&custom_attr, PTHREAD_CREATE_DETACHED);
        if (ret != 0) {
            printf("pthread_attr_setdetachstate failed !\n");
            goto err;
        }
    }

    /* Create thread */
    thread_rec->entry_func = entry_func;
    thread_rec->arg = arg;
    thread_rec->status = JOINABLE;
    if (UpUserPermissions() != true) {
        printf("upuserpermissions err in ThreadCreate, Pthread ID = %u\n", thread_rec->handle);
        goto err;
    }

    return_code = pthread_create(&(thread_rec->id), &custom_attr, default_thread_function, thread_rec);
    if (return_code != 0) {
        printf("pthread_create error in ThreadCreate, Pthread ID = %u\n", thread_rec->handle);

        DownUserPermissions();
        goto err;
    }
    DownUserPermissions();

    //*thread_id = thread_rec->handle;
    *thread_id = thread_rec->handle;
    //id_to_handle[thread_rec->handle] = thread_rec->id;

    /* this Id no longer free */
    thread_rec->stack_size = stack_size;
    thread_rec->priority = priority;

    return_code = pthread_attr_getstack(&custom_attr, &thread_rec->stack_base, &thread_rec->stack_size);
    if (return_code != 0) {
        printf("%s: pthread_attr_getstack err: %d", __func__, return_code);
        return ERROR;
    }
    pthread_attr_destroy(&custom_attr);
    return SUCCESS;

err:
    if (thread_rec->freed == 1)
        THREAD_FREE(thread_rec);
    pthread_attr_destroy(&custom_attr);
    return ERROR;
}

Ref

  1. Linux 线程调度与优先级
  2. Linux任务调度机制