iop: Support wating on message boxes

This commit is contained in:
Ziemas 2024-05-02 06:20:37 +02:00
parent 38fe4161d0
commit 3c73063940
4 changed files with 101 additions and 49 deletions

View file

@ -196,9 +196,7 @@ s32 SendMbx(s32 mbxid, void* sendmsg) {
}
s32 ReceiveMbx(MsgPacket** recvmsg, int mbxid) {
ASSERT(false);
// TODO
return 0;
return iop->kernel.ReceiveMbx((void**)recvmsg, mbxid);
}
s32 PollMbx(MsgPacket** recvmsg, int mbxid) {

View file

@ -30,6 +30,12 @@
#define SA_THFIFO 0
#define SA_THPRI 1
// Message box attributes
#define MBA_THFIFO 0x000
#define MBA_THPRI 0x001
#define MBA_MSFIFO 0x000
#define MBA_MSPRI 0x004
class IOP;
namespace iop {

View file

@ -103,6 +103,12 @@ void IOP_Kernel::iWakeupThread(s32 id) {
wakeup_queue.push(id);
}
s32 IOP_Kernel::CreateSema(s32 attr, s32 option, s32 init_count, s32 max_count) {
s32 id = semas.size();
semas.emplace_back((Semaphore::attribute)attr, option, init_count, max_count);
return id;
}
s32 IOP_Kernel::WaitSema(s32 id) {
auto& sema = semas.at(id);
if (sema.count > 0) {
@ -159,6 +165,81 @@ s32 IOP_Kernel::PollSema(s32 id) {
return KE_SEMA_ZERO;
}
/*!
* Create a message box
*/
s32 IOP_Kernel::CreateMbx() {
s32 id = mbxs.size();
mbxs.emplace_back();
return id;
}
s32 IOP_Kernel::ReceiveMbx(void** msg, s32 mbx) {
ASSERT(mbx < (s32)mbxs.size());
s32 gotSomething = mbxs[mbx].messages.empty() ? 0 : 1;
if (!gotSomething) {
/* Was empty, wait until there's messages */
mbxs[mbx].wait_list.push_back(_currentThread);
_currentThread->state = IopThread::State::Wait;
_currentThread->waitType = IopThread::Wait::MsgBox;
leaveThread();
}
ASSERT(mbxs[mbx].messages.empty() == false);
void* thing = mbxs[mbx].messages.front();
if (msg) {
*msg = thing;
}
mbxs[mbx].messages.pop();
return KE_OK;
}
/*!
* Set msg to thing if its there and pop it.
* Returns if it got something.
*/
s32 IOP_Kernel::PollMbx(void** msg, s32 mbx) {
ASSERT(mbx < (s32)mbxs.size());
s32 gotSomething = mbxs[mbx].messages.empty() ? 0 : 1;
if (gotSomething) {
void* thing = mbxs[mbx].messages.front();
if (msg) {
*msg = thing;
}
mbxs[mbx].messages.pop();
}
return gotSomething ? KE_OK : KE_MBOX_NOMSG;
}
s32 IOP_Kernel::PeekMbx(s32 mbx) {
return !mbxs[mbx].messages.empty();
}
/*!
* Push something into a mbx
*/
s32 IOP_Kernel::SendMbx(s32 mbx, void* value) {
ASSERT(mbx < (s32)mbxs.size());
mbxs[mbx].messages.push(value);
IopThread* to_run = nullptr;
if (!mbxs[mbx].wait_list.empty()) {
to_run = mbxs[mbx].wait_list.front();
mbxs[mbx].wait_list.pop_front();
to_run->waitType = IopThread::Wait::None;
to_run->state = IopThread::State::Ready;
}
return KE_OK;
}
/*!
* Return to kernel from a thread, not to be called from the kernel thread.
*/

View file

@ -57,6 +57,7 @@ struct IopThread {
None,
Semaphore,
Delay,
MsgBox,
};
IopThread(std::string n, void (*f)(), s32 ID, u32 priority)
@ -91,6 +92,11 @@ struct Semaphore {
std::list<IopThread*> wait_list;
};
struct MsgBox {
std::queue<void*> messages;
std::list<IopThread*> wait_list;
};
class IOP_Kernel {
public:
IOP_Kernel() {
@ -122,52 +128,13 @@ class IOP_Kernel {
return _currentThread->thID;
}
/*!
* Create a message box
*/
s32 CreateMbx() {
s32 id = mbxs.size();
mbxs.emplace_back();
return id;
}
/*!
* Set msg to thing if its there and pop it.
* Returns if it got something.
*/
s32 PollMbx(void** msg, s32 mbx) {
ASSERT(mbx < (s32)mbxs.size());
s32 gotSomething = mbxs[mbx].empty() ? 0 : 1;
if (gotSomething) {
void* thing = mbxs[mbx].front();
if (msg) {
*msg = thing;
}
mbxs[mbx].pop();
}
return gotSomething ? KE_OK : KE_MBOX_NOMSG;
}
s32 PeekMbx(s32 mbx) { return !mbxs[mbx].empty(); }
/*!
* Push something into a mbx
*/
s32 SendMbx(s32 mbx, void* value) {
ASSERT(mbx < (s32)mbxs.size());
mbxs[mbx].push(value);
return 0;
}
s32 CreateSema(s32 attr, s32 option, s32 init_count, s32 max_count) {
s32 id = semas.size();
semas.emplace_back((Semaphore::attribute)attr, option, init_count, max_count);
return id;
}
s32 CreateMbx();
s32 ReceiveMbx(void** msg, s32 mbx);
s32 PollMbx(void** msg, s32 mbx);
s32 PeekMbx(s32 mbx);
s32 SendMbx(s32 mbx, void* value);
s32 CreateSema(s32 attr, s32 option, s32 init_count, s32 max_count);
s32 WaitSema(s32 id);
s32 SignalSema(s32 id);
s32 PollSema(s32 id);
@ -205,7 +172,7 @@ class IOP_Kernel {
s32 _nextThID = 0;
IopThread* _currentThread = nullptr;
std::vector<IopThread> threads;
std::vector<std::queue<void*>> mbxs;
std::vector<MsgBox> mbxs;
std::vector<SifRecord> sif_records;
std::vector<Semaphore> semas;
std::queue<int> wakeup_queue;