clang-format on most of kernel/
This commit is contained in:
@@ -9,17 +9,15 @@
|
||||
|
||||
#include <xenia/kernel/objects/xenumerator.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
XEnumerator::XEnumerator(KernelState* kernel_state)
|
||||
: XObject(kernel_state, kTypeEnumerator) {}
|
||||
|
||||
XEnumerator::~XEnumerator() {}
|
||||
|
||||
XEnumerator::XEnumerator(KernelState* kernel_state) :
|
||||
XObject(kernel_state, kTypeEnumerator) {
|
||||
}
|
||||
void XEnumerator::Initialize() {}
|
||||
|
||||
XEnumerator::~XEnumerator() {
|
||||
}
|
||||
|
||||
void XEnumerator::Initialize() {
|
||||
}
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -11,27 +11,22 @@
|
||||
#define XENIA_KERNEL_XBOXKRNL_XENUMERATOR_H_
|
||||
|
||||
#include <xenia/kernel/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
|
||||
class XEnumerator : public XObject {
|
||||
public:
|
||||
public:
|
||||
XEnumerator(KernelState* kernel_state);
|
||||
virtual ~XEnumerator();
|
||||
|
||||
void Initialize();
|
||||
|
||||
private:
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XENUMERATOR_H_
|
||||
|
||||
@@ -9,15 +9,11 @@
|
||||
|
||||
#include <xenia/kernel/objects/xevent.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
|
||||
|
||||
XEvent::XEvent(KernelState* kernel_state) :
|
||||
XObject(kernel_state, kTypeEvent),
|
||||
handle_(NULL) {
|
||||
}
|
||||
XEvent::XEvent(KernelState* kernel_state)
|
||||
: XObject(kernel_state, kTypeEvent), handle_(NULL) {}
|
||||
|
||||
XEvent::~XEvent() {
|
||||
if (handle_) {
|
||||
@@ -36,15 +32,15 @@ void XEvent::InitializeNative(void* native_ptr, DISPATCH_HEADER& header) {
|
||||
|
||||
bool manual_reset;
|
||||
switch (header.type_flags >> 24) {
|
||||
case 0x00: // EventNotificationObject (manual reset)
|
||||
manual_reset = true;
|
||||
break;
|
||||
case 0x01: // EventSynchronizationObject (auto reset)
|
||||
manual_reset = false;
|
||||
break;
|
||||
default:
|
||||
assert_always();
|
||||
return;
|
||||
case 0x00: // EventNotificationObject (manual reset)
|
||||
manual_reset = true;
|
||||
break;
|
||||
case 0x01: // EventSynchronizationObject (auto reset)
|
||||
manual_reset = false;
|
||||
break;
|
||||
default:
|
||||
assert_always();
|
||||
return;
|
||||
}
|
||||
|
||||
bool initial_state = header.signal_state ? true : false;
|
||||
@@ -60,10 +56,9 @@ int32_t XEvent::Pulse(uint32_t priority_increment, bool wait) {
|
||||
return PulseEvent(handle_) ? 1 : 0;
|
||||
}
|
||||
|
||||
int32_t XEvent::Reset() {
|
||||
return ResetEvent(handle_) ? 1 : 0;
|
||||
}
|
||||
int32_t XEvent::Reset() { return ResetEvent(handle_) ? 1 : 0; }
|
||||
|
||||
void XEvent::Clear() {
|
||||
ResetEvent(handle_);
|
||||
}
|
||||
void XEvent::Clear() { ResetEvent(handle_); }
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -11,16 +11,13 @@
|
||||
#define XENIA_KERNEL_XBOXKRNL_XEVENT_H_
|
||||
|
||||
#include <xenia/kernel/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
|
||||
class XEvent : public XObject {
|
||||
public:
|
||||
public:
|
||||
XEvent(KernelState* kernel_state);
|
||||
virtual ~XEvent();
|
||||
|
||||
@@ -34,13 +31,11 @@ public:
|
||||
|
||||
virtual void* GetWaitHandle() { return handle_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
HANDLE handle_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XEVENT_H_
|
||||
|
||||
@@ -12,14 +12,11 @@
|
||||
#include <xenia/kernel/async_request.h>
|
||||
#include <xenia/kernel/objects/xevent.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
|
||||
|
||||
XFile::XFile(KernelState* kernel_state, fs::Mode mode) :
|
||||
mode_(mode), position_(0),
|
||||
XObject(kernel_state, kTypeFile) {
|
||||
XFile::XFile(KernelState* kernel_state, fs::Mode mode)
|
||||
: mode_(mode), position_(0), XObject(kernel_state, kTypeFile) {
|
||||
async_event_ = new XEvent(kernel_state);
|
||||
async_event_->Initialize(false, false);
|
||||
}
|
||||
@@ -30,9 +27,7 @@ XFile::~XFile() {
|
||||
async_event_->Delete();
|
||||
}
|
||||
|
||||
void* XFile::GetWaitHandle() {
|
||||
return async_event_->GetWaitHandle();
|
||||
}
|
||||
void* XFile::GetWaitHandle() { return async_event_->GetWaitHandle(); }
|
||||
|
||||
X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) {
|
||||
@@ -40,7 +35,8 @@ X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
// Read from current position.
|
||||
byte_offset = position_;
|
||||
}
|
||||
X_STATUS result = ReadSync(buffer, buffer_length, byte_offset, out_bytes_read);
|
||||
X_STATUS result =
|
||||
ReadSync(buffer, buffer_length, byte_offset, out_bytes_read);
|
||||
if (XSUCCEEDED(result)) {
|
||||
position_ += *out_bytes_read;
|
||||
}
|
||||
@@ -52,7 +48,10 @@ X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
// Also tack on our event so that any waiters wake.
|
||||
request->AddWaitEvent(async_event_);
|
||||
position_ = byte_offset;
|
||||
//return entry_->ReadAsync(buffer, buffer_length, byte_offset, request);
|
||||
// return entry_->ReadAsync(buffer, buffer_length, byte_offset, request);
|
||||
X_STATUS result = X_STATUS_NOT_IMPLEMENTED;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
@@ -22,14 +21,14 @@ class XAsyncRequest;
|
||||
class XEvent;
|
||||
|
||||
class XFileInfo {
|
||||
public:
|
||||
public:
|
||||
// FILE_NETWORK_OPEN_INFORMATION
|
||||
uint64_t creation_time;
|
||||
uint64_t last_access_time;
|
||||
uint64_t last_write_time;
|
||||
uint64_t change_time;
|
||||
uint64_t allocation_size;
|
||||
uint64_t file_length;
|
||||
uint64_t creation_time;
|
||||
uint64_t last_access_time;
|
||||
uint64_t last_write_time;
|
||||
uint64_t change_time;
|
||||
uint64_t allocation_size;
|
||||
uint64_t file_length;
|
||||
X_FILE_ATTRIBUTES attributes;
|
||||
|
||||
void Write(uint8_t* base, uint32_t p) {
|
||||
@@ -40,24 +39,24 @@ public:
|
||||
poly::store_and_swap<uint64_t>(base + p + 32, allocation_size);
|
||||
poly::store_and_swap<uint64_t>(base + p + 40, file_length);
|
||||
poly::store_and_swap<uint32_t>(base + p + 48, attributes);
|
||||
poly::store_and_swap<uint32_t>(base + p + 52, 0); // pad
|
||||
poly::store_and_swap<uint32_t>(base + p + 52, 0); // pad
|
||||
}
|
||||
};
|
||||
|
||||
class XDirectoryInfo {
|
||||
public:
|
||||
public:
|
||||
// FILE_DIRECTORY_INFORMATION
|
||||
uint32_t next_entry_offset;
|
||||
uint32_t file_index;
|
||||
uint64_t creation_time;
|
||||
uint64_t last_access_time;
|
||||
uint64_t last_write_time;
|
||||
uint64_t change_time;
|
||||
uint64_t end_of_file;
|
||||
uint64_t allocation_size;
|
||||
uint32_t next_entry_offset;
|
||||
uint32_t file_index;
|
||||
uint64_t creation_time;
|
||||
uint64_t last_access_time;
|
||||
uint64_t last_write_time;
|
||||
uint64_t change_time;
|
||||
uint64_t end_of_file;
|
||||
uint64_t allocation_size;
|
||||
X_FILE_ATTRIBUTES attributes;
|
||||
uint32_t file_name_length;
|
||||
char file_name[1];
|
||||
uint32_t file_name_length;
|
||||
char file_name[1];
|
||||
|
||||
void Write(uint8_t* base, uint32_t p) {
|
||||
uint8_t* dst = base + p;
|
||||
@@ -75,7 +74,8 @@ public:
|
||||
poly::store_and_swap<uint64_t>(dst + 48, info->allocation_size);
|
||||
poly::store_and_swap<uint32_t>(dst + 56, info->attributes);
|
||||
poly::store_and_swap<uint32_t>(dst + 60, info->file_name_length);
|
||||
xe_copy_memory(dst + 64, info->file_name_length, info->file_name, info->file_name_length);
|
||||
xe_copy_memory(dst + 64, info->file_name_length, info->file_name,
|
||||
info->file_name_length);
|
||||
dst += info->next_entry_offset;
|
||||
src += info->next_entry_offset;
|
||||
} while (info->next_entry_offset != 0);
|
||||
@@ -85,13 +85,13 @@ static_assert_size(XDirectoryInfo, 72);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff540287(v=vs.85).aspx
|
||||
class XVolumeInfo {
|
||||
public:
|
||||
public:
|
||||
// FILE_FS_VOLUME_INFORMATION
|
||||
uint64_t creation_time;
|
||||
uint32_t serial_number;
|
||||
uint32_t label_length;
|
||||
uint32_t supports_objects;
|
||||
char label[1];
|
||||
uint64_t creation_time;
|
||||
uint32_t serial_number;
|
||||
uint32_t label_length;
|
||||
uint32_t supports_objects;
|
||||
char label[1];
|
||||
|
||||
void Write(uint8_t* base, uint32_t p) {
|
||||
uint8_t* dst = base + p;
|
||||
@@ -99,32 +99,35 @@ public:
|
||||
poly::store_and_swap<uint32_t>(dst + 8, this->serial_number);
|
||||
poly::store_and_swap<uint32_t>(dst + 12, this->label_length);
|
||||
poly::store_and_swap<uint32_t>(dst + 16, this->supports_objects);
|
||||
xe_copy_memory(dst + 20, this->label_length, this->label, this->label_length);
|
||||
xe_copy_memory(dst + 20, this->label_length, this->label,
|
||||
this->label_length);
|
||||
}
|
||||
};
|
||||
static_assert_size(XVolumeInfo, 24);
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff540251(v=vs.85).aspx
|
||||
class XFileSystemAttributeInfo {
|
||||
public:
|
||||
public:
|
||||
// FILE_FS_ATTRIBUTE_INFORMATION
|
||||
uint32_t attributes;
|
||||
int32_t maximum_component_name_length;
|
||||
uint32_t fs_name_length;
|
||||
char fs_name[1];
|
||||
uint32_t attributes;
|
||||
int32_t maximum_component_name_length;
|
||||
uint32_t fs_name_length;
|
||||
char fs_name[1];
|
||||
|
||||
void Write(uint8_t* base, uint32_t p) {
|
||||
uint8_t* dst = base + p;
|
||||
poly::store_and_swap<uint32_t>(dst + 0, this->attributes);
|
||||
poly::store_and_swap<uint32_t>(dst + 4, this->maximum_component_name_length);
|
||||
poly::store_and_swap<uint32_t>(dst + 4,
|
||||
this->maximum_component_name_length);
|
||||
poly::store_and_swap<uint32_t>(dst + 8, this->fs_name_length);
|
||||
xe_copy_memory(dst + 12, this->fs_name_length, this->fs_name, this->fs_name_length);
|
||||
xe_copy_memory(dst + 12, this->fs_name_length, this->fs_name,
|
||||
this->fs_name_length);
|
||||
}
|
||||
};
|
||||
static_assert_size(XFileSystemAttributeInfo, 16);
|
||||
|
||||
class XFile : public XObject {
|
||||
public:
|
||||
public:
|
||||
virtual ~XFile();
|
||||
|
||||
virtual const std::string& path() const = 0;
|
||||
@@ -148,24 +151,21 @@ public:
|
||||
|
||||
virtual void* GetWaitHandle();
|
||||
|
||||
protected:
|
||||
protected:
|
||||
XFile(KernelState* kernel_state, fs::Mode mode);
|
||||
virtual X_STATUS ReadSync(
|
||||
void* buffer, size_t buffer_length, size_t byte_offset,
|
||||
size_t* out_bytes_read) = 0;
|
||||
virtual X_STATUS ReadSync(void* buffer, size_t buffer_length,
|
||||
size_t byte_offset, size_t* out_bytes_read) = 0;
|
||||
|
||||
private:
|
||||
fs::Mode mode_;
|
||||
XEvent* async_event_;
|
||||
private:
|
||||
fs::Mode mode_;
|
||||
XEvent* async_event_;
|
||||
|
||||
// TODO(benvanik): create flags, open state, etc.
|
||||
|
||||
size_t position_;
|
||||
size_t position_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XFILE_H_
|
||||
|
||||
@@ -13,14 +13,11 @@
|
||||
#include <xenia/cpu/cpu.h>
|
||||
#include <xenia/kernel/objects/xthread.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::kernel;
|
||||
|
||||
|
||||
XKernelModule::XKernelModule(KernelState* kernel_state, const char* path) :
|
||||
XModule(kernel_state, path) {
|
||||
XKernelModule::XKernelModule(KernelState* kernel_state, const char* path)
|
||||
: XModule(kernel_state, path) {
|
||||
emulator_ = kernel_state->emulator();
|
||||
memory_ = emulator_->memory();
|
||||
export_resolver_ = kernel_state->emulator()->export_resolver();
|
||||
@@ -28,11 +25,13 @@ XKernelModule::XKernelModule(KernelState* kernel_state, const char* path) :
|
||||
OnLoad();
|
||||
}
|
||||
|
||||
XKernelModule::~XKernelModule() {
|
||||
}
|
||||
XKernelModule::~XKernelModule() {}
|
||||
|
||||
void* XKernelModule::GetProcAddressByOrdinal(uint16_t ordinal) {
|
||||
// TODO(benvanik): check export tables.
|
||||
XELOGE("GetProcAddressByOrdinal not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -14,29 +14,26 @@
|
||||
|
||||
XEDECLARECLASS1(xe, Emulator);
|
||||
XEDECLARECLASS1(xe, ExportResolver);
|
||||
XEDECLARECLASS2(xe, kernel, KernelState);
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
class KernelState;
|
||||
|
||||
class XKernelModule : public XModule {
|
||||
public:
|
||||
public:
|
||||
XKernelModule(KernelState* kernel_state, const char* path);
|
||||
virtual ~XKernelModule();
|
||||
|
||||
virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
|
||||
|
||||
protected:
|
||||
Emulator* emulator_;
|
||||
Memory* memory_;
|
||||
ExportResolver* export_resolver_;
|
||||
protected:
|
||||
Emulator* emulator_;
|
||||
Memory* memory_;
|
||||
ExportResolver* export_resolver_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XKERNEL_MODULE_H_
|
||||
|
||||
@@ -11,14 +11,11 @@
|
||||
|
||||
#include <xdb/protocol.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::kernel;
|
||||
|
||||
|
||||
XModule::XModule(KernelState* kernel_state, const std::string& path) :
|
||||
XObject(kernel_state, kTypeModule), path_(path) {
|
||||
XModule::XModule(KernelState* kernel_state, const std::string& path)
|
||||
: XObject(kernel_state, kTypeModule), path_(path) {
|
||||
auto last_slash = path.find_last_of('/');
|
||||
if (last_slash == path.npos) {
|
||||
last_slash = path.find_last_of('\\');
|
||||
@@ -54,8 +51,10 @@ void XModule::OnLoad() {
|
||||
kernel_state_->RegisterModule(this);
|
||||
}
|
||||
|
||||
X_STATUS XModule::GetSection(
|
||||
const char* name,
|
||||
uint32_t* out_section_data, uint32_t* out_section_size) {
|
||||
X_STATUS XModule::GetSection(const char* name, uint32_t* out_section_data,
|
||||
uint32_t* out_section_size) {
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -13,16 +13,13 @@
|
||||
#include <string>
|
||||
|
||||
#include <xenia/kernel/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
|
||||
class XModule : public XObject {
|
||||
public:
|
||||
public:
|
||||
XModule(KernelState* kernel_state, const std::string& path);
|
||||
virtual ~XModule();
|
||||
|
||||
@@ -30,20 +27,17 @@ public:
|
||||
const std::string& name() const { return name_; }
|
||||
|
||||
virtual void* GetProcAddressByOrdinal(uint16_t ordinal) = 0;
|
||||
virtual X_STATUS GetSection(
|
||||
const char* name,
|
||||
uint32_t* out_section_data, uint32_t* out_section_size);
|
||||
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
|
||||
uint32_t* out_section_size);
|
||||
|
||||
protected:
|
||||
protected:
|
||||
void OnLoad();
|
||||
|
||||
std::string name_;
|
||||
std::string path_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XMODULE_H_
|
||||
|
||||
@@ -9,15 +9,11 @@
|
||||
|
||||
#include <xenia/kernel/objects/xmutant.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
|
||||
|
||||
XMutant::XMutant(KernelState* kernel_state) :
|
||||
XObject(kernel_state, kTypeMutant),
|
||||
handle_(NULL) {
|
||||
}
|
||||
XMutant::XMutant(KernelState* kernel_state)
|
||||
: XObject(kernel_state, kTypeMutant), handle_(NULL) {}
|
||||
|
||||
XMutant::~XMutant() {
|
||||
if (handle_) {
|
||||
@@ -38,8 +34,8 @@ void XMutant::InitializeNative(void* native_ptr, DISPATCH_HEADER& header) {
|
||||
assert_always();
|
||||
}
|
||||
|
||||
X_STATUS XMutant::ReleaseMutant(
|
||||
uint32_t priority_increment, bool abandon, bool wait) {
|
||||
X_STATUS XMutant::ReleaseMutant(uint32_t priority_increment, bool abandon,
|
||||
bool wait) {
|
||||
// TODO(benvanik): abandoning.
|
||||
assert_false(abandon);
|
||||
BOOL result = ReleaseMutex(handle_);
|
||||
@@ -49,3 +45,6 @@ X_STATUS XMutant::ReleaseMutant(
|
||||
return X_STATUS_MUTANT_NOT_OWNED;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -11,16 +11,13 @@
|
||||
#define XENIA_KERNEL_XBOXKRNL_XMUTANT_H_
|
||||
|
||||
#include <xenia/kernel/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
|
||||
class XMutant : public XObject {
|
||||
public:
|
||||
public:
|
||||
XMutant(KernelState* kernel_state);
|
||||
virtual ~XMutant();
|
||||
|
||||
@@ -31,13 +28,11 @@ public:
|
||||
|
||||
virtual void* GetWaitHandle() { return handle_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
HANDLE handle_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XMUTANT_H_
|
||||
|
||||
@@ -9,15 +9,14 @@
|
||||
|
||||
#include <xenia/kernel/objects/xnotify_listener.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
|
||||
|
||||
XNotifyListener::XNotifyListener(KernelState* kernel_state) :
|
||||
XObject(kernel_state, kTypeNotifyListener),
|
||||
wait_handle_(NULL), mask_(0), notification_count_(0) {
|
||||
}
|
||||
XNotifyListener::XNotifyListener(KernelState* kernel_state)
|
||||
: XObject(kernel_state, kTypeNotifyListener),
|
||||
wait_handle_(NULL),
|
||||
mask_(0),
|
||||
notification_count_(0) {}
|
||||
|
||||
XNotifyListener::~XNotifyListener() {
|
||||
kernel_state_->UnregisterNotifyListener(this);
|
||||
@@ -48,13 +47,13 @@ void XNotifyListener::EnqueueNotification(XNotificationID id, uint32_t data) {
|
||||
} else {
|
||||
// New.
|
||||
notification_count_++;
|
||||
notifications_.insert({ id, data });
|
||||
notifications_.insert({id, data});
|
||||
}
|
||||
SetEvent(wait_handle_);
|
||||
}
|
||||
|
||||
bool XNotifyListener::DequeueNotification(
|
||||
XNotificationID* out_id, uint32_t* out_data) {
|
||||
bool XNotifyListener::DequeueNotification(XNotificationID* out_id,
|
||||
uint32_t* out_data) {
|
||||
std::lock_guard<std::mutex> lock(lock_);
|
||||
bool dequeued = false;
|
||||
if (notification_count_) {
|
||||
@@ -71,8 +70,8 @@ bool XNotifyListener::DequeueNotification(
|
||||
return dequeued;
|
||||
}
|
||||
|
||||
bool XNotifyListener::DequeueNotification(
|
||||
XNotificationID id, uint32_t* out_data) {
|
||||
bool XNotifyListener::DequeueNotification(XNotificationID id,
|
||||
uint32_t* out_data) {
|
||||
std::lock_guard<std::mutex> lock(lock_);
|
||||
bool dequeued = false;
|
||||
if (notification_count_) {
|
||||
@@ -89,3 +88,6 @@ bool XNotifyListener::DequeueNotification(
|
||||
}
|
||||
return dequeued;
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -7,25 +7,19 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
// This should probably be in XAM, but I don't want to build an extensible
|
||||
// object system. Meh.
|
||||
|
||||
#ifndef XENIA_KERNEL_XBOXKRNL_XNOTIFY_LISTENER_H_
|
||||
#define XENIA_KERNEL_XBOXKRNL_XNOTIFY_LISTENER_H_
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <xenia/kernel/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
|
||||
class XNotifyListener : public XObject {
|
||||
public:
|
||||
public:
|
||||
XNotifyListener(KernelState* kernel_state);
|
||||
virtual ~XNotifyListener();
|
||||
|
||||
@@ -37,7 +31,7 @@ public:
|
||||
|
||||
virtual void* GetWaitHandle() { return wait_handle_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
HANDLE wait_handle_;
|
||||
std::mutex lock_;
|
||||
std::unordered_map<XNotificationID, uint32_t> notifications_;
|
||||
@@ -45,9 +39,7 @@ private:
|
||||
uint64_t mask_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XNOTIFY_LISTENER_H_
|
||||
|
||||
@@ -9,15 +9,11 @@
|
||||
|
||||
#include <xenia/kernel/objects/xsemaphore.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
|
||||
|
||||
XSemaphore::XSemaphore(KernelState* kernel_state) :
|
||||
XObject(kernel_state, kTypeSemaphore),
|
||||
handle_(NULL) {
|
||||
}
|
||||
XSemaphore::XSemaphore(KernelState* kernel_state)
|
||||
: XObject(kernel_state, kTypeSemaphore), handle_(NULL) {}
|
||||
|
||||
XSemaphore::~XSemaphore() {
|
||||
if (handle_) {
|
||||
@@ -43,3 +39,6 @@ int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) {
|
||||
::ReleaseSemaphore(handle_, release_count, &previous_count);
|
||||
return previous_count;
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -11,16 +11,13 @@
|
||||
#define XENIA_KERNEL_XBOXKRNL_XSEMAPHORE_H_
|
||||
|
||||
#include <xenia/kernel/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
|
||||
class XSemaphore : public XObject {
|
||||
public:
|
||||
public:
|
||||
XSemaphore(KernelState* kernel_state);
|
||||
virtual ~XSemaphore();
|
||||
|
||||
@@ -31,13 +28,11 @@ public:
|
||||
|
||||
virtual void* GetWaitHandle() { return handle_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
HANDLE handle_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XSEMAPHORE_H_
|
||||
|
||||
@@ -16,41 +16,34 @@
|
||||
#include <xenia/kernel/objects/xevent.h>
|
||||
#include <xenia/kernel/objects/xuser_module.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace alloy;
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::kernel;
|
||||
|
||||
uint32_t next_xthread_id = 0;
|
||||
thread_local XThread* current_thread_tls;
|
||||
std::mutex critical_region_;
|
||||
XThread* shared_kernel_thread_ = 0;
|
||||
|
||||
namespace {
|
||||
static uint32_t next_xthread_id = 0;
|
||||
static thread_local XThread* current_thread_tls;
|
||||
static std::mutex critical_region_;
|
||||
static XThread* shared_kernel_thread_ = 0;
|
||||
}
|
||||
|
||||
|
||||
XThread::XThread(KernelState* kernel_state,
|
||||
uint32_t stack_size,
|
||||
uint32_t xapi_thread_startup,
|
||||
uint32_t start_address, uint32_t start_context,
|
||||
uint32_t creation_flags) :
|
||||
XObject(kernel_state, kTypeThread),
|
||||
thread_id_(++next_xthread_id),
|
||||
thread_handle_(0),
|
||||
thread_state_address_(0),
|
||||
thread_state_(0),
|
||||
event_(NULL),
|
||||
irql_(0) {
|
||||
creation_params_.stack_size = stack_size;
|
||||
creation_params_.xapi_thread_startup = xapi_thread_startup;
|
||||
creation_params_.start_address = start_address;
|
||||
creation_params_.start_context = start_context;
|
||||
XThread::XThread(KernelState* kernel_state, uint32_t stack_size,
|
||||
uint32_t xapi_thread_startup, uint32_t start_address,
|
||||
uint32_t start_context, uint32_t creation_flags)
|
||||
: XObject(kernel_state, kTypeThread),
|
||||
thread_id_(++next_xthread_id),
|
||||
thread_handle_(0),
|
||||
thread_state_address_(0),
|
||||
thread_state_(0),
|
||||
event_(NULL),
|
||||
irql_(0) {
|
||||
creation_params_.stack_size = stack_size;
|
||||
creation_params_.xapi_thread_startup = xapi_thread_startup;
|
||||
creation_params_.start_address = start_address;
|
||||
creation_params_.start_context = start_context;
|
||||
|
||||
// top 8 bits = processor ID (or 0 for default)
|
||||
// bit 0 = 1 to create suspended
|
||||
creation_params_.creation_flags = creation_flags;
|
||||
creation_params_.creation_flags = creation_flags;
|
||||
|
||||
// Adjust stack size - min of 16k.
|
||||
if (creation_params_.stack_size < 16 * 1024) {
|
||||
@@ -108,8 +101,7 @@ XThread* XThread::GetCurrentThread() {
|
||||
XThread::EnterCriticalRegion();
|
||||
thread = shared_kernel_thread_;
|
||||
if (!thread) {
|
||||
thread = new XThread(
|
||||
KernelState::shared(), 32 * 1024, 0, 0, 0, 0);
|
||||
thread = new XThread(KernelState::shared(), 32 * 1024, 0, 0, 0, 0);
|
||||
shared_kernel_thread_ = thread;
|
||||
current_thread_tls = thread;
|
||||
}
|
||||
@@ -127,21 +119,17 @@ uint32_t XThread::GetCurrentThreadId(const uint8_t* thread_state_block) {
|
||||
return poly::load_and_swap<uint32_t>(thread_state_block + 0x14C);
|
||||
}
|
||||
|
||||
uint32_t XThread::thread_state() {
|
||||
return thread_state_address_;
|
||||
}
|
||||
uint32_t XThread::thread_state() { return thread_state_address_; }
|
||||
|
||||
uint32_t XThread::thread_id() {
|
||||
return thread_id_;
|
||||
}
|
||||
uint32_t XThread::thread_id() { return thread_id_; }
|
||||
|
||||
uint32_t XThread::last_error() {
|
||||
uint8_t *p = memory()->Translate(thread_state_address_);
|
||||
uint8_t* p = memory()->Translate(thread_state_address_);
|
||||
return poly::load_and_swap<uint32_t>(p + 0x160);
|
||||
}
|
||||
|
||||
void XThread::set_last_error(uint32_t error_code) {
|
||||
uint8_t *p = memory()->Translate(thread_state_address_);
|
||||
uint8_t* p = memory()->Translate(thread_state_address_);
|
||||
poly::store_and_swap<uint32_t>(p + 0x160, error_code);
|
||||
}
|
||||
|
||||
@@ -163,8 +151,8 @@ X_STATUS XThread::Create() {
|
||||
// 0x160: last error
|
||||
// So, at offset 0x100 we have a 4b pointer to offset 200, then have the
|
||||
// structure.
|
||||
thread_state_address_ = (uint32_t)memory()->HeapAlloc(
|
||||
0, 2048, MEMORY_FLAG_ZERO);
|
||||
thread_state_address_ =
|
||||
(uint32_t)memory()->HeapAlloc(0, 2048, alloy::MEMORY_FLAG_ZERO);
|
||||
if (!thread_state_address_) {
|
||||
XELOGW("Unable to allocate thread state block");
|
||||
return X_STATUS_NO_MEMORY;
|
||||
@@ -178,14 +166,14 @@ X_STATUS XThread::Create() {
|
||||
// Allocate thread scratch.
|
||||
// This is used by interrupts/APCs/etc so we can round-trip pointers through.
|
||||
scratch_size_ = 4 * 16;
|
||||
scratch_address_ = (uint32_t)memory()->HeapAlloc(
|
||||
0, scratch_size_, MEMORY_FLAG_ZERO);
|
||||
scratch_address_ =
|
||||
(uint32_t)memory()->HeapAlloc(0, scratch_size_, alloy::MEMORY_FLAG_ZERO);
|
||||
|
||||
// Allocate TLS block.
|
||||
const xe_xex2_header_t* header = module->xex_header();
|
||||
uint32_t tls_size = header->tls_info.slot_count * header->tls_info.data_size;
|
||||
tls_address_ = (uint32_t)memory()->HeapAlloc(
|
||||
0, tls_size, MEMORY_FLAG_ZERO);
|
||||
tls_address_ =
|
||||
(uint32_t)memory()->HeapAlloc(0, tls_size, alloy::MEMORY_FLAG_ZERO);
|
||||
if (!tls_address_) {
|
||||
XELOGW("Unable to allocate thread local storage block");
|
||||
module->Release();
|
||||
@@ -194,22 +182,21 @@ X_STATUS XThread::Create() {
|
||||
|
||||
// Copy in default TLS info.
|
||||
// TODO(benvanik): is this correct?
|
||||
memory()->Copy(
|
||||
tls_address_, header->tls_info.raw_data_address, tls_size);
|
||||
memory()->Copy(tls_address_, header->tls_info.raw_data_address, tls_size);
|
||||
|
||||
// Setup the thread state block (last error/etc).
|
||||
uint8_t *p = memory()->Translate(thread_state_address_);
|
||||
uint8_t* p = memory()->Translate(thread_state_address_);
|
||||
poly::store_and_swap<uint32_t>(p + 0x000, tls_address_);
|
||||
poly::store_and_swap<uint32_t>(p + 0x100, thread_state_address_);
|
||||
poly::store_and_swap<uint32_t>(p + 0x14C, thread_id_);
|
||||
poly::store_and_swap<uint32_t>(p + 0x150, 0); // ?
|
||||
poly::store_and_swap<uint32_t>(p + 0x160, 0); // last error
|
||||
poly::store_and_swap<uint32_t>(p + 0x150, 0); // ?
|
||||
poly::store_and_swap<uint32_t>(p + 0x160, 0); // last error
|
||||
|
||||
// Allocate processor thread state.
|
||||
// This is thread safe.
|
||||
thread_state_ = new XenonThreadState(
|
||||
kernel_state()->processor()->runtime(),
|
||||
thread_id_, creation_params_.stack_size, thread_state_address_);
|
||||
thread_state_ =
|
||||
new XenonThreadState(kernel_state()->processor()->runtime(), thread_id_,
|
||||
creation_params_.stack_size, thread_state_address_);
|
||||
|
||||
X_STATUS return_code = PlatformCreate();
|
||||
if (XFAILED(return_code)) {
|
||||
@@ -268,13 +255,10 @@ static uint32_t __stdcall XThreadStartCallbackWin32(void* param) {
|
||||
|
||||
X_STATUS XThread::PlatformCreate() {
|
||||
bool suspended = creation_params_.creation_flags & 0x1;
|
||||
thread_handle_ = CreateThread(
|
||||
NULL,
|
||||
creation_params_.stack_size,
|
||||
(LPTHREAD_START_ROUTINE)XThreadStartCallbackWin32,
|
||||
this,
|
||||
suspended ? CREATE_SUSPENDED : 0,
|
||||
NULL);
|
||||
thread_handle_ =
|
||||
CreateThread(NULL, creation_params_.stack_size,
|
||||
(LPTHREAD_START_ROUTINE)XThreadStartCallbackWin32, this,
|
||||
suspended ? CREATE_SUSPENDED : 0, NULL);
|
||||
if (!thread_handle_) {
|
||||
uint32_t last_error = GetLastError();
|
||||
// TODO(benvanik): translate?
|
||||
@@ -319,20 +303,15 @@ X_STATUS XThread::PlatformCreate() {
|
||||
if (creation_params_.creation_flags & 0x1) {
|
||||
#if XE_PLATFORM_OSX
|
||||
result_code = pthread_create_suspended_np(
|
||||
reinterpret_cast<pthread_t*>(&thread_handle_),
|
||||
&attr,
|
||||
&XThreadStartCallbackPthreads,
|
||||
this);
|
||||
reinterpret_cast<pthread_t*>(&thread_handle_), &attr,
|
||||
&XThreadStartCallbackPthreads, this);
|
||||
#else
|
||||
// TODO(benvanik): pthread_create_suspended_np on linux
|
||||
assert_always();
|
||||
#endif // OSX
|
||||
} else {
|
||||
result_code = pthread_create(
|
||||
reinterpret_cast<pthread_t*>(&thread_handle_),
|
||||
&attr,
|
||||
&XThreadStartCallbackPthreads,
|
||||
this);
|
||||
result_code = pthread_create(reinterpret_cast<pthread_t*>(&thread_handle_),
|
||||
&attr, &XThreadStartCallbackPthreads, this);
|
||||
}
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
@@ -389,28 +368,21 @@ void XThread::EnterCriticalRegion() {
|
||||
critical_region_.lock();
|
||||
}
|
||||
|
||||
void XThread::LeaveCriticalRegion() {
|
||||
critical_region_.unlock();
|
||||
}
|
||||
void XThread::LeaveCriticalRegion() { critical_region_.unlock(); }
|
||||
|
||||
uint32_t XThread::RaiseIrql(uint32_t new_irql) {
|
||||
return irql_.exchange(new_irql);
|
||||
}
|
||||
|
||||
void XThread::LowerIrql(uint32_t new_irql) {
|
||||
irql_ = new_irql;
|
||||
}
|
||||
void XThread::LowerIrql(uint32_t new_irql) { irql_ = new_irql; }
|
||||
|
||||
void XThread::LockApc() {
|
||||
apc_lock_.lock();
|
||||
}
|
||||
void XThread::LockApc() { apc_lock_.lock(); }
|
||||
|
||||
void XThread::UnlockApc() {
|
||||
bool needs_apc = apc_list_->HasPending();
|
||||
apc_lock_.unlock();
|
||||
if (needs_apc) {
|
||||
QueueUserAPC(reinterpret_cast<PAPCFUNC>(DeliverAPCs),
|
||||
thread_handle_,
|
||||
QueueUserAPC(reinterpret_cast<PAPCFUNC>(DeliverAPCs), thread_handle_,
|
||||
reinterpret_cast<ULONG_PTR>(this));
|
||||
}
|
||||
}
|
||||
@@ -447,16 +419,15 @@ void XThread::DeliverAPCs(void* data) {
|
||||
poly::store_and_swap<uint32_t>(scratch_ptr + 4, normal_context);
|
||||
poly::store_and_swap<uint32_t>(scratch_ptr + 8, system_arg1);
|
||||
poly::store_and_swap<uint32_t>(scratch_ptr + 12, system_arg2);
|
||||
// kernel_routine(apc_address, &normal_routine, &normal_context, &system_arg1, &system_arg2)
|
||||
// kernel_routine(apc_address, &normal_routine, &normal_context,
|
||||
// &system_arg1, &system_arg2)
|
||||
uint64_t kernel_args[] = {
|
||||
apc_address,
|
||||
thread->scratch_address_ + 0,
|
||||
thread->scratch_address_ + 4,
|
||||
thread->scratch_address_ + 8,
|
||||
thread->scratch_address_ + 12,
|
||||
apc_address, thread->scratch_address_ + 0,
|
||||
thread->scratch_address_ + 4, thread->scratch_address_ + 8,
|
||||
thread->scratch_address_ + 12,
|
||||
};
|
||||
processor->ExecuteInterrupt(
|
||||
0, kernel_routine, kernel_args, poly::countof(kernel_args));
|
||||
processor->ExecuteInterrupt(0, kernel_routine, kernel_args,
|
||||
poly::countof(kernel_args));
|
||||
normal_routine = poly::load_and_swap<uint32_t>(scratch_ptr + 0);
|
||||
normal_context = poly::load_and_swap<uint32_t>(scratch_ptr + 4);
|
||||
system_arg1 = poly::load_and_swap<uint32_t>(scratch_ptr + 8);
|
||||
@@ -467,9 +438,9 @@ void XThread::DeliverAPCs(void* data) {
|
||||
if (normal_routine) {
|
||||
thread->UnlockApc();
|
||||
// normal_routine(normal_context, system_arg1, system_arg2)
|
||||
uint64_t normal_args[] = { normal_context, system_arg1, system_arg2 };
|
||||
processor->ExecuteInterrupt(
|
||||
0, normal_routine, normal_args, poly::countof(normal_args));
|
||||
uint64_t normal_args[] = {normal_context, system_arg1, system_arg2};
|
||||
processor->ExecuteInterrupt(0, normal_routine, normal_args,
|
||||
poly::countof(normal_args));
|
||||
thread->LockApc();
|
||||
}
|
||||
}
|
||||
@@ -493,17 +464,15 @@ void XThread::RundownAPCs() {
|
||||
// Call the rundown routine.
|
||||
if (rundown_routine) {
|
||||
// rundown_routine(apc)
|
||||
uint64_t args[] = { apc_address };
|
||||
kernel_state()->processor()->ExecuteInterrupt(
|
||||
0, rundown_routine, args, poly::countof(args));
|
||||
uint64_t args[] = {apc_address};
|
||||
kernel_state()->processor()->ExecuteInterrupt(0, rundown_routine, args,
|
||||
poly::countof(args));
|
||||
}
|
||||
}
|
||||
UnlockApc();
|
||||
}
|
||||
|
||||
int32_t XThread::QueryPriority() {
|
||||
return GetThreadPriority(thread_handle_);
|
||||
}
|
||||
int32_t XThread::QueryPriority() { return GetThreadPriority(thread_handle_); }
|
||||
|
||||
void XThread::SetPriority(int32_t increment) {
|
||||
SetThreadPriority(thread_handle_, increment);
|
||||
@@ -538,8 +507,8 @@ X_STATUS XThread::Suspend(uint32_t* out_suspend_count) {
|
||||
}
|
||||
}
|
||||
|
||||
X_STATUS XThread::Delay(
|
||||
uint32_t processor_mode, uint32_t alertable, uint64_t interval) {
|
||||
X_STATUS XThread::Delay(uint32_t processor_mode, uint32_t alertable,
|
||||
uint64_t interval) {
|
||||
int64_t timeout_ticks = interval;
|
||||
DWORD timeout_ms;
|
||||
if (timeout_ticks > 0) {
|
||||
@@ -549,21 +518,22 @@ X_STATUS XThread::Delay(
|
||||
timeout_ms = 0;
|
||||
} else if (timeout_ticks < 0) {
|
||||
// Relative time.
|
||||
timeout_ms = (DWORD)(-timeout_ticks / 10000); // Ticks -> MS
|
||||
timeout_ms = (DWORD)(-timeout_ticks / 10000); // Ticks -> MS
|
||||
} else {
|
||||
timeout_ms = 0;
|
||||
}
|
||||
DWORD result = SleepEx(timeout_ms, alertable ? TRUE : FALSE);
|
||||
switch (result) {
|
||||
case 0:
|
||||
return X_STATUS_SUCCESS;
|
||||
case WAIT_IO_COMPLETION:
|
||||
return X_STATUS_USER_APC;
|
||||
default:
|
||||
return X_STATUS_ALERTED;
|
||||
case 0:
|
||||
return X_STATUS_SUCCESS;
|
||||
case WAIT_IO_COMPLETION:
|
||||
return X_STATUS_USER_APC;
|
||||
default:
|
||||
return X_STATUS_ALERTED;
|
||||
}
|
||||
}
|
||||
|
||||
void* XThread::GetWaitHandle() {
|
||||
return event_->GetWaitHandle();
|
||||
}
|
||||
void* XThread::GetWaitHandle() { return event_->GetWaitHandle(); }
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -15,26 +15,21 @@
|
||||
#include <string>
|
||||
|
||||
#include <xenia/kernel/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
XEDECLARECLASS2(xe, cpu, XenonThreadState);
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
class NativeList;
|
||||
class XEvent;
|
||||
|
||||
|
||||
class XThread : public XObject {
|
||||
public:
|
||||
XThread(KernelState* kernel_state,
|
||||
uint32_t stack_size,
|
||||
uint32_t xapi_thread_startup,
|
||||
uint32_t start_address, uint32_t start_context,
|
||||
uint32_t creation_flags);
|
||||
public:
|
||||
XThread(KernelState* kernel_state, uint32_t stack_size,
|
||||
uint32_t xapi_thread_startup, uint32_t start_address,
|
||||
uint32_t start_context, uint32_t creation_flags);
|
||||
virtual ~XThread();
|
||||
|
||||
static XThread* GetCurrentThread();
|
||||
@@ -68,12 +63,12 @@ public:
|
||||
|
||||
X_STATUS Resume(uint32_t* out_suspend_count);
|
||||
X_STATUS Suspend(uint32_t* out_suspend_count);
|
||||
X_STATUS Delay(
|
||||
uint32_t processor_mode, uint32_t alertable, uint64_t interval);
|
||||
X_STATUS Delay(uint32_t processor_mode, uint32_t alertable,
|
||||
uint64_t interval);
|
||||
|
||||
virtual void* GetWaitHandle();
|
||||
|
||||
private:
|
||||
private:
|
||||
X_STATUS PlatformCreate();
|
||||
void PlatformDestroy();
|
||||
X_STATUS PlatformExit(int exit_code);
|
||||
@@ -82,33 +77,31 @@ private:
|
||||
void RundownAPCs();
|
||||
|
||||
struct {
|
||||
uint32_t stack_size;
|
||||
uint32_t xapi_thread_startup;
|
||||
uint32_t start_address;
|
||||
uint32_t start_context;
|
||||
uint32_t creation_flags;
|
||||
uint32_t stack_size;
|
||||
uint32_t xapi_thread_startup;
|
||||
uint32_t start_address;
|
||||
uint32_t start_context;
|
||||
uint32_t creation_flags;
|
||||
} creation_params_;
|
||||
|
||||
uint32_t thread_id_;
|
||||
void* thread_handle_;
|
||||
uint32_t scratch_address_;
|
||||
uint32_t scratch_size_;
|
||||
uint32_t tls_address_;
|
||||
uint32_t thread_state_address_;
|
||||
uint32_t thread_id_;
|
||||
void* thread_handle_;
|
||||
uint32_t scratch_address_;
|
||||
uint32_t scratch_size_;
|
||||
uint32_t tls_address_;
|
||||
uint32_t thread_state_address_;
|
||||
cpu::XenonThreadState* thread_state_;
|
||||
|
||||
std::string name_;
|
||||
std::string name_;
|
||||
|
||||
std::atomic<uint32_t> irql_;
|
||||
std::mutex apc_lock_;
|
||||
NativeList* apc_list_;
|
||||
NativeList* apc_list_;
|
||||
|
||||
XEvent* event_;
|
||||
XEvent* event_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XTHREAD_H_
|
||||
|
||||
@@ -11,15 +11,11 @@
|
||||
|
||||
#include <xenia/cpu/processor.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::kernel;
|
||||
|
||||
|
||||
XTimer::XTimer(KernelState* kernel_state) :
|
||||
XObject(kernel_state, kTypeTimer),
|
||||
handle_(NULL) {
|
||||
}
|
||||
XTimer::XTimer(KernelState* kernel_state)
|
||||
: XObject(kernel_state, kTypeTimer), handle_(NULL) {}
|
||||
|
||||
XTimer::~XTimer() {
|
||||
if (handle_) {
|
||||
@@ -32,33 +28,32 @@ void XTimer::Initialize(uint32_t timer_type) {
|
||||
|
||||
bool manual_reset = false;
|
||||
switch (timer_type) {
|
||||
case 0: // NotificationTimer
|
||||
manual_reset = true;
|
||||
break;
|
||||
case 1: // SynchronizationTimer
|
||||
manual_reset = false;
|
||||
break;
|
||||
default:
|
||||
assert_always();
|
||||
break;
|
||||
case 0: // NotificationTimer
|
||||
manual_reset = true;
|
||||
break;
|
||||
case 1: // SynchronizationTimer
|
||||
manual_reset = false;
|
||||
break;
|
||||
default:
|
||||
assert_always();
|
||||
break;
|
||||
}
|
||||
|
||||
handle_ = CreateWaitableTimer(NULL, manual_reset, NULL);
|
||||
}
|
||||
|
||||
X_STATUS XTimer::SetTimer(
|
||||
int64_t due_time, uint32_t period_ms,
|
||||
uint32_t routine, uint32_t routine_arg, bool resume) {
|
||||
X_STATUS XTimer::SetTimer(int64_t due_time, uint32_t period_ms,
|
||||
uint32_t routine, uint32_t routine_arg, bool resume) {
|
||||
// Stash routine for callback.
|
||||
current_routine_ = routine;
|
||||
current_routine_arg_ = routine_arg;
|
||||
|
||||
LARGE_INTEGER due_time_li;
|
||||
due_time_li.QuadPart = due_time;
|
||||
BOOL result = SetWaitableTimer(
|
||||
handle_, &due_time_li, period_ms,
|
||||
routine ? (PTIMERAPCROUTINE)CompletionRoutine : NULL, this,
|
||||
resume ? TRUE : FALSE);
|
||||
BOOL result =
|
||||
SetWaitableTimer(handle_, &due_time_li, period_ms,
|
||||
routine ? (PTIMERAPCROUTINE)CompletionRoutine : NULL,
|
||||
this, resume ? TRUE : FALSE);
|
||||
|
||||
// Caller is checking for STATUS_TIMER_RESUME_IGNORED.
|
||||
// This occurs if result == TRUE but error is set.
|
||||
@@ -69,8 +64,8 @@ X_STATUS XTimer::SetTimer(
|
||||
return result ? X_STATUS_SUCCESS : X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
void XTimer::CompletionRoutine(
|
||||
XTimer* timer, DWORD timer_low, DWORD timer_high) {
|
||||
void XTimer::CompletionRoutine(XTimer* timer, DWORD timer_low,
|
||||
DWORD timer_high) {
|
||||
assert_true(timer->current_routine_);
|
||||
|
||||
// Queue APC to call back routine with (arg, low, high).
|
||||
@@ -81,6 +76,9 @@ void XTimer::CompletionRoutine(
|
||||
}
|
||||
|
||||
X_STATUS XTimer::Cancel() {
|
||||
return CancelWaitableTimer(handle_) == 0 ?
|
||||
X_STATUS_SUCCESS : X_STATUS_UNSUCCESSFUL;
|
||||
return CancelWaitableTimer(handle_) == 0 ? X_STATUS_SUCCESS
|
||||
: X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -11,41 +11,36 @@
|
||||
#define XENIA_KERNEL_XBOXKRNL_XTIMER_H_
|
||||
|
||||
#include <xenia/kernel/xobject.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
|
||||
class XTimer : public XObject {
|
||||
public:
|
||||
public:
|
||||
XTimer(KernelState* kernel_state);
|
||||
virtual ~XTimer();
|
||||
|
||||
void Initialize(uint32_t timer_type);
|
||||
|
||||
// completion routine, arg to completion routine
|
||||
X_STATUS SetTimer(int64_t due_time, uint32_t period_ms,
|
||||
uint32_t routine, uint32_t routine_arg, bool resume);
|
||||
X_STATUS SetTimer(int64_t due_time, uint32_t period_ms, uint32_t routine,
|
||||
uint32_t routine_arg, bool resume);
|
||||
X_STATUS Cancel();
|
||||
|
||||
virtual void* GetWaitHandle() { return handle_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
HANDLE handle_;
|
||||
|
||||
uint32_t current_routine_;
|
||||
uint32_t current_routine_arg_;
|
||||
|
||||
static void CompletionRoutine(
|
||||
XTimer* timer, DWORD timer_low, DWORD timer_high);
|
||||
static void CompletionRoutine(XTimer* timer, DWORD timer_low,
|
||||
DWORD timer_high);
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_TIMER_H_
|
||||
|
||||
@@ -14,24 +14,17 @@
|
||||
#include <xenia/kernel/objects/xfile.h>
|
||||
#include <xenia/kernel/objects/xthread.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::kernel;
|
||||
|
||||
XUserModule::XUserModule(KernelState* kernel_state, const char* path)
|
||||
: XModule(kernel_state, path), xex_(NULL) {}
|
||||
|
||||
XUserModule::XUserModule(KernelState* kernel_state, const char* path) :
|
||||
XModule(kernel_state, path),
|
||||
xex_(NULL) {
|
||||
}
|
||||
XUserModule::~XUserModule() { xe_xex2_release(xex_); }
|
||||
|
||||
XUserModule::~XUserModule() {
|
||||
xe_xex2_release(xex_);
|
||||
}
|
||||
|
||||
xe_xex2_ref XUserModule::xex() {
|
||||
return xe_xex2_retain(xex_);
|
||||
}
|
||||
xe_xex2_ref XUserModule::xex() { return xe_xex2_retain(xex_); }
|
||||
|
||||
const xe_xex2_header_t* XUserModule::xex_header() {
|
||||
return xe_xex2_get_header(xex_);
|
||||
@@ -134,9 +127,8 @@ void* XUserModule::GetProcAddressByOrdinal(uint16_t ordinal) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
X_STATUS XUserModule::GetSection(
|
||||
const char* name,
|
||||
uint32_t* out_section_data, uint32_t* out_section_size) {
|
||||
X_STATUS XUserModule::GetSection(const char* name, uint32_t* out_section_data,
|
||||
uint32_t* out_section_size) {
|
||||
auto header = xe_xex2_get_header(xex_);
|
||||
for (size_t n = 0; n < header->resource_info_count; n++) {
|
||||
auto& res = header->resource_infos[n];
|
||||
@@ -158,12 +150,8 @@ X_STATUS XUserModule::Launch(uint32_t flags) {
|
||||
Dump();
|
||||
|
||||
// Create a thread to run in.
|
||||
XThread* thread = new XThread(
|
||||
kernel_state(),
|
||||
header->exe_stack_size,
|
||||
0,
|
||||
header->exe_entry_point, NULL,
|
||||
0);
|
||||
XThread* thread = new XThread(kernel_state(), header->exe_stack_size, 0,
|
||||
header->exe_entry_point, NULL, 0);
|
||||
|
||||
X_STATUS result = thread->Create();
|
||||
if (XFAILED(result)) {
|
||||
@@ -196,11 +184,10 @@ void XUserModule::Dump() {
|
||||
printf("\n");
|
||||
printf(" Execution Info:\n");
|
||||
printf(" Media ID: %.8X\n", header->execution_info.media_id);
|
||||
printf(" Version: %d.%d.%d.%d\n",
|
||||
header->execution_info.version.major,
|
||||
header->execution_info.version.minor,
|
||||
header->execution_info.version.build,
|
||||
header->execution_info.version.qfe);
|
||||
printf(
|
||||
" Version: %d.%d.%d.%d\n", header->execution_info.version.major,
|
||||
header->execution_info.version.minor,
|
||||
header->execution_info.version.build, header->execution_info.version.qfe);
|
||||
printf(" Base Version: %d.%d.%d.%d\n",
|
||||
header->execution_info.base_version.major,
|
||||
header->execution_info.base_version.minor,
|
||||
@@ -222,14 +209,14 @@ void XUserModule::Dump() {
|
||||
printf(" Slot Count: %d\n", header->tls_info.slot_count);
|
||||
printf(" Data Size: %db\n", header->tls_info.data_size);
|
||||
printf(" Address: %.8X, %db\n", header->tls_info.raw_data_address,
|
||||
header->tls_info.raw_data_size);
|
||||
header->tls_info.raw_data_size);
|
||||
printf("\n");
|
||||
printf(" Headers:\n");
|
||||
for (size_t n = 0; n < header->header_count; n++) {
|
||||
const xe_xex2_opt_header_t* opt_header = &header->headers[n];
|
||||
printf(" %.8X (%.8X, %4db) %.8X = %11d\n",
|
||||
opt_header->key, opt_header->offset, opt_header->length,
|
||||
opt_header->value, opt_header->value);
|
||||
printf(" %.8X (%.8X, %4db) %.8X = %11d\n", opt_header->key,
|
||||
opt_header->offset, opt_header->length, opt_header->value,
|
||||
opt_header->value);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
@@ -237,8 +224,8 @@ void XUserModule::Dump() {
|
||||
printf("Resources:\n");
|
||||
for (size_t n = 0; n < header->resource_info_count; n++) {
|
||||
auto& res = header->resource_infos[n];
|
||||
printf(" %-8s %.8X-%.8X, %db\n",
|
||||
res.name, res.address, res.address + res.size, res.size);
|
||||
printf(" %-8s %.8X-%.8X, %db\n", res.name, res.address,
|
||||
res.address + res.size, res.size);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
@@ -248,23 +235,23 @@ void XUserModule::Dump() {
|
||||
const xe_xex2_section_t* section = &header->sections[n];
|
||||
const char* type = "UNKNOWN";
|
||||
switch (section->info.type) {
|
||||
case XEX_SECTION_CODE:
|
||||
type = "CODE ";
|
||||
break;
|
||||
case XEX_SECTION_DATA:
|
||||
type = "RWDATA ";
|
||||
break;
|
||||
case XEX_SECTION_READONLY_DATA:
|
||||
type = "RODATA ";
|
||||
break;
|
||||
case XEX_SECTION_CODE:
|
||||
type = "CODE ";
|
||||
break;
|
||||
case XEX_SECTION_DATA:
|
||||
type = "RWDATA ";
|
||||
break;
|
||||
case XEX_SECTION_READONLY_DATA:
|
||||
type = "RODATA ";
|
||||
break;
|
||||
}
|
||||
const size_t start_address =
|
||||
header->exe_address + (i * xe_xex2_section_length);
|
||||
const size_t end_address =
|
||||
start_address + (section->info.page_count * xe_xex2_section_length);
|
||||
printf(" %3d %s %3d pages %.8X - %.8X (%d bytes)\n",
|
||||
(int)n, type, section->info.page_count, (int)start_address,
|
||||
(int)end_address, section->info.page_count * xe_xex2_section_length);
|
||||
printf(" %3d %s %3d pages %.8X - %.8X (%d bytes)\n", (int)n, type,
|
||||
section->info.page_count, (int)start_address, (int)end_address,
|
||||
section->info.page_count * xe_xex2_section_length);
|
||||
i += section->info.page_count;
|
||||
}
|
||||
printf("\n");
|
||||
@@ -272,9 +259,8 @@ void XUserModule::Dump() {
|
||||
// Static libraries.
|
||||
printf("Static Libraries:\n");
|
||||
for (size_t n = 0; n < header->static_library_count; n++) {
|
||||
const xe_xex2_static_library_t *library = &header->static_libraries[n];
|
||||
printf(" %-8s : %d.%d.%d.%d\n",
|
||||
library->name, library->major,
|
||||
const xe_xex2_static_library_t* library = &header->static_libraries[n];
|
||||
printf(" %-8s : %d.%d.%d.%d\n", library->name, library->major,
|
||||
library->minor, library->build, library->qfe);
|
||||
}
|
||||
printf("\n");
|
||||
@@ -286,15 +272,15 @@ void XUserModule::Dump() {
|
||||
|
||||
xe_xex2_import_info_t* import_infos;
|
||||
size_t import_info_count;
|
||||
if (!xe_xex2_get_import_infos(xex_, library,
|
||||
&import_infos, &import_info_count)) {
|
||||
if (!xe_xex2_get_import_infos(xex_, library, &import_infos,
|
||||
&import_info_count)) {
|
||||
printf(" %s - %d imports\n", library->name, (int)import_info_count);
|
||||
printf(" Version: %d.%d.%d.%d\n",
|
||||
library->version.major, library->version.minor,
|
||||
library->version.build, library->version.qfe);
|
||||
printf(" Min Version: %d.%d.%d.%d\n",
|
||||
library->min_version.major, library->min_version.minor,
|
||||
library->min_version.build, library->min_version.qfe);
|
||||
printf(" Version: %d.%d.%d.%d\n", library->version.major,
|
||||
library->version.minor, library->version.build,
|
||||
library->version.qfe);
|
||||
printf(" Min Version: %d.%d.%d.%d\n", library->min_version.major,
|
||||
library->min_version.minor, library->min_version.build,
|
||||
library->min_version.qfe);
|
||||
printf("\n");
|
||||
|
||||
// Counts.
|
||||
@@ -323,30 +309,28 @@ void XUserModule::Dump() {
|
||||
(int)(known_count / (float)import_info_count * 100.0f),
|
||||
known_count, unknown_count);
|
||||
printf(" Implemented: %3d%% (%d implemented, %d unimplemented)\n",
|
||||
(int)(impl_count / (float)import_info_count * 100.0f),
|
||||
impl_count, unimpl_count);
|
||||
(int)(impl_count / (float)import_info_count * 100.0f), impl_count,
|
||||
unimpl_count);
|
||||
printf("\n");
|
||||
|
||||
// Listing.
|
||||
for (size_t m = 0; m < import_info_count; m++) {
|
||||
const xe_xex2_import_info_t* info = &import_infos[m];
|
||||
KernelExport* kernel_export = export_resolver->GetExportByOrdinal(
|
||||
library->name, info->ordinal);
|
||||
const char *name = "UNKNOWN";
|
||||
KernelExport* kernel_export =
|
||||
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
||||
const char* name = "UNKNOWN";
|
||||
bool implemented = false;
|
||||
if (kernel_export) {
|
||||
name = kernel_export->name;
|
||||
implemented = kernel_export->is_implemented;
|
||||
}
|
||||
if (kernel_export && kernel_export->type == KernelExport::Variable) {
|
||||
printf(" V %.8X %.3X (%3d) %s %s\n",
|
||||
info->value_address, info->ordinal, info->ordinal,
|
||||
implemented ? " " : "!!", name);
|
||||
printf(" V %.8X %.3X (%3d) %s %s\n", info->value_address,
|
||||
info->ordinal, info->ordinal, implemented ? " " : "!!", name);
|
||||
} else if (info->thunk_address) {
|
||||
printf(" F %.8X %.8X %.3X (%3d) %s %s\n",
|
||||
info->value_address, info->thunk_address, info->ordinal,
|
||||
info->ordinal, implemented ? " " : "!!", name);
|
||||
|
||||
printf(" F %.8X %.8X %.3X (%3d) %s %s\n", info->value_address,
|
||||
info->thunk_address, info->ordinal, info->ordinal,
|
||||
implemented ? " " : "!!", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -359,3 +343,6 @@ void XUserModule::Dump() {
|
||||
printf(" TODO\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -13,16 +13,14 @@
|
||||
#include <xenia/kernel/objects/xmodule.h>
|
||||
|
||||
#include <xenia/export_resolver.h>
|
||||
#include <xenia/xbox.h>
|
||||
#include <xenia/kernel/util/xex2.h>
|
||||
|
||||
#include <xenia/xbox.h>
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
|
||||
class XUserModule : public XModule {
|
||||
public:
|
||||
public:
|
||||
XUserModule(KernelState* kernel_state, const char* path);
|
||||
virtual ~XUserModule();
|
||||
|
||||
@@ -33,23 +31,20 @@ public:
|
||||
X_STATUS LoadFromMemory(const void* addr, const size_t length);
|
||||
|
||||
virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
|
||||
virtual X_STATUS GetSection(
|
||||
const char* name,
|
||||
uint32_t* out_section_data, uint32_t* out_section_size);
|
||||
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
|
||||
uint32_t* out_section_size);
|
||||
|
||||
X_STATUS Launch(uint32_t flags);
|
||||
|
||||
void Dump();
|
||||
|
||||
private:
|
||||
private:
|
||||
int LoadPE();
|
||||
|
||||
xe_xex2_ref xex_;
|
||||
xe_xex2_ref xex_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_KERNEL_XBOXKRNL_XUSER_MODULE_H_
|
||||
|
||||
Reference in New Issue
Block a user