pthreadでスレッドのプライオリティを設定する方法

#はじめに
pthreadの関数を使用して、スレッドプライオリティを設定する方法を解説していきます。

プライオリティの設定方法は、2種類あります。

1. pthread_attr_tを利用してスレッド生成前に設定する
2. スレッド生成後に設定する

どちらも共通して、root権限で実行しないとエラーとなります。

#1. スレッド生成前に設定する方法
流れとしては、以下のとおりです。

1. pthread_attr_init()でpthread_attr_tを初期化
2. pthread_attr_setinheritsched()でattrからスケジューリング属性を取得するように指定する
3. pthread_attr_setschedpolicy()でスケジューリングポリシーを設定する
4. pthread_attr_setschedparam()でプライオリティを設定する

以下はサンプルコードです。

```cpp
#include <iostream>
#include <pthread.h>
#include <sched.h>

#define NUM_OF_THREADS 4

pthread_mutex_t mtx;

void* entry(void* arg)
{
    struct sched_param param;
    int policy{};
    int ret = pthread_getschedparam(pthread_self(), &policy, &param);
    if (ret != 0)
    {
        std::cout << "pthread_getschedparam() error[" << ret << "]\n";
    }
    
    pthread_mutex_lock(&mtx);

    std::cout << "Priority:" << param.sched_priority << " start\n";
        
    pthread_mutex_unlock(&mtx);

    // do some work

    return NULL;
}

int main()
{
    pthread_mutex_init(&mtx, NULL);

    pthread_attr_t attr;
    pthread_attr_init(&attr);

    int ret = pthread_attr_setinheritsched(&param, PTHREAD_EXPLICIT_SCHED);
    if (ret != 0)
    {
        std::cout << "pthread_attr_setinheritsched() error[" << ret << "]¥n";
    }

    ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
    if (ret != 0)
    {
        std::cout << "pthread_attr_setschedpolicy() error[" << ret << "]¥n";
    }

    pthread_t threads[NUM_OF_THREADS];

    for (int i = 0; i < NUM_OF_THREADS; i++)
    {
        param.sched_priority = i + 1;

        ret = pthread_attr_setschedparam(&attr, &param);
        if (ret != 0)
        {
            std::cout << "pthread_attr_setschedparam() error[" << ret << "]¥n";
        }
        
        ret = pthread_create(&threads[i], &attr, entry, NULL);
        if (ret != 0)
        {
            std::cout << "pthread_create() error[" << ret << "]¥n";
        }
    }

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

    pthread_attr_destroy(&attr);
    pthread_mutex_destroy(&mtx);

    return 0;
}
```

#2. スレッド生成後に設定する方法

pthread_create()でスレッドを生成したあとで、pthread_setschedparam()関数を使用してスレッドを設定します。

```cpp
#include <iostream>
#include <pthread.h>
#include <sched.h>

#define NUM_OF_THREADS 4

pthread_mutex_t mtx;

void* entry(void* arg)
{
    pthread_mutex_lock(&mtx);

    struct sched_param param;
    int policy{};
    int ret = pthread_getschedparam(pthread_self(), &policy, &param);
    if (ret != 0)
    {
        std::cout << "pthread_getschedparam() error[" << ret << "]\n";
    }

    pthread_mutex_unlock(&mtx);
    
    pthread_mutex_lock(&mtx);

    std::cout << "Priority:" << param.sched_priority << " start\n";
        
    pthread_mutex_unlock(&mtx);

    // do some work

    return NULL;
}

int main()
{
    pthread_mutex_init(&mtx, NULL);

    pthread_t threads[NUM_OF_THREADS];

    struct sched_param param;

    pthread_mutex_lock(&mtx);

    for (int i = 0; i < NUM_OF_THREADS; i++)
    {
        ret = pthread_create(&threads[i], &attr, entry, NULL);
        if (ret != 0)
        {
            std::cout << "pthread_create() error[" << ret << "]¥n";
        }
    }

    for (int i = 0; i < NUM_OF_THREADS; i++)
    {
        param.sched_priority = i + 1;

        ret = pthread_setschedparam(threads[i], SCHED_RR, &param);
        if (ret != 0)
        {
            std::cout << "pthread_setschedparam() error[" << ret << "]¥n";
        }
    }

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

    pthread_mutex_destroy(&mtx);

    return 0;
}
```

本来は、同一CPU上で異なるプライオリティのスレッドを動かしたら、それぞれのスレッドのスループットに差が発生するかという検証をする予定でした。

しかし、CPUアフィニティを設定して同一CPU上で複数スレッドを実行するコードを実行すると、アプリケーションが固まってしまうという問題に遭遇。

このあたりの情報をご存じの方がいらっしゃたら、ぜひ教えていただけると嬉しいです。