meso: Implement LightSession functions
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#include <mesosphere/interrupts/KAlarm.hpp>
|
||||
#include <mesosphere/threading/KScheduler.hpp>
|
||||
#include <mesosphere/threading/KScopedCriticalSection.hpp>
|
||||
#include <mesosphere/arch/KInterruptMaskGuard.hpp>
|
||||
|
||||
namespace mesosphere
|
||||
@@ -24,8 +24,7 @@ void KAlarm::RemoveAlarmable(const IAlarmable &alarmable)
|
||||
void KAlarm::HandleAlarm()
|
||||
{
|
||||
{
|
||||
KCriticalSection &critsec = KScheduler::GetCriticalSection();
|
||||
std::scoped_lock criticalSection{critsec};
|
||||
KScopedCriticalSection critsec{};
|
||||
std::scoped_lock guard{spinlock};
|
||||
|
||||
KSystemClock::SetInterruptMasked(true); // mask timer interrupt
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mesosphere/processes/KLightClientSession.hpp>
|
||||
#include <mesosphere/processes/KLightSession.hpp>
|
||||
#include <mesosphere/threading/KScopedCriticalSection.hpp>
|
||||
#include <mesosphere/threading/KThread.hpp>
|
||||
#include <mesosphere/core/KCoreContext.hpp>
|
||||
|
||||
namespace mesosphere
|
||||
{
|
||||
@@ -10,5 +11,15 @@ KLightClientSession::~KLightClientSession()
|
||||
parent->Terminate(false);
|
||||
}
|
||||
|
||||
Result KLightClientSession::SendSyncRequest(LightSessionRequest *request)
|
||||
{
|
||||
KScopedCriticalSection critsec{};
|
||||
Result res;
|
||||
KThread *curThread = KCoreContext::GetCurrentInstance().GetCurrentThread();
|
||||
curThread->SetCurrentLightSessionRequest(request);
|
||||
curThread->ClearSync();
|
||||
res = parent->server.HandleSyncRequest(*curThread);
|
||||
return res.IsSuccess() ? curThread->GetSyncResult() : res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,6 +85,13 @@ void KThread::ResumeFromKernelSync()
|
||||
Reschedule(SchedulingStatus::Running);
|
||||
}
|
||||
|
||||
void KThread::ResumeFromKernelSync(Result res)
|
||||
{
|
||||
// Has to be called from critical section
|
||||
syncResult = res;
|
||||
ResumeFromKernelSync();
|
||||
}
|
||||
|
||||
void KThread::ResumeAllFromKernelSync(KThread::WaitList &waitList)
|
||||
{
|
||||
// Has to be called from critical section
|
||||
@@ -96,6 +103,18 @@ void KThread::ResumeAllFromKernelSync(KThread::WaitList &waitList)
|
||||
);
|
||||
}
|
||||
|
||||
void KThread::ResumeAllFromKernelSync(KThread::WaitList &waitList, Result res)
|
||||
{
|
||||
// Has to be called from critical section
|
||||
waitList.clear_and_dispose(
|
||||
[res](KThread *t) {
|
||||
t->syncResult = res;
|
||||
t->currentWaitList = nullptr;
|
||||
t->Reschedule(SchedulingStatus::Running);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
void KThread::CancelKernelSync()
|
||||
{
|
||||
KScopedCriticalSection criticalSection;
|
||||
|
||||
Reference in New Issue
Block a user