Compare commits

...

5 Commits

Author SHA1 Message Date
Marco Rodolfi 25d11b8d77
Merge d395891fc9 into 55bbb28a80 2025-01-17 09:00:40 +00:00
Marco Rodolfi 55bbb28a80 [threading] Linux fixes on setting an incorrect priority
This call was failing since SCHED_FIFO doesn't support negative priorities, but only positive ones, see third paragraph of scheduling policies: https://man7.org/linux/man-pages/man7/sched.7.html.

Additionally Linux do provice up to 99 levels, but I've limited myself to the required UNIX standard of 32, and split the priority levels evenly from that.

I've also added a couple of rows to debug additional issues in the future like this.
2025-01-17 09:56:43 +01:00
Marco Rodolfi d395891fc9 [filesystem] Moved generic methods to platform independent code 2025-01-17 09:19:41 +01:00
The-Little-Wolf 4d7b30e844 [Xam/XamUser] - Stub XamUserGetOnlineLanguageFromXUID
- Stubs XamUserGetOnlineLanguageFromXUID and have it return cvars::user_language
- Leave notes for future implementation once we have proper profile support
2025-01-17 08:32:46 +01:00
Marco Rodolfi d7ffa408dd [linux_platform] Implement a bunch of missing functions necessaries to make Xenia build correctly under Linux
With this part fixed and a function readapted from the original codebase to fix the different signature, we should have a compiling Linux build now.
2025-01-16 12:26:14 +01:00
7 changed files with 128 additions and 11 deletions

View File

@ -53,4 +53,7 @@ uint64_t Clock::QueryHostUptimeMillis() {
return host_tick_count_platform() * 1000 / host_tick_frequency_platform(); return host_tick_count_platform() * 1000 / host_tick_frequency_platform();
} }
uint64_t Clock::QueryHostInterruptTime() {
return host_tick_count_platform();
}
} // namespace xe } // namespace xe

View File

@ -24,5 +24,28 @@ bool CreateParentFolder(const std::filesystem::path& path) {
return true; return true;
} }
std::vector<FileInfo> ListDirectories(const std::filesystem::path& path) {
std::vector<FileInfo> files = ListFiles(path);
std::vector<FileInfo> directories = {};
std::copy_if(
files.cbegin(), files.cend(), std::back_inserter(directories),
[](const FileInfo& file) { return file.type == FileInfo::Type::kDirectory; });
return std::move(directories);
}
std::vector<FileInfo> FilterByName(const std::vector<FileInfo>& files,
const std::regex pattern) {
std::vector<FileInfo> filtered_entries = {};
std::copy_if(files.cbegin(), files.cend(),
std::back_inserter(filtered_entries), [pattern](const FileInfo& file) {
return std::regex_match(file.name.filename().string(),
pattern);
});
return std::move(filtered_entries);
}
} // namespace filesystem } // namespace filesystem
} // namespace xe } // namespace xe

View File

@ -192,20 +192,27 @@ std::unique_ptr<FileHandle> FileHandle::OpenExisting(
return std::make_unique<PosixFileHandle>(path, handle); return std::make_unique<PosixFileHandle>(path, handle);
} }
bool GetInfo(const std::filesystem::path& path, FileInfo* out_info) { std::optional<FileInfo> GetInfo(const std::filesystem::path& path) {
FileInfo info{};
struct stat st; struct stat st;
if (stat(path.c_str(), &st) == 0) { if (stat(path.c_str(), &st) == 0) {
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
out_info->type = FileInfo::Type::kDirectory; info.type = FileInfo::Type::kDirectory;
// On Linux st.st_size can have non-zero size (generally 4096) so make 0
info.total_size = 0;
} else { } else {
out_info->type = FileInfo::Type::kFile; info.type = FileInfo::Type::kFile;
info.total_size = st.st_size;
} }
out_info->create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime); info.path = path.parent_path();
out_info->access_timestamp = convertUnixtimeToWinFiletime(st.st_atime); info.name = path.filename();
out_info->write_timestamp = convertUnixtimeToWinFiletime(st.st_mtime); info.create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime);
return true; info.access_timestamp = convertUnixtimeToWinFiletime(st.st_atime);
info.write_timestamp = convertUnixtimeToWinFiletime(st.st_mtime);
return std::move(info);
} }
return false; return {};
} }
std::vector<FileInfo> ListFiles(const std::filesystem::path& path) { std::vector<FileInfo> ListFiles(const std::filesystem::path& path) {
@ -240,7 +247,7 @@ std::vector<FileInfo> ListFiles(const std::filesystem::path& path) {
result.push_back(info); result.push_back(info);
} }
closedir(dir); closedir(dir);
return result; return std::move(result);
} }
bool SetAttributes(const std::filesystem::path& path, uint64_t attributes) { bool SetAttributes(const std::filesystem::path& path, uint64_t attributes) {

View File

@ -0,0 +1,46 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2023 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <xbyak/xbyak/xbyak_util.h>
#include "xenia/ui/window_gtk.h"
class StartupCpuFeatureCheck {
public:
StartupCpuFeatureCheck() {
Xbyak::util::Cpu cpu;
const char* error_message = nullptr;
if (!cpu.has(Xbyak::util::Cpu::tAVX)) {
error_message =
"Your CPU does not support AVX, which is required by Xenia. See "
"the "
"FAQ for system requirements at https://xenia.jp";
}
if (error_message == nullptr) {
return;
} else {
GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT;
auto dialog =
gtk_message_dialog_new(nullptr, flags, GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,error_message);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
exit(1);
}
}
};
// This is a hack to get an instance of StartupAvxCheck
// constructed before any initialization code,
// where the AVX check then happens in the constructor.
// Ref:
// https://reviews.llvm.org/D12689#243295
__attribute__((init_priority(101)))
static StartupCpuFeatureCheck gStartupAvxCheck;

View File

@ -402,6 +402,7 @@ class Timer : public WaitHandle {
virtual bool Cancel() = 0; virtual bool Cancel() = 0;
}; };
#if XE_PLATFORM_WINDOWS
struct ThreadPriority { struct ThreadPriority {
static const int32_t kLowest = -2; static const int32_t kLowest = -2;
static const int32_t kBelowNormal = -1; static const int32_t kBelowNormal = -1;
@ -409,6 +410,15 @@ struct ThreadPriority {
static const int32_t kAboveNormal = 1; static const int32_t kAboveNormal = 1;
static const int32_t kHighest = 2; static const int32_t kHighest = 2;
}; };
#else
struct ThreadPriority {
static const int32_t kLowest = 1;
static const int32_t kBelowNormal = 8;
static const int32_t kNormal = 16;
static const int32_t kAboveNormal = 24;
static const int32_t kHighest = 32;
};
#endif
// Models a Win32-like thread object. // Models a Win32-like thread object.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx

View File

@ -27,6 +27,8 @@
#include <ctime> #include <ctime>
#include <memory> #include <memory>
#include "logging.h"
#if XE_PLATFORM_ANDROID #if XE_PLATFORM_ANDROID
#include <dlfcn.h> #include <dlfcn.h>
@ -159,6 +161,10 @@ void Sleep(std::chrono::microseconds duration) {
} while (ret == -1 && errno == EINTR); } while (ret == -1 && errno == EINTR);
} }
void NanoSleep(int64_t duration) {
Sleep(std::chrono::nanoseconds(duration));
}
// TODO(bwrsandman) Implement by allowing alert interrupts from IO operations // TODO(bwrsandman) Implement by allowing alert interrupts from IO operations
thread_local bool alertable_state_ = false; thread_local bool alertable_state_ = false;
SleepResult AlertableSleep(std::chrono::microseconds duration) { SleepResult AlertableSleep(std::chrono::microseconds duration) {
@ -660,8 +666,18 @@ class PosixCondition<Thread> : public PosixConditionBase {
WaitStarted(); WaitStarted();
sched_param param{}; sched_param param{};
param.sched_priority = new_priority; param.sched_priority = new_priority;
if (pthread_setschedparam(thread_, SCHED_FIFO, &param) != 0) int res = pthread_setschedparam(thread_, SCHED_FIFO, &param);
if (res != 0) {
switch (res) {
case EPERM:
XELOGW("Permission denied while setting priority");
break;
case EINVAL:
assert_always(); assert_always();
default:
XELOGW("Unknown error while setting priority");
}
}
} }
void QueueUserCallback(std::function<void()> callback) { void QueueUserCallback(std::function<void()> callback) {

View File

@ -799,6 +799,18 @@ dword_result_t XamUserGetUserFlagsFromXUID_entry(qword_t xuid) {
} }
DECLARE_XAM_EXPORT1(XamUserGetUserFlagsFromXUID, kUserProfiles, kImplemented); DECLARE_XAM_EXPORT1(XamUserGetUserFlagsFromXUID, kUserProfiles, kImplemented);
dword_result_t XamUserGetOnlineLanguageFromXUID_entry(qword_t xuid) {
/* Notes:
- Calls XamUserGetUserFlagsFromXUID and returns (ulonglong)(cached_flag <<
0x20) >> 0x39 & 0x1f;
- XamUserGetMembershipTierFromXUID and XamUserGetOnlineCountryFromXUID also
call it
- Removed in metro
*/
return cvars::user_language;
}
DECLARE_XAM_EXPORT1(XamUserGetOnlineLanguageFromXUID, kUserProfiles, kStub);
constexpr uint8_t kStatsMaxAmount = 64; constexpr uint8_t kStatsMaxAmount = 64;
struct X_STATS_DETAILS { struct X_STATS_DETAILS {