meso: Implement LightSession functions
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#include <mesosphere/processes/KLightServerSession.hpp>
|
||||
#include <mesosphere/processes/KLightSession.hpp>
|
||||
#include <mesosphere/threading/KScopedCriticalSection.hpp>
|
||||
#include <mesosphere/core/KCoreContext.hpp>
|
||||
|
||||
namespace mesosphere
|
||||
{
|
||||
@@ -10,11 +10,6 @@ KLightServerSession::~KLightServerSession()
|
||||
Terminate(true);
|
||||
}
|
||||
|
||||
bool KLightServerSession::IsSignaled() const
|
||||
{
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
void KLightServerSession::Terminate(bool fromServer)
|
||||
{
|
||||
SharedPtr<KThread> curSender{std::move(currentSender)};
|
||||
@@ -26,19 +21,121 @@ void KLightServerSession::Terminate(bool fromServer)
|
||||
parent->isClientAlive = false;
|
||||
}
|
||||
if (curSender != nullptr) {
|
||||
kassert(curSender->GetSchedulingStatus() == KThread::SchedulingStatus::Paused && curSender->IsInKernelSync());
|
||||
curSender->CancelKernelSync(ResultKernelConnectionClosed()); //TODO check
|
||||
if (!curSender->IsDying()) {
|
||||
curSender->ResumeFromKernelSync(ResultKernelConnectionClosed());
|
||||
}
|
||||
currentSender = nullptr;
|
||||
currentReceiver = nullptr;
|
||||
}
|
||||
|
||||
for (auto &&sender : senderThreads) {
|
||||
kassert(sender.GetSchedulingStatus() == KThread::SchedulingStatus::Paused && sender.IsInKernelSync());
|
||||
sender.CancelKernelSync(ResultKernelConnectionClosed()); //TODO check
|
||||
if (!sender.IsDying()) {
|
||||
sender.ResumeFromKernelSync(ResultKernelConnectionClosed()); //TODO check
|
||||
}
|
||||
}
|
||||
|
||||
KThread::ResumeAllFromKernelSync(receiverThreads);
|
||||
}
|
||||
}
|
||||
|
||||
Result KLightServerSession::HandleSyncRequest(KThread &sender)
|
||||
{
|
||||
if (!parent->isClientAlive || !parent->isServerAlive) {
|
||||
return ResultKernelConnectionClosed();
|
||||
}
|
||||
|
||||
if (!sender.WaitForKernelSync(senderThreads)) {
|
||||
return ResultKernelThreadTerminating();
|
||||
}
|
||||
|
||||
if (currentSender != nullptr || receiverThreads.empty()) {
|
||||
// Nothing more to do if a request is being handled or if there's no receiver yet.
|
||||
return ResultSuccess();
|
||||
} else {
|
||||
// Otherwise, wake once receiver.
|
||||
receiverThreads.front().ResumeFromKernelSync();
|
||||
return ResultSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
Result KLightServerSession::ReplyAndReceive(LightSessionRequest *request)
|
||||
{
|
||||
KThread *curThread = KCoreContext::GetCurrentInstance().GetCurrentThread();
|
||||
curThread->SetCurrentLightSessionRequest(request);
|
||||
|
||||
if (request->cmdId < 0) {
|
||||
// Reply
|
||||
SharedPtr<KThread> curSender{};
|
||||
{
|
||||
KScopedCriticalSection critsec{};
|
||||
if (!parent->isClientAlive || !parent->isServerAlive) {
|
||||
return ResultKernelConnectionClosed();
|
||||
}
|
||||
if (currentSender == nullptr || currentReceiver != curThread) {
|
||||
return ResultKernelInvalidState();
|
||||
}
|
||||
|
||||
curSender = std::move(currentSender);
|
||||
if (!curSender->IsDying()) {
|
||||
*curSender->GetCurrentLightSessionRequest() = *curThread->GetCurrentLightSessionRequest();
|
||||
curSender->ResumeFromKernelSync();
|
||||
}
|
||||
currentSender = nullptr;
|
||||
currentReceiver = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Receive
|
||||
KCriticalSection &critsec = KScheduler::GetCriticalSection();
|
||||
std::scoped_lock criticalSection{critsec};
|
||||
bool waitedForSync = false;
|
||||
|
||||
// If there's already one receiver, return an error
|
||||
if (!receiverThreads.empty()) {
|
||||
return ResultKernelInvalidState();
|
||||
}
|
||||
|
||||
while (currentReceiver == nullptr) {
|
||||
if (waitedForSync) {
|
||||
curThread->SetWaitingSync(false);
|
||||
}
|
||||
|
||||
if (!parent->isClientAlive || !parent->isServerAlive) {
|
||||
return ResultKernelConnectionClosed();
|
||||
}
|
||||
|
||||
// Try to see if we can do sync immediately, otherwise wait until later...
|
||||
if (currentSender == nullptr && !senderThreads.empty()) {
|
||||
// Do the sync.
|
||||
currentSender = &senderThreads.front();
|
||||
currentReceiver = curThread;
|
||||
*curThread->GetCurrentLightSessionRequest() = *currentSender->GetCurrentLightSessionRequest();
|
||||
return ResultSuccess();
|
||||
} else {
|
||||
// We didn't get to sync, we need to wait.
|
||||
if (!curThread->WaitForKernelSync(receiverThreads)) {
|
||||
return ResultKernelThreadTerminating();
|
||||
}
|
||||
|
||||
if (curThread->IsSyncCancelled()) {
|
||||
curThread->ResumeFromKernelSync();
|
||||
curThread->SetSyncCancelled(false);
|
||||
return ResultKernelCancelled();
|
||||
}
|
||||
|
||||
// Wait NOW.
|
||||
critsec.unlock();
|
||||
critsec.lock();
|
||||
waitedForSync = true;
|
||||
if (receiverThreads.empty()) {
|
||||
return ResultKernelInvalidState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ResultKernelInvalidState();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user