meso: Implement LightSession functions

This commit is contained in:
TuxSH 2018-11-12 12:30:58 +01:00 committed by Michael Scire
parent be3550d382
commit acf32f841c
8 changed files with 177 additions and 18 deletions

View file

@ -11,12 +11,16 @@ namespace mesosphere
class KLightSession;
class KClientPort;
struct LightSessionRequest;
class KLightClientSession final : public KAutoObject, public IClient<KLightSession, KLightClientSession, KLightServerSession> {
public:
MESOSPHERE_AUTO_OBJECT_TRAITS(AutoObject, LightClientSession);
virtual ~KLightClientSession();
Result SendSyncRequest(LightSessionRequest *request);
private:
friend class KLightSession;

View file

@ -2,7 +2,7 @@
#include <mesosphere/core/util.hpp>
#include <mesosphere/core/Result.hpp>
#include <mesosphere/core/KSynchronizationObject.hpp>
#include <mesosphere/core/KAutoObject.hpp>
#include <mesosphere/interfaces/IServer.hpp>
#include <mesosphere/threading/KThread.hpp>
@ -15,17 +15,19 @@ class KLightClientSession;
class KLightSession;
class KClientPort;
struct LightSessionRequest;
struct LightServerSessionListTag;
using LightServerSessionListBaseHook = boost::intrusive::list_base_hook<boost::intrusive::tag<LightServerSessionListTag> >;
class KLightServerSession final :
public KSynchronizationObject,
public KAutoObject,
public IServer<KLightSession, KLightClientSession, KLightServerSession>,
public LightServerSessionListBaseHook {
public:
MESOSPHERE_AUTO_OBJECT_TRAITS(SynchronizationObject, LightServerSession);
MESOSPHERE_AUTO_OBJECT_TRAITS(AutoObject, LightServerSession);
using List = typename boost::intrusive::make_list<
KLightServerSession,
@ -35,8 +37,10 @@ class KLightServerSession final :
virtual ~KLightServerSession();
virtual bool IsSignaled() const override;
/// Needs to be called from critical section
Result HandleSyncRequest(KThread &sender);
Result ReplyAndReceive(LightSessionRequest *request);
private:
friend class KLightSession;

View file

@ -11,6 +11,11 @@
namespace mesosphere
{
struct LightSessionRequest {
s32 cmdId;
u32 data[6];
};
class KLightSession final :
public KAutoObject,
public ISetAllocated<KLightSession>,

View file

@ -13,6 +13,8 @@
namespace mesosphere
{
struct LightSessionRequest;
struct KThreadContext;
struct ThreadWaitListTag;
@ -236,8 +238,12 @@ class KThread final :
bool WaitForKernelSync(WaitList &waitList);
/// Takes effect when critical section is left
void ResumeFromKernelSync();
/// Takes effect when critical section is left
void ResumeFromKernelSync(Result res);
/// Takes effect when critical section is left -- all threads in waitlist
static void ResumeAllFromKernelSync(WaitList &waitList);
/// Takes effect when critical section is left -- all threads in waitlist
static void ResumeAllFromKernelSync(WaitList &waitList, Result res);
/// Takes effect immediately
void CancelKernelSync();
/// Takes effect immediately
@ -250,10 +256,23 @@ class KThread final :
void SetWaitingSync(bool isWaitingSync) { this->isWaitingSync = isWaitingSync; }
constexpr bool IsSyncCancelled() const { return isSyncCancelled; }
void SetSyncCancelled(bool isSyncCancelled) { this->isSyncCancelled = isSyncCancelled; }
void ClearSync()
{
signaledSyncObject = nullptr;
syncResult = ResultSuccess();
}
constexpr Result GetSyncResult() const { return syncResult; }
/// Takes effect when critical section is left
void HandleSyncObjectSignaled(KSynchronizationObject *syncObj);
LightSessionRequest *GetCurrentLightSessionRequest() const { return currentLightSessionRequest; }
void SetCurrentLightSessionRequest(LightSessionRequest *currentLightSessionRequest)
{
this->currentLightSessionRequest = currentLightSessionRequest;
}
template<typename Clock, typename Duration>
Result WaitSynchronization(int &outId, KSynchronizationObject **syncObjs, int numSyncObjs, const std::chrono::time_point<Clock, Duration> &timeoutTime)
{
@ -305,6 +324,7 @@ private:
ulong affinityMask = 0;
bool isSyncCancelled = false;
bool isWaitingSync = false;
LightSessionRequest *currentLightSessionRequest = nullptr; // located in kernel thread stacks
uiptr wantedMutex = 0;
KThread *wantedMutexOwner = nullptr;
MutexWaitList mutexWaitList{};

View file

@ -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

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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;