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

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: 
1.1.1.4 ! root       53:        try {
        !            54:                thread.reset(new std::thread(func));
        !            55:        } catch (...) { }
1.1       root       56:        if ((bool)thread == false) {
1.1.1.4 ! root       57:                warnx("Failed to initialize thread(%s) at %s", threadname, __method__);
1.1       root       58:                return false;
                     59:        }
                     60:        return true;
                     61: }
                     62: 
                     63: // スレッドに終了を要求し、その終了を待つ。
                     64: // スレッド外から呼ぶこと。
                     65: void
                     66: ThreadDevice::TerminateThread()
                     67: {
                     68:        if ((bool)thread) {
                     69:                Terminate();
                     70: 
                     71:                if (thread->joinable()) {
                     72:                        thread->join();
                     73:                }
                     74: 
                     75:                thread.reset();
                     76:        }
                     77: }
1.1.1.3   root       78: 
                     79: // このスレッドアフィニティを設定する。
                     80: void
                     81: ThreadDevice::SetThreadAffinityHint(AffinityClass hint)
                     82: {
                     83: #if defined(HAVE_PTHREAD_SETAFFINITY_NP) && defined(HAVE_MICPUSET)
                     84:        auto aff = gMainApp.cpu_affinity;
                     85:        if (aff == MainApp::CPUAffinity::None) {
                     86:                return;
                     87:        }
                     88: 
                     89:        // hint, aff, cpu_list から cset を作成する。
                     90:        //
                     91:        // aff  hint  list
                     92:        // ----- ---- ----
                     93:        // Low  Heavy 0         -
                     94:        // Low  Heavy 1         -
                     95:        // High Light 0         -
                     96:        // High Light 1         -
                     97:        // ↑このケースは CPU を固定しないので cset の収集自体不要。
                     98:        //
                     99:        // Low  Light 0         -
                    100:        // Low  Light 1         set
                    101:        // High Heavy 0         -
                    102:        // High Heavy 1         set
                    103:        // ↑このケースは list[] が true なところを固定。
                    104:        //
                    105:        // Perf Light 0         set
                    106:        // Perf Light 1         -
                    107:        // Perf Heavy 0         -
                    108:        // Perf Heavy 1         set
                    109:        // ↑このケースは (bool)hint と list[] が一致したところを固定。
                    110: 
                    111:        // このスレッドは CPU を固定しない。
                    112:        if ((hint == AffinityClass::Heavy && aff == MainApp::CPUAffinity::Low ) ||
                    113:                (hint == AffinityClass::Light && aff == MainApp::CPUAffinity::High))
                    114:        {
                    115:                return;
                    116:        }
                    117: 
                    118:        const std::vector<bool>& cpu_list = gMainApp.cpu_list;
                    119:        MICPUSet cset;
                    120:        for (int i = 0, end = cpu_list.size(); i < end; i++) {
                    121:                if (aff == MainApp::CPUAffinity::Perf) {
                    122:                        // Light,Heavy と list が一致していたらセット。
                    123:                        bool hintb = (hint == AffinityClass::Heavy);
                    124:                        if (hintb == cpu_list[i]) {
                    125:                                cset.Set(i);
                    126:                        }
                    127:                } else {
                    128:                        // Low,High と Light,Heavy が一致しているので立ってるほうをセット。
                    129:                        if (cpu_list[i]) {
                    130:                                cset.Set(i);
                    131:                        }
                    132:                }
                    133:        }
                    134: 
                    135:        int r = PTHREAD_SETAFFINITY(pthread_self(), cset);
                    136: 
                    137:        if (gMainApp.hostcpu->loglevel >= 1) {
                    138:                std::string csetstr;
                    139:                for (int i = 0, end = cpu_list.size(); i < end; i++) {
                    140:                        csetstr += '0' + (uint)cset.Get(i);
                    141:                }
                    142:                gMainApp.hostcpu->putmsgn("SetAffinity:%-12s(%s) %s%s%s",
                    143:                        PTHREAD_GETNAME().c_str(),
                    144:                        (hint == AffinityClass::Light ? "Light" : "Heavy"),
                    145:                        csetstr.c_str(),
                    146:                        (r == 0 ? "" : " = "),
                    147:                        (r == 0 ? "" : strerror(r)));
                    148:        }
                    149: 
                    150:        // エラーなら errno ではなく戻り値にエラー番号が返ってくる。
                    151:        // NetBSD では sysctl で許可しないと一般ユーザはこの機能を使えないため
                    152:        // EPERM で失敗したら以降はもう何もしない。
                    153:        if (r == EPERM) {
                    154:                gMainApp.cpu_affinity = MainApp::CPUAffinity::None;
                    155:        }
                    156: #else
                    157:        // なければ無視する。
                    158: #endif
                    159: }

unix.superglobalmegacorp.com

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