Annotation of nono/vm/thread.cpp, revision 1.1.1.3

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2021 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // スレッドを持つデバイス
                      9: //
                     10: 
                     11: #include "thread.h"
1.1.1.3 ! root       12: #include "mainapp.h"
1.1       root       13: #include "mythread.h"
                     14: 
                     15: // コンストラクタ
1.1.1.3 ! root       16: ThreadDevice::ThreadDevice(uint objid_)
1.1.1.2   root       17:        : inherited(objid_)
1.1       root       18: {
                     19:        // スレッド名はデフォルトでこのオブジェクトと同じ名前にしておく。
                     20:        // 継承側コンストラクタ等で SetThreadName() で変更してもよい。
                     21:        SetThreadName(GetName().c_str());
                     22: }
                     23: 
                     24: // デストラクタ
                     25: ThreadDevice::~ThreadDevice()
                     26: {
                     27:        // ここで virtual の Terminate() は呼べないので、
                     28:        // 継承側のデストラクタで TerminateThread() をそれぞれ呼ぶこと。
                     29: }
                     30: 
                     31: // スレッド名を設定する
                     32: // (ポインタしか管理しないので実体は呼び出し側で責任を持つこと)
                     33: void
                     34: ThreadDevice::SetThreadName(const char *threadname_)
                     35: {
                     36:        assert(threadname_);
                     37:        threadname = threadname_;
                     38: }
                     39: 
                     40: // スレッド開始
                     41: bool
                     42: ThreadDevice::StartThread()
                     43: {
                     44:        auto func = [this]() {
                     45:                PTHREAD_SETNAME(threadname);
                     46:                std::lock_guard<std::mutex> lock_sub(this->thread_starter);
                     47:                this->ThreadRun();
                     48:        };
                     49: 
                     50:        // スレッド起動
                     51:        std::lock_guard<std::mutex> lock(thread_starter);
                     52: 
                     53:        thread.reset(new std::thread(func));
                     54:        if ((bool)thread == false) {
                     55:                return false;
                     56:        }
                     57:        return true;
                     58: }
                     59: 
                     60: // スレッドに終了を要求し、その終了を待つ。
                     61: // スレッド外から呼ぶこと。
                     62: void
                     63: ThreadDevice::TerminateThread()
                     64: {
                     65:        if ((bool)thread) {
                     66:                Terminate();
                     67: 
                     68:                if (thread->joinable()) {
                     69:                        thread->join();
                     70:                }
                     71: 
                     72:                thread.reset();
                     73:        }
                     74: }
1.1.1.3 ! root       75: 
        !            76: // このスレッドアフィニティを設定する。
        !            77: void
        !            78: ThreadDevice::SetThreadAffinityHint(AffinityClass hint)
        !            79: {
        !            80: #if defined(HAVE_PTHREAD_SETAFFINITY_NP) && defined(HAVE_MICPUSET)
        !            81:        auto aff = gMainApp.cpu_affinity;
        !            82:        if (aff == MainApp::CPUAffinity::None) {
        !            83:                return;
        !            84:        }
        !            85: 
        !            86:        // hint, aff, cpu_list から cset を作成する。
        !            87:        //
        !            88:        // aff  hint  list
        !            89:        // ----- ---- ----
        !            90:        // Low  Heavy 0         -
        !            91:        // Low  Heavy 1         -
        !            92:        // High Light 0         -
        !            93:        // High Light 1         -
        !            94:        // ↑このケースは CPU を固定しないので cset の収集自体不要。
        !            95:        //
        !            96:        // Low  Light 0         -
        !            97:        // Low  Light 1         set
        !            98:        // High Heavy 0         -
        !            99:        // High Heavy 1         set
        !           100:        // ↑このケースは list[] が true なところを固定。
        !           101:        //
        !           102:        // Perf Light 0         set
        !           103:        // Perf Light 1         -
        !           104:        // Perf Heavy 0         -
        !           105:        // Perf Heavy 1         set
        !           106:        // ↑このケースは (bool)hint と list[] が一致したところを固定。
        !           107: 
        !           108:        // このスレッドは CPU を固定しない。
        !           109:        if ((hint == AffinityClass::Heavy && aff == MainApp::CPUAffinity::Low ) ||
        !           110:                (hint == AffinityClass::Light && aff == MainApp::CPUAffinity::High))
        !           111:        {
        !           112:                return;
        !           113:        }
        !           114: 
        !           115:        const std::vector<bool>& cpu_list = gMainApp.cpu_list;
        !           116:        MICPUSet cset;
        !           117:        for (int i = 0, end = cpu_list.size(); i < end; i++) {
        !           118:                if (aff == MainApp::CPUAffinity::Perf) {
        !           119:                        // Light,Heavy と list が一致していたらセット。
        !           120:                        bool hintb = (hint == AffinityClass::Heavy);
        !           121:                        if (hintb == cpu_list[i]) {
        !           122:                                cset.Set(i);
        !           123:                        }
        !           124:                } else {
        !           125:                        // Low,High と Light,Heavy が一致しているので立ってるほうをセット。
        !           126:                        if (cpu_list[i]) {
        !           127:                                cset.Set(i);
        !           128:                        }
        !           129:                }
        !           130:        }
        !           131: 
        !           132:        int r = PTHREAD_SETAFFINITY(pthread_self(), cset);
        !           133: 
        !           134:        if (gMainApp.hostcpu->loglevel >= 1) {
        !           135:                std::string csetstr;
        !           136:                for (int i = 0, end = cpu_list.size(); i < end; i++) {
        !           137:                        csetstr += '0' + (uint)cset.Get(i);
        !           138:                }
        !           139:                gMainApp.hostcpu->putmsgn("SetAffinity:%-12s(%s) %s%s%s",
        !           140:                        PTHREAD_GETNAME().c_str(),
        !           141:                        (hint == AffinityClass::Light ? "Light" : "Heavy"),
        !           142:                        csetstr.c_str(),
        !           143:                        (r == 0 ? "" : " = "),
        !           144:                        (r == 0 ? "" : strerror(r)));
        !           145:        }
        !           146: 
        !           147:        // エラーなら errno ではなく戻り値にエラー番号が返ってくる。
        !           148:        // NetBSD では sysctl で許可しないと一般ユーザはこの機能を使えないため
        !           149:        // EPERM で失敗したら以降はもう何もしない。
        !           150:        if (r == EPERM) {
        !           151:                gMainApp.cpu_affinity = MainApp::CPUAffinity::None;
        !           152:        }
        !           153: #else
        !           154:        // なければ無視する。
        !           155: #endif
        !           156: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.