summaryrefslogtreecommitdiff
path: root/src/KingSystem/ActorSystem/actBaseProcJobQue.cpp
blob: e4992638bf81248a49cad6092c8a6e865ec43dea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "KingSystem/ActorSystem/actBaseProcJobQue.h"
#include <mc/seadWorkerMgr.h>
#include "KingSystem/ActorSystem/actBaseProc.h"

namespace ksys::act {

BaseProcJobQue::BaseProcJobQue() : mPool() {}

BaseProcJobQue::~BaseProcJobQue() {
    mJobQueue.clear();
}

void BaseProcJobQue::init(sead::Heap* heap) {
    mJobQueue.initialize(mPool.size(), heap);
    mJobQueue.clear();
    for (u32 i = 0; i < sead::CoreInfo::getNumCores(); ++i)
        mJobQueue.setGranularity(i, 1);
}

bool BaseProcJobQue::pushJobQueue(sead::WorkerMgr* worker_mgr, BaseProcJobLists* lists,
                                  int priority, JobType type) {
    mJobQueue.clear();
    const bool ok = pushJobs(&mJobQueue, lists, priority, true, type);
    if (ok) {
        sead::CoreIdMask cores{sead::CoreId::cMain, sead::CoreId::cSub1, sead::CoreId::cSub2};
        worker_mgr->pushJobQueue("BaseProcJobQue::pushJobQueue", &mJobQueue, cores,
                                 sead::SyncType::cNoSync, sead::JobQueuePushType::cForward);
    }
    return ok;
}

bool BaseProcJobQue::pushJobs(sead::FixedSizeJQ* queue, BaseProcJobLists* lists, int priority,
                              bool should_reset_job_idx, JobType type) {
    if (should_reset_job_idx)
        mFreeJobIdx = 0;

    const auto& list = lists->getList(priority);
    const int num_jobs = list.size();
    int num_remaining_jobs = num_jobs;
    if (num_jobs == 0)
        return false;

    const int capacity = int(mPool.size() / 2);

    const int num_free = capacity - mFreeJobIdx;
    if (num_free <= 0)
        return false;

    auto* link = static_cast<BaseProcJobLink*>(list.front());

    if (num_remaining_jobs > num_free) {
        if (num_remaining_jobs <= 0)
            return true;

        int rounds = num_remaining_jobs / num_free + 1;
        do {
            auto* const batch_head = link;

            for (int i = 1; link && i <= rounds; ++i)
                link = static_cast<BaseProcJobLink*>(lists->getNextJob(link));

            mPool(mFreeJobIdx).set(batch_head, rounds);
            queue->enque(&mPool(mFreeJobIdx));
            num_remaining_jobs -= rounds;
            rounds = std::min(rounds, num_remaining_jobs);
            ++mFreeJobIdx;
        } while (num_remaining_jobs > 0 && num_remaining_jobs > capacity - mFreeJobIdx);
    }

    for (int i = 1; link && i <= num_remaining_jobs; ++i) {
        link->getProc()->onJobPush(type);
        if (!link->getProc()->shouldSkipJobPush(type)) {
            mPool(mFreeJobIdx).set(link, 1);
            queue->enque(&mPool(mFreeJobIdx));
            ++mFreeJobIdx;
        }
        link = static_cast<BaseProcJobLink*>(lists->getNextJob(link));
    }

    return true;
}

// NON_MATCHING: sxtw + madd -> smaddl
bool BaseProcJobQue::pushExtraJobs(sead::FixedSizeJQ* queue, BaseProcJobLists* lists, int priority,
                                   JobType type) {
    const auto& list = lists->getList(priority);
    if (list.size() == 0)
        return false;

    for (auto* link = static_cast<BaseProcJobLink*>(list.front()); link;
         link = static_cast<BaseProcJobLink*>(lists->getNextJob(link))) {
        const auto idx = mNumExtraJobs.increment();
        if (!isIndexValid(idx))
            return false;

        link->getProc()->onJobPush(type);

        BaseProcJob& job = mPool[idx];
        if (!link->getProc()->shouldSkipJobPush(type)) {
            job.set(link, 1);
            if (!queue->enque(&job))
                return false;
        }
    }

    return true;
}

bool BaseProcJobQue::pushExtraJobs(sead::FixedSizeJQ* queue,
                                   const agl::utl::AtomicPtrArray<BaseProcJobLink>& links) {
    if (links.size() <= 0)
        return false;

    for (auto it = links.begin(), end = links.end(); it != end; ++it) {
        const auto idx = mNumExtraJobs.increment();
        if (!isIndexValid(idx))
            return false;

        mPool[idx].mJobLink = &*it;
        mPool[idx].mRequiredCalcRounds = 1;
        if (!queue->enque(&mPool[idx]))
            return false;
    }

    return true;
}

}  // namespace ksys::act