Remove SyncRequest from K::Object and create a new K::Session type

This is a first step at fixing the conceptual insanity that is our
handling of service and IPC calls. For now, interfaces still directly
derived from Session because we don't have the infrastructure to do it
properly. (That is, Processes and scheduling them.)
This commit is contained in:
Yuri Kunde Schlesner 2014-12-14 03:30:11 -02:00
parent 1ee740898a
commit e321decf98
15 changed files with 129 additions and 104 deletions

View file

@ -2,6 +2,8 @@
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <map>
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/math_util.h"
@ -10,8 +12,8 @@
#include "core/file_sys/archive_sdmc.h"
#include "core/file_sys/directory.h"
#include "core/hle/kernel/archive.h"
#include "core/hle/kernel/session.h"
#include "core/hle/result.h"
#include "core/hle/service/service.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// Kernel namespace
@ -41,19 +43,15 @@ enum class DirectoryCommand : u32 {
Close = 0x08020000,
};
class Archive : public Object {
class Archive : public Kernel::Session {
public:
std::string GetTypeName() const override { return "Archive"; }
std::string GetName() const override { return name; }
static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; }
Kernel::HandleType GetHandleType() const override { return HandleType::Archive; }
std::string GetName() const override { return "Archive: " + name; }
std::string name; ///< Name of archive (optional)
FileSys::Archive* backend; ///< Archive backend interface
ResultVal<bool> SyncRequest() override {
u32* cmd_buff = Service::GetCommandBuffer();
u32* cmd_buff = Kernel::GetCommandBuffer();
FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
switch (cmd) {
@ -102,7 +100,8 @@ public:
default:
{
LOG_ERROR(Service_FS, "Unknown command=0x%08X", cmd);
return UnimplementedFunction(ErrorModule::FS);
cmd_buff[0] = UnimplementedFunction(ErrorModule::FS).raw;
return MakeResult<bool>(false);
}
}
cmd_buff[1] = 0; // No error
@ -110,19 +109,15 @@ public:
}
};
class File : public Object {
class File : public Kernel::Session {
public:
std::string GetTypeName() const override { return "File"; }
std::string GetName() const override { return path.DebugStr(); }
static Kernel::HandleType GetStaticHandleType() { return HandleType::File; }
Kernel::HandleType GetHandleType() const override { return HandleType::File; }
std::string GetName() const override { return "Path: " + path.DebugStr(); }
FileSys::Path path; ///< Path of the file
std::unique_ptr<FileSys::File> backend; ///< File backend interface
ResultVal<bool> SyncRequest() override {
u32* cmd_buff = Service::GetCommandBuffer();
u32* cmd_buff = Kernel::GetCommandBuffer();
FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
switch (cmd) {
@ -188,19 +183,15 @@ public:
}
};
class Directory : public Object {
class Directory : public Kernel::Session {
public:
std::string GetTypeName() const override { return "Directory"; }
std::string GetName() const override { return path.DebugStr(); }
static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; }
Kernel::HandleType GetHandleType() const override { return HandleType::Directory; }
std::string GetName() const override { return "Directory: " + path.DebugStr(); }
FileSys::Path path; ///< Path of the directory
std::unique_ptr<FileSys::Directory> backend; ///< File backend interface
ResultVal<bool> SyncRequest() override {
u32* cmd_buff = Service::GetCommandBuffer();
u32* cmd_buff = Kernel::GetCommandBuffer();
DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
switch (cmd) {
@ -230,7 +221,7 @@ public:
LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
ResultCode error = UnimplementedFunction(ErrorModule::FS);
cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
return error;
return MakeResult<bool>(false);
}
cmd_buff[1] = 0; // No error
return MakeResult<bool>(false);

View file

@ -22,7 +22,7 @@ enum KernelHandle {
enum class HandleType : u32 {
Unknown = 0,
Port = 1,
Service = 2,
Session = 2,
Event = 3,
Mutex = 4,
SharedMemory = 5,
@ -30,10 +30,7 @@ enum class HandleType : u32 {
Thread = 7,
Process = 8,
AddressArbiter = 9,
File = 10,
Semaphore = 11,
Archive = 12,
Directory = 13,
Semaphore = 10,
};
enum {
@ -52,15 +49,6 @@ public:
virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
virtual Kernel::HandleType GetHandleType() const = 0;
/**
* Synchronize kernel object.
* @return True if the current thread should wait as a result of the sync
*/
virtual ResultVal<bool> SyncRequest() {
LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
return UnimplementedFunction(ErrorModule::Kernel);
}
/**
* Wait for kernel object to synchronize.
* @return True if the current thread should wait as a result of the wait

View file

@ -0,0 +1,58 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "core/hle/kernel/kernel.h"
namespace Kernel {
static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header
/**
* Returns a pointer to the command buffer in kernel memory
* @param offset Optional offset into command buffer
* @return Pointer to command buffer
*/
inline static u32* GetCommandBuffer(const int offset=0) {
return (u32*)Memory::GetPointer(Memory::KERNEL_MEMORY_VADDR + kCommandHeaderOffset + offset);
}
/**
* Kernel object representing the client endpoint of an IPC session. Sessions are the basic CTR-OS
* primitive for communication between different processes, and are used to implement service calls
* to the various system services.
*
* To make a service call, the client must write the command header and parameters to the buffer
* located at offset 0x80 of the TLS (Thread-Local Storage) area, then execute a SendSyncRequest
* SVC call with its Session handle. The kernel will read the command header, using it to marshall
* the parameters to the process at the server endpoint of the session. After the server replies to
* the request, the response is marshalled back to the caller's TLS buffer and control is
* transferred back to it.
*
* In Citra, only the client endpoint is currently implemented and only HLE calls, where the IPC
* request is answered by C++ code in the emulator, are supported. When SendSyncRequest is called
* with the session handle, this class's SyncRequest method is called, which should read the TLS
* buffer and emulate the call accordingly. Since the code can directly read the emulated memory,
* no parameter marshalling is done.
*
* In the long term, this should be turned into the full-fledged IPC mechanism implemented by
* CTR-OS so that IPC calls can be optionally handled by the real implementations of processes, as
* opposed to HLE simulations.
*/
class Session : public Object {
public:
std::string GetTypeName() const override { return "Session"; }
static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Session; }
Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Session; }
/**
* Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls
* aren't supported yet.
*/
virtual ResultVal<bool> SyncRequest() = 0;
};
}