mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
iop: Support wating on message boxes
This commit is contained in:
parent
38fe4161d0
commit
3c73063940
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue