Merge pull request #1696 from Nekotekina/master

Style fix, preparations
This commit is contained in:
Ivan 2016-05-23 16:53:36 +03:00
commit cdefb969ec
370 changed files with 5242 additions and 3825 deletions

View file

@ -1,6 +1,7 @@
#pragma once
#include "types.h"
#include "Platform.h"
// Helper class, provides access to compiler-specific atomic intrinsics
template<typename T, std::size_t Size>
@ -744,9 +745,9 @@ public:
while (true)
{
func(_new = old, args...);
func((_new = old), args...);
if (atomic_storage<type>::compare_exchange(m_data, old, _new)) return old;
if (LIKELY(atomic_storage<type>::compare_exchange(m_data, old, _new))) return old;
}
}
@ -765,9 +766,9 @@ public:
while (true)
{
func(_new = old, args...);
func((_new = old), args...);
if (atomic_storage<type>::compare_exchange(m_data, old, _new)) return _new;
if (LIKELY(atomic_storage<type>::compare_exchange(m_data, old, _new))) return _new;
}
}
@ -786,9 +787,9 @@ public:
while (true)
{
RT&& result = func(_new = old, args...);
RT&& result = func((_new = old), args...);
if (atomic_storage<type>::compare_exchange(m_data, old, _new)) return std::move(result);
if (LIKELY(atomic_storage<type>::compare_exchange(m_data, old, _new))) return std::move(result);
}
}
@ -800,9 +801,9 @@ public:
while (true)
{
func(_new = old, args...);
func((_new = old), args...);
if (atomic_storage<type>::compare_exchange(m_data, old, _new)) return;
if (LIKELY(atomic_storage<type>::compare_exchange(m_data, old, _new))) return;
}
}

View file

@ -1,5 +1,7 @@
#pragma once
#include <unordered_set>
// Regarded as a Debugger Enchantment
namespace debug
{

View file

@ -5,7 +5,7 @@
namespace cfg
{
_log::channel cfg("CFG", _log::level::notice);
logs::channel cfg("CFG", logs::level::notice);
entry_base::entry_base(type _type)
: m_type(_type)

View file

@ -179,7 +179,7 @@ namespace cfg
for (const auto& v : init)
{
// Ensure elements are unique
ASSERT(map.emplace(v.first, v.second).second);
VERIFY(map.emplace(v.first, v.second).second);
}
return map;
@ -529,4 +529,4 @@ namespace cfg
}
// Registered log channel
#define LOG_CHANNEL(name) _log::channel name(#name, _log::level::notice); namespace _log { cfg::enum_entry<_log::level, true> name(cfg::root.log, #name, ::name.enabled); }
#define LOG_CHANNEL(name) extern logs::channel name; namespace logs { static cfg::enum_entry<logs::level, true> name(cfg::root.log, #name, ::name.enabled); }

View file

@ -69,6 +69,19 @@ static time_t to_time(const FILETIME& ft)
return to_time(v);
}
static fs::error to_error(DWORD e)
{
switch (e)
{
case ERROR_FILE_NOT_FOUND: return fs::error::noent;
case ERROR_PATH_NOT_FOUND: return fs::error::noent;
case ERROR_ALREADY_EXISTS: return fs::error::exist;
case ERROR_FILE_EXISTS: return fs::error::exist;
case ERROR_NEGATIVE_SEEK: return fs::error::inval;
default: throw fmt::exception("Unknown Win32 error: %u.", e);
}
}
#else
#include <sys/mman.h>
@ -87,11 +100,22 @@ static time_t to_time(const FILETIME& ft)
#include <sys/sendfile.h>
#endif
static fs::error to_error(int e)
{
switch (e)
{
case ENOENT: return fs::error::noent;
case EEXIST: return fs::error::exist;
case EINVAL: return fs::error::inval;
default: throw fmt::exception("Unknown system error: %d.", e);
}
}
#endif
namespace fs
{
thread_local uint error = 0;
thread_local error g_tls_error = error::ok;
class device_manager final
{
@ -146,7 +170,7 @@ std::shared_ptr<fs::device_base> fs::get_virtual_device(const std::string& path)
std::shared_ptr<fs::device_base> fs::set_virtual_device(const std::string& name, const std::shared_ptr<device_base>& device)
{
Expects(name.size() > 2 && name[0] == '/' && name[1] == '/' && name.find('/', 2) == -1);
EXPECTS(name.size() > 2 && name[0] == '/' && name[1] == '/' && name.find('/', 2) == -1);
return get_device_manager().set_device(name, device);
}
@ -178,26 +202,26 @@ std::string fs::get_parent_dir(const std::string& path)
static const auto test_get_parent_dir = []() -> bool
{
// Success:
ASSERT(fs::get_parent_dir("/x/y///") == "/x");
ASSERT(fs::get_parent_dir("/x/y/") == "/x");
ASSERT(fs::get_parent_dir("/x/y") == "/x");
ASSERT(fs::get_parent_dir("x:/y") == "x:");
ASSERT(fs::get_parent_dir("//x/y") == "//x");
VERIFY(fs::get_parent_dir("/x/y///") == "/x");
VERIFY(fs::get_parent_dir("/x/y/") == "/x");
VERIFY(fs::get_parent_dir("/x/y") == "/x");
VERIFY(fs::get_parent_dir("x:/y") == "x:");
VERIFY(fs::get_parent_dir("//x/y") == "//x");
// Failure:
ASSERT(fs::get_parent_dir("").empty());
ASSERT(fs::get_parent_dir("x/").empty());
ASSERT(fs::get_parent_dir("x").empty());
ASSERT(fs::get_parent_dir("x///").empty());
ASSERT(fs::get_parent_dir("/x/").empty());
ASSERT(fs::get_parent_dir("/x").empty());
ASSERT(fs::get_parent_dir("/").empty());
ASSERT(fs::get_parent_dir("//").empty());
ASSERT(fs::get_parent_dir("//x").empty());
ASSERT(fs::get_parent_dir("//x/").empty());
ASSERT(fs::get_parent_dir("///").empty());
ASSERT(fs::get_parent_dir("///x").empty());
ASSERT(fs::get_parent_dir("///x/").empty());
VERIFY(fs::get_parent_dir("").empty());
VERIFY(fs::get_parent_dir("x/").empty());
VERIFY(fs::get_parent_dir("x").empty());
VERIFY(fs::get_parent_dir("x///").empty());
VERIFY(fs::get_parent_dir("/x/").empty());
VERIFY(fs::get_parent_dir("/x").empty());
VERIFY(fs::get_parent_dir("/").empty());
VERIFY(fs::get_parent_dir("//").empty());
VERIFY(fs::get_parent_dir("//x").empty());
VERIFY(fs::get_parent_dir("//x/").empty());
VERIFY(fs::get_parent_dir("///").empty());
VERIFY(fs::get_parent_dir("///x").empty());
VERIFY(fs::get_parent_dir("///x/").empty());
return false;
}();
@ -213,14 +237,7 @@ bool fs::stat(const std::string& path, stat_t& info)
WIN32_FILE_ATTRIBUTE_DATA attrs;
if (!GetFileAttributesExW(to_wchar(path).get(), GetFileExInfoStandard, &attrs))
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
}
g_tls_error = to_error(GetLastError());
return false;
}
@ -234,7 +251,7 @@ bool fs::stat(const std::string& path, stat_t& info)
struct ::stat file_info;
if (::stat(path.c_str(), &file_info) != 0)
{
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
@ -260,14 +277,7 @@ bool fs::exists(const std::string& path)
#ifdef _WIN32
if (GetFileAttributesW(to_wchar(path).get()) == INVALID_FILE_ATTRIBUTES)
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
}
g_tls_error = to_error(GetLastError());
return false;
}
@ -276,7 +286,7 @@ bool fs::exists(const std::string& path)
struct ::stat file_info;
if (::stat(path.c_str(), &file_info) != 0)
{
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
@ -296,7 +306,7 @@ bool fs::is_file(const std::string& path)
if (info.is_directory)
{
fs::error = EEXIST;
g_tls_error = error::exist;
return false;
}
@ -307,21 +317,14 @@ bool fs::is_file(const std::string& path)
const DWORD attrs = GetFileAttributesW(to_wchar(path).get());
if (attrs == INVALID_FILE_ATTRIBUTES)
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
}
g_tls_error = to_error(GetLastError());
return false;
}
#else
struct ::stat file_info;
if (::stat(path.c_str(), &file_info) != 0)
{
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
#endif
@ -333,7 +336,7 @@ bool fs::is_file(const std::string& path)
if (S_ISDIR(file_info.st_mode))
#endif
{
fs::error = EEXIST;
g_tls_error = error::exist;
return false;
}
@ -352,7 +355,7 @@ bool fs::is_dir(const std::string& path)
if (info.is_directory == false)
{
fs::error = EEXIST;
g_tls_error = error::exist;
return false;
}
@ -363,21 +366,14 @@ bool fs::is_dir(const std::string& path)
const DWORD attrs = GetFileAttributesW(to_wchar(path).get());
if (attrs == INVALID_FILE_ATTRIBUTES)
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
}
g_tls_error = to_error(GetLastError());
return false;
}
#else
struct ::stat file_info;
if (::stat(path.c_str(), &file_info) != 0)
{
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
#endif
@ -388,7 +384,7 @@ bool fs::is_dir(const std::string& path)
if (!S_ISDIR(file_info.st_mode))
#endif
{
fs::error = EEXIST;
g_tls_error = error::exist;
return false;
}
@ -405,14 +401,7 @@ bool fs::create_dir(const std::string& path)
#ifdef _WIN32
if (!CreateDirectoryW(to_wchar(path).get(), NULL))
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_ALREADY_EXISTS: fs::error = EEXIST; break;
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
}
g_tls_error = to_error(GetLastError());
return false;
}
@ -420,7 +409,7 @@ bool fs::create_dir(const std::string& path)
#else
if (::mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0)
{
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
@ -450,13 +439,7 @@ bool fs::remove_dir(const std::string& path)
#ifdef _WIN32
if (!RemoveDirectoryW(to_wchar(path).get()))
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
}
g_tls_error = to_error(GetLastError());
return false;
}
@ -464,7 +447,7 @@ bool fs::remove_dir(const std::string& path)
#else
if (::rmdir(path.c_str()) != 0)
{
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
@ -489,13 +472,7 @@ bool fs::rename(const std::string& from, const std::string& to)
#ifdef _WIN32
if (!MoveFileW(to_wchar(from).get(), to_wchar(to).get()))
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u.\nFrom: %s\nTo: %s" HERE, error, from, to);
}
g_tls_error = to_error(GetLastError());
return false;
}
@ -503,7 +480,7 @@ bool fs::rename(const std::string& from, const std::string& to)
#else
if (::rename(from.c_str(), to.c_str()) != 0)
{
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
@ -523,13 +500,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
#ifdef _WIN32
if (!CopyFileW(to_wchar(from).get(), to_wchar(to).get(), !overwrite))
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u.\nFrom: %s\nTo: %s" HERE, error, from, to);
}
g_tls_error = to_error(GetLastError());
return false;
}
@ -540,7 +511,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
const int input = ::open(from.c_str(), O_RDONLY);
if (input == -1)
{
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
@ -550,7 +521,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
const int err = errno;
::close(input);
fs::error = err;
g_tls_error = to_error(err);
return false;
}
@ -569,7 +540,7 @@ bool fs::copy_file(const std::string& from, const std::string& to, bool overwrit
::close(input);
::close(output);
fs::error = err;
g_tls_error = to_error(err);
return false;
}
@ -589,14 +560,7 @@ bool fs::remove_file(const std::string& path)
#ifdef _WIN32
if (!DeleteFileW(to_wchar(path).get()))
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
}
g_tls_error = to_error(GetLastError());
return false;
}
@ -604,7 +568,7 @@ bool fs::remove_file(const std::string& path)
#else
if (::unlink(path.c_str()) != 0)
{
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
@ -624,14 +588,7 @@ bool fs::truncate_file(const std::string& path, u64 length)
const auto handle = CreateFileW(to_wchar(path).get(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE)
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
}
g_tls_error = to_error(GetLastError());
return false;
}
@ -641,13 +598,7 @@ bool fs::truncate_file(const std::string& path, u64 length)
// Seek and truncate
if (!SetFilePointerEx(handle, distance, NULL, FILE_BEGIN) || !SetEndOfFile(handle))
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_NEGATIVE_SEEK: fs::error = EINVAL; break;
default: throw fmt::exception("Unknown Win32 error: %u (length=0x%llx)." HERE, error, length);
}
g_tls_error = to_error(GetLastError());
CloseHandle(handle);
return false;
}
@ -657,7 +608,7 @@ bool fs::truncate_file(const std::string& path, u64 length)
#else
if (::truncate(path.c_str(), length) != 0)
{
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
@ -672,7 +623,7 @@ void fs::file::xnull() const
void fs::file::xfail() const
{
throw fmt::exception("Unexpected fs::file error %u", fs::error);
throw fmt::exception("Unexpected fs::error %u", g_tls_error);
}
bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
@ -704,7 +655,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
{
if (mode & fs::excl)
{
fs::error = EINVAL;
g_tls_error = error::inval;
return false;
}
@ -715,15 +666,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
if (handle == INVALID_HANDLE_VALUE)
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
case ERROR_FILE_EXISTS: fs::error = EEXIST; break;
default: throw fmt::exception("Unknown Win32 error: %u (%s)." HERE, error, path);
}
g_tls_error = to_error(GetLastError());
return false;
}
@ -747,12 +690,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
FILE_BASIC_INFO basic_info;
if (!GetFileInformationByHandleEx(m_handle, FileBasicInfo, &basic_info, sizeof(FILE_BASIC_INFO)))
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case 0:
default: throw fmt::exception("Win32 error: %u." HERE, error);
}
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
stat_t info;
@ -773,47 +711,22 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
pos.QuadPart = 0;
if (!SetFilePointerEx(m_handle, pos, &old, FILE_CURRENT)) // get old position
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case 0:
default: throw fmt::exception("Unknown Win32 error: %u." HERE, error);
}
g_tls_error = to_error(GetLastError());
return false;
}
pos.QuadPart = length;
if (!SetFilePointerEx(m_handle, pos, NULL, FILE_BEGIN)) // set new position
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_NEGATIVE_SEEK: fs::error = EINVAL; break;
default: throw fmt::exception("Unknown Win32 error: %u." HERE, error);
}
g_tls_error = to_error(GetLastError());
return false;
}
const BOOL result = SetEndOfFile(m_handle); // change file size
if (!result)
if (!result || !SetFilePointerEx(m_handle, old, NULL, FILE_BEGIN)) // restore position
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case 0:
default: throw fmt::exception("Unknown Win32 error: %u." HERE, error);
}
}
if (!SetFilePointerEx(m_handle, old, NULL, FILE_BEGIN) && result) // restore position
{
if (DWORD error = GetLastError())
{
throw fmt::exception("Win32 error: %u." HERE, error);
}
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
return result != FALSE;
@ -823,16 +736,12 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
{
// TODO (call ReadFile multiple times if count is too big)
const int size = ::narrow<int>(count, "Too big count" HERE);
Expects(size >= 0);
EXPECTS(size >= 0);
DWORD nread;
if (!ReadFile(m_handle, buffer, size, &nread, NULL))
{
switch (DWORD error = GetLastError())
{
case 0:
default: throw fmt::exception("Win32 error: %u." HERE, error);
}
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
return nread;
@ -842,16 +751,12 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
{
// TODO (call WriteFile multiple times if count is too big)
const int size = ::narrow<int>(count, "Too big count" HERE);
Expects(size >= 0);
EXPECTS(size >= 0);
DWORD nwritten;
if (!WriteFile(m_handle, buffer, size, &nwritten, NULL))
{
switch (DWORD error = GetLastError())
{
case 0:
default: throw fmt::exception("Win32 error: %u." HERE, error);
}
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
return nwritten;
@ -870,11 +775,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
if (!SetFilePointerEx(m_handle, pos, &pos, mode))
{
switch (DWORD error = GetLastError())
{
case 0:
default: throw fmt::exception("Win32 error: %u." HERE, error);
}
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
return pos.QuadPart;
@ -885,11 +786,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
LARGE_INTEGER size;
if (!GetFileSizeEx(m_handle, &size))
{
switch (DWORD error = GetLastError())
{
case 0:
default: throw fmt::exception("Win32 error: %u." HERE, error);
}
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
return size.QuadPart;
@ -913,8 +810,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
if (fd == -1)
{
// TODO: errno
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
@ -938,11 +834,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
struct ::stat file_info;
if (::fstat(m_fd, &file_info) != 0)
{
switch (int error = errno)
{
case 0:
default: throw fmt::exception("Unknown error: %d." HERE, error);
}
throw fmt::exception("System error: %d." HERE, errno);
}
stat_t info;
@ -960,12 +852,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
{
if (::ftruncate(m_fd, length) != 0)
{
switch (int error = errno)
{
case 0:
default: throw fmt::exception("Unknown error: %d." HERE, error);
}
g_tls_error = to_error(errno);
return false;
}
@ -977,11 +864,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
const auto result = ::read(m_fd, buffer, count);
if (result == -1)
{
switch (int error = errno)
{
case 0:
default: throw fmt::exception("Unknown error: %d." HERE, error);
}
throw fmt::exception("System error: %d." HERE, errno);
}
return result;
@ -992,11 +875,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
const auto result = ::write(m_fd, buffer, count);
if (result == -1)
{
switch (int error = errno)
{
case 0:
default: throw fmt::exception("Unknown error: %d." HERE, error);
}
throw fmt::exception("System error: %d." HERE, errno);
}
return result;
@ -1013,11 +892,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
const auto result = ::lseek(m_fd, offset, mode);
if (result == -1)
{
switch (int error = errno)
{
case 0:
default: throw fmt::exception("Unknown error: %d." HERE, error);
}
throw fmt::exception("System error: %d." HERE, errno);
}
return result;
@ -1028,11 +903,7 @@ bool fs::file::open(const std::string& path, bitset_t<open_mode> mode)
struct ::stat file_info;
if (::fstat(m_fd, &file_info) != 0)
{
switch (int error = errno)
{
case 0:
default: throw fmt::exception("Unknown error: %d." HERE, error);
}
throw fmt::exception("System error: %d." HERE, errno);
}
return file_info.st_size;
@ -1049,7 +920,7 @@ fs::file::file(const void* ptr, std::size_t size)
{
class memory_stream : public file_base
{
u64 m_pos{}; // TODO: read/seek could modify m_pos atomically
u64 m_pos{};
const char* const m_ptr;
const u64 m_size;
@ -1063,26 +934,26 @@ fs::file::file(const void* ptr, std::size_t size)
fs::stat_t stat() override
{
throw std::logic_error("memory_stream doesn't support stat()");
throw std::logic_error("Not supported" HERE);
}
bool trunc(u64 length) override
{
throw std::logic_error("memory_stream doesn't support trunc()");
throw std::logic_error("Not allowed" HERE);
}
u64 read(void* buffer, u64 count) override
{
const u64 start = m_pos;
const u64 end = seek(count, fs::seek_cur);
const u64 read_size = end >= start ? end - start : throw std::logic_error("memory_stream::read(): overflow");
const u64 read_size = end >= start ? end - start : throw std::logic_error("Stream overflow" HERE);
std::memcpy(buffer, m_ptr + start, read_size);
return read_size;
}
u64 write(const void* buffer, u64 count) override
{
throw std::logic_error("memory_stream is not writable");
throw std::logic_error("Not allowed" HERE);
}
u64 seek(s64 offset, fs::seek_mode whence) override
@ -1091,7 +962,7 @@ fs::file::file(const void* ptr, std::size_t size)
whence == fs::seek_set ? m_pos = std::min<u64>(offset, m_size) :
whence == fs::seek_cur ? m_pos = std::min<u64>(offset + m_pos, m_size) :
whence == fs::seek_end ? m_pos = std::min<u64>(offset + m_size, m_size) :
throw std::logic_error("memory_stream::seek(): invalid whence");
throw fmt::exception("Invalid whence (0x%x)" HERE, whence);
}
u64 size() override
@ -1127,14 +998,7 @@ bool fs::dir::open(const std::string& path)
if (handle == INVALID_HANDLE_VALUE)
{
// TODO: convert Win32 error code to errno
switch (DWORD error = GetLastError())
{
case ERROR_FILE_NOT_FOUND: fs::error = ENOENT; break;
case ERROR_PATH_NOT_FOUND: fs::error = ENOENT; break;
default: throw fmt::exception("Unknown Win32 error: %u." HERE, error);
}
g_tls_error = to_error(GetLastError());
return false;
}
@ -1179,11 +1043,12 @@ bool fs::dir::open(const std::string& path)
WIN32_FIND_DATAW found;
if (!FindNextFileW(m_handle, &found))
{
switch (DWORD error = GetLastError())
if (ERROR_NO_MORE_FILES == GetLastError())
{
case ERROR_NO_MORE_FILES: return false;
default: throw fmt::exception("Unknown Win32 error: %u." HERE, error);
return false;
}
throw fmt::exception("Win32 error: %u." HERE, GetLastError());
}
add_entry(found);
@ -1205,8 +1070,7 @@ bool fs::dir::open(const std::string& path)
if (!ptr)
{
// TODO: errno
fs::error = errno;
g_tls_error = to_error(errno);
return false;
}
@ -1236,11 +1100,7 @@ bool fs::dir::open(const std::string& path)
struct ::stat file_info;
if (::fstatat(::dirfd(m_dd), found->d_name, &file_info, 0) != 0)
{
switch (int error = errno)
{
case 0:
default: throw fmt::exception("Unknown error: %d." HERE, error);
}
throw fmt::exception("System error: %d." HERE, errno);
}
info.name = found->d_name;

View file

@ -10,9 +10,6 @@
namespace fs
{
// Error code returned
extern thread_local uint error;
// File open mode flags
enum struct open_mode : u32
{
@ -265,6 +262,13 @@ namespace fs
return read(&str[0], str.size()) == str.size();
}
// Read std::string
bool read(std::string& str, std::size_t size) const
{
str.resize(size);
return read(&str[0], size) == size;
}
// Read POD, sizeof(T) is used
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, bool> read(T& data) const
@ -279,6 +283,14 @@ namespace fs
return read(vec.data(), sizeof(T) * vec.size()) == sizeof(T) * vec.size();
}
// Read POD std::vector
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, bool> read(std::vector<T>& vec, std::size_t size) const
{
vec.resize(size);
return read(vec.data(), sizeof(T) * size) == sizeof(T) * size;
}
// Read POD (experimental)
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, T> read() const
@ -432,4 +444,16 @@ namespace fs
// Get size of all files recursively
u64 get_dir_size(const std::string& path);
enum class error : uint
{
ok = 0,
inval,
noent,
exist,
};
// Error code returned
extern thread_local error g_tls_error;
}

View file

@ -3,12 +3,8 @@
#define GSL_THROW_ON_CONTRACT_VIOLATION
#pragma push_macro("new")
#pragma push_macro("Expects")
#pragma push_macro("Ensures")
#undef new
#include <gsl.h>
#pragma pop_macro("new")
#undef Expects
#undef Ensures
#include <gsl.h>
#pragma pop_macro("Ensures")
#pragma pop_macro("Expects")
#pragma pop_macro("new")

View file

@ -8,7 +8,11 @@
// Thread-specific log prefix provider
thread_local std::string(*g_tls_log_prefix)() = nullptr;
namespace _log
#ifndef _MSC_VER
constexpr DECLARE(bijective<logs::level, const char*>::map);
#endif
namespace logs
{
struct listener
{
@ -65,7 +69,7 @@ namespace _log
channel ARMv7("ARMv7");
}
void _log::channel::broadcast(const _log::channel& ch, _log::level sev, const char* fmt...)
void logs::channel::broadcast(const logs::channel& ch, logs::level sev, const char* fmt...)
{
va_list args;
va_start(args, fmt);
@ -75,13 +79,13 @@ void _log::channel::broadcast(const _log::channel& ch, _log::level sev, const ch
[[noreturn]] extern void catch_all_exceptions();
_log::file_writer::file_writer(const std::string& name)
logs::file_writer::file_writer(const std::string& name)
{
try
{
if (!m_file.open(fs::get_config_dir() + name, fs::rewrite + fs::append))
{
throw fmt::exception("Can't create log file %s (error %d)", name, fs::error);
throw fmt::exception("Can't create log file %s (error %d)", name, fs::g_tls_error);
}
}
catch (...)
@ -90,17 +94,17 @@ _log::file_writer::file_writer(const std::string& name)
}
}
void _log::file_writer::log(const std::string& text)
void logs::file_writer::log(const std::string& text)
{
m_file.write(text);
}
std::size_t _log::file_writer::size() const
std::size_t logs::file_writer::size() const
{
return m_file.pos();
}
void _log::file_listener::log(const _log::channel& ch, _log::level sev, const std::string& text)
void logs::file_listener::log(const logs::channel& ch, logs::level sev, const std::string& text)
{
std::string msg; msg.reserve(text.size() + 200);

View file

@ -3,7 +3,7 @@
#include "types.h"
#include "Atomic.h"
namespace _log
namespace logs
{
enum class level : uint
{
@ -79,27 +79,27 @@ namespace _log
}
template<>
struct bijective<_log::level, const char*>
struct bijective<logs::level, const char*>
{
static constexpr bijective_pair<_log::level, const char*> map[]
static constexpr bijective_pair<logs::level, const char*> map[]
{
{ _log::level::always, "Nothing" },
{ _log::level::fatal, "Fatal" },
{ _log::level::error, "Error" },
{ _log::level::todo, "TODO" },
{ _log::level::success, "Success" },
{ _log::level::warning, "Warning" },
{ _log::level::notice, "Notice" },
{ _log::level::trace, "Trace" },
{ logs::level::always, "Nothing" },
{ logs::level::fatal, "Fatal" },
{ logs::level::error, "Error" },
{ logs::level::todo, "TODO" },
{ logs::level::success, "Success" },
{ logs::level::warning, "Warning" },
{ logs::level::notice, "Notice" },
{ logs::level::trace, "Trace" },
};
};
// Legacy:
#define LOG_SUCCESS(ch, fmt, ...) _log::ch.success(fmt, ##__VA_ARGS__)
#define LOG_NOTICE(ch, fmt, ...) _log::ch.notice (fmt, ##__VA_ARGS__)
#define LOG_WARNING(ch, fmt, ...) _log::ch.warning(fmt, ##__VA_ARGS__)
#define LOG_ERROR(ch, fmt, ...) _log::ch.error (fmt, ##__VA_ARGS__)
#define LOG_TODO(ch, fmt, ...) _log::ch.todo (fmt, ##__VA_ARGS__)
#define LOG_TRACE(ch, fmt, ...) _log::ch.trace (fmt, ##__VA_ARGS__)
#define LOG_FATAL(ch, fmt, ...) _log::ch.fatal (fmt, ##__VA_ARGS__)
#define LOG_SUCCESS(ch, fmt, ...) logs::ch.success(fmt, ##__VA_ARGS__)
#define LOG_NOTICE(ch, fmt, ...) logs::ch.notice (fmt, ##__VA_ARGS__)
#define LOG_WARNING(ch, fmt, ...) logs::ch.warning(fmt, ##__VA_ARGS__)
#define LOG_ERROR(ch, fmt, ...) logs::ch.error (fmt, ##__VA_ARGS__)
#define LOG_TODO(ch, fmt, ...) logs::ch.todo (fmt, ##__VA_ARGS__)
#define LOG_TRACE(ch, fmt, ...) logs::ch.trace (fmt, ##__VA_ARGS__)
#define LOG_FATAL(ch, fmt, ...) logs::ch.fatal (fmt, ##__VA_ARGS__)

View file

@ -41,6 +41,7 @@ constexpr std::uint32_t size32(const T(&)[Size])
#define CHECK_ALIGN(type, align) static_assert(alignof(type) == align, "Invalid " #type " type alignment")
#define CHECK_MAX_SIZE(type, size) static_assert(sizeof(type) <= size, #type " type size is too big")
#define CHECK_SIZE_ALIGN(type, size, align) CHECK_SIZE(type, size); CHECK_ALIGN(type, align)
#define CHECK_STORAGE(type, storage) static_assert(sizeof(type) <= sizeof(storage) && alignof(type) <= alignof(decltype(storage)), #type " is too small")
// Return 32 bit sizeof() to avoid widening/narrowing conversions with size_t
#define SIZE_32(type) static_cast<std::uint32_t>(sizeof(type))
@ -60,20 +61,22 @@ constexpr std::uint32_t size32(const T(&)[Size])
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
// Macro set, allows to hide "return" in simple lambda expressions.
// Macro set, wraps an expression into lambda
#define WRAP_EXPR(expr, ...) [&](__VA_ARGS__) { return expr; }
#define COPY_EXPR(expr, ...) [=](__VA_ARGS__) { return expr; }
#define PURE_EXPR(expr, ...) [] (__VA_ARGS__) { return expr; }
#define return_ return
#define HERE "\n(in file " __FILE__ ":" STRINGIZE(__LINE__) ")"
// Ensure that the expression is evaluated to true. Always evaluated and allowed to have side effects (unlike assert() macro).
#define ASSERT(expr) if (!(expr)) throw std::runtime_error("Assertion failed: " #expr HERE)
#define VERIFY(expr) do { if (!(expr)) throw std::runtime_error("Verification failed: " #expr HERE); } while (0)
// Expects() and Ensures() are intended to check function arguments and results.
// Expressions are not guaranteed to evaluate. Redefinition with ASSERT macro for better unification.
#define Expects ASSERT
#define Ensures ASSERT
// EXPECTS() and ENSURES() are intended to check function arguments and results.
// Expressions are not guaranteed to evaluate.
#define EXPECTS(expr) do { if (!(expr)) throw std::runtime_error("Precondition failed: " #expr HERE); } while (0)
#define ENSURES(expr) do { if (!(expr)) throw std::runtime_error("Postcondition failed: " #expr HERE); } while (0)
#define DECLARE(...) decltype(__VA_ARGS__) __VA_ARGS__

View file

@ -35,7 +35,7 @@ public:
bool try_wait()
{
return LIKELY(m_value.compare_and_swap_test(1, 0));
return m_value.compare_and_swap_test(1, 0);
}
void post()

View file

@ -140,6 +140,34 @@ void shared_mutex::unlock_notify()
}
}
void shared_mutex::lock_upgrade_hard()
{
unlock_shared();
lock();
}
void shared_mutex::lock_degrade_hard()
{
initialize_once();
std::unique_lock<std::mutex> lock(m_data->mutex);
m_ctrl -= SM_WRITER_LOCK - 1;
if (m_data->rq_size)
{
// Notify all readers
lock.unlock();
m_data->rcv.notify_all();
}
else if (m_data->wq_size)
{
// Notify next exclusive owner
lock.unlock();
m_data->wcv.notify_one();
}
}
void shared_mutex::initialize_once()
{
if (UNLIKELY(!m_data))

View file

@ -32,6 +32,9 @@ class shared_mutex final
void lock_hard();
void unlock_notify();
void lock_upgrade_hard();
void lock_degrade_hard();
public:
constexpr shared_mutex() = default;
@ -42,15 +45,9 @@ public:
bool try_lock_shared()
{
auto ctrl = m_ctrl.load();
const u32 ctrl = m_ctrl.load();
if (UNLIKELY(ctrl >= SM_READER_MAX))
{
ctrl = 0;
}
// Weak attempt
return LIKELY(m_ctrl.compare_and_swap_test(ctrl, ctrl + 1));
return ctrl < SM_READER_MAX && m_ctrl.compare_and_swap_test(ctrl, ctrl + 1);
}
void lock_shared()
@ -72,12 +69,12 @@ public:
bool try_lock()
{
return LIKELY(m_ctrl.compare_and_swap_test(0, SM_WRITER_LOCK));
return !m_ctrl && m_ctrl.compare_and_swap_test(0, SM_WRITER_LOCK);
}
void lock()
{
if (UNLIKELY(!try_lock()))
if (UNLIKELY(!m_ctrl.compare_and_swap_test(0, SM_WRITER_LOCK)))
{
lock_hard();
}
@ -85,11 +82,39 @@ public:
void unlock()
{
if (UNLIKELY(m_ctrl.fetch_sub(SM_WRITER_LOCK) != SM_WRITER_LOCK))
m_ctrl &= ~SM_WRITER_LOCK;
if (UNLIKELY(m_ctrl))
{
unlock_notify();
}
}
bool try_lock_upgrade()
{
return m_ctrl == 1 && m_ctrl.compare_and_swap_test(1, SM_WRITER_LOCK);
}
bool try_lock_degrade()
{
return m_ctrl == SM_WRITER_LOCK && m_ctrl.compare_and_swap_test(SM_WRITER_LOCK, 1);
}
void lock_upgrade()
{
if (UNLIKELY(!m_ctrl.compare_and_swap_test(1, SM_WRITER_LOCK)))
{
lock_upgrade_hard();
}
}
void lock_degrade()
{
if (UNLIKELY(!m_ctrl.compare_and_swap_test(SM_WRITER_LOCK, 1)))
{
lock_degrade_hard();
}
}
};
//! Simplified shared (reader) lock implementation.
@ -133,3 +158,23 @@ public:
m_mutex.unlock();
}
};
// Exclusive (writer) lock in the scope of shared (reader) lock.
class upgraded_lock final
{
shared_mutex& m_mutex;
public:
upgraded_lock(const writer_lock&) = delete;
upgraded_lock(shared_mutex& mutex)
: m_mutex(mutex)
{
m_mutex.lock_upgrade();
}
~upgraded_lock()
{
m_mutex.lock_degrade();
}
};

View file

@ -59,17 +59,27 @@ public:
// Remove thread from the sleep queue
void leave()
{
auto it = std::find(m_queue.begin(), m_queue.end(), &m_thread);
if (it != m_queue.end())
for (auto it = m_queue.begin(), end = m_queue.end(); it != end; it++)
{
m_queue.erase(it);
if (*it == &m_thread)
{
m_queue.erase(it);
return;
}
}
}
// Check whether the thread exists in the sleep queue
explicit operator bool() const
{
return std::find(m_queue.begin(), m_queue.end(), &m_thread) != m_queue.end();
for (auto it = m_queue.begin(), end = m_queue.end(); it != end; it++)
{
if (*it == &m_thread)
{
return true;
}
}
return false;
}
};

View file

@ -5,6 +5,7 @@
#include <cassert>
#include <array>
#include <memory>
#include <algorithm>
std::string v128::to_hex() const
{

View file

@ -1,8 +1,8 @@
#pragma once
#include <cstdarg>
#include <string>
#include <exception>
#include <string>
#include "Platform.h"
#include "types.h"
@ -14,7 +14,7 @@ namespace fmt
// Formatting function
template<typename... Args>
inline std::string format(const char* fmt, const Args&... args) noexcept
inline std::string format(const char* fmt, const Args&... args)
{
return unsafe_format(fmt, ::unveil<Args>::get(args)...);
}
@ -34,7 +34,6 @@ namespace fmt
class exception : public exception_base
{
public:
// Formatting constructor
template<typename... Args>
exception(const char* fmt, const Args&... args)
: exception_base(fmt, ::unveil<Args>::get(args)...)

View file

@ -1263,9 +1263,11 @@ const bool s_self_test = []() -> bool
return true;
}();
#include <thread>
#include <mutex>
#include <condition_variable>
#include <exception>
#include <chrono>
thread_local DECLARE(thread_ctrl::g_tls_this_thread) = nullptr;
@ -1278,17 +1280,20 @@ struct thread_ctrl::internal
task_stack atexit;
std::exception_ptr exception; // Caught exception
std::chrono::high_resolution_clock::time_point time_limit;
};
// Temporarily until better interface is implemented
extern std::condition_variable& get_current_thread_cv()
{
return thread_ctrl::get_current()->get_data()->cond;
}
thread_local thread_ctrl::internal* g_tls_internal = nullptr;
extern std::mutex& get_current_thread_mutex()
{
return thread_ctrl::get_current()->get_data()->mutex;
return g_tls_internal->mutex;
}
extern std::condition_variable& get_current_thread_cv()
{
return g_tls_internal->cond;
}
// TODO
@ -1296,10 +1301,64 @@ extern atomic_t<u32> g_thread_count(0);
extern thread_local std::string(*g_tls_log_prefix)();
void thread_ctrl::start(const std::shared_ptr<thread_ctrl>& ctrl, task_stack task)
{
reinterpret_cast<std::thread&>(ctrl->m_thread) = std::thread([ctrl, task = std::move(task)]
{
try
{
ctrl->initialize();
task.exec();
}
catch (...)
{
ctrl->initialize_once();
ctrl->m_data->exception = std::current_exception();
}
ctrl->finalize();
});
}
void thread_ctrl::wait_start(u64 timeout)
{
initialize_once();
m_data->time_limit = std::chrono::high_resolution_clock::now() + std::chrono::microseconds(timeout);
}
bool thread_ctrl::wait_wait(u64 timeout)
{
initialize_once();
std::unique_lock<std::mutex> lock(m_data->mutex, std::adopt_lock);
if (timeout && m_data->cond.wait_until(lock, m_data->time_limit) == std::cv_status::timeout)
{
lock.release();
return false;
}
m_data->cond.wait(lock);
lock.release();
return true;
}
void thread_ctrl::test()
{
if (m_data && m_data->exception)
{
std::rethrow_exception(m_data->exception);
}
}
void thread_ctrl::initialize()
{
initialize_once(); // TODO (temporarily)
// Initialize TLS variable
g_tls_this_thread = this;
g_tls_internal = this->m_data;
g_tls_log_prefix = []
{
@ -1339,12 +1398,6 @@ void thread_ctrl::initialize()
#endif
}
void thread_ctrl::set_exception() noexcept
{
initialize_once();
m_data->exception = std::current_exception();
}
void thread_ctrl::finalize() noexcept
{
// TODO
@ -1355,30 +1408,43 @@ void thread_ctrl::finalize() noexcept
--g_thread_count;
#ifdef _MSC_VER
#ifdef _WIN32
ULONG64 time;
QueryThreadCycleTime(m_thread.native_handle(), &time);
QueryThreadCycleTime(GetCurrentThread(), &time);
LOG_NOTICE(GENERAL, "Thread time: %f Gc", time / 1000000000.);
#endif
}
task_stack& thread_ctrl::get_atexit() const
void thread_ctrl::push_atexit(task_stack task)
{
initialize_once();
return m_data->atexit;
m_data->atexit.push(std::move(task));
}
thread_ctrl::thread_ctrl(std::string&& name)
: m_name(std::move(name))
{
CHECK_STORAGE(std::thread, m_thread);
#pragma push_macro("new")
#undef new
new (&m_thread) std::thread;
#pragma pop_macro("new")
}
thread_ctrl::~thread_ctrl()
{
if (m_thread.joinable())
if (reinterpret_cast<std::thread&>(m_thread).joinable())
{
m_thread.detach();
reinterpret_cast<std::thread&>(m_thread).detach();
}
delete m_data;
reinterpret_cast<std::thread&>(m_thread).~thread();
}
void thread_ctrl::initialize_once() const
void thread_ctrl::initialize_once()
{
if (UNLIKELY(!m_data))
{
@ -1393,33 +1459,37 @@ void thread_ctrl::initialize_once() const
void thread_ctrl::join()
{
if (LIKELY(m_thread.joinable()))
// Increase contention counter
const u32 _j = m_joining++;
if (LIKELY(_j >= 0x80000000))
{
// Increase contention counter
if (UNLIKELY(m_joining++))
// Already joined (signal condition)
m_joining = 0x80000000;
}
else if (LIKELY(_j == 0))
{
// Winner joins the thread
reinterpret_cast<std::thread&>(m_thread).join();
// Notify others if necessary
if (UNLIKELY(m_joining.exchange(0x80000000) != 1))
{
// Hard way
initialize_once();
std::unique_lock<std::mutex> lock(m_data->mutex);
m_data->join.wait(lock, WRAP_EXPR(!m_thread.joinable()));
// Serialize for reliable notification
m_data->mutex.lock();
m_data->mutex.unlock();
m_data->join.notify_all();
}
else
{
// Winner joins the thread
m_thread.join();
}
else
{
// Hard way
initialize_once();
// Notify others if necessary
if (UNLIKELY(m_joining > 1))
{
initialize_once();
// Serialize for reliable notification
m_data->mutex.lock();
m_data->mutex.unlock();
m_data->join.notify_all();
}
}
std::unique_lock<std::mutex> lock(m_data->mutex);
m_data->join.wait(lock, WRAP_EXPR(m_joining >= 0x80000000));
}
if (UNLIKELY(m_data && m_data->exception))
@ -1428,7 +1498,18 @@ void thread_ctrl::join()
}
}
void thread_ctrl::lock_notify() const
void thread_ctrl::lock()
{
initialize_once();
m_data->mutex.lock();
}
void thread_ctrl::unlock()
{
m_data->mutex.unlock();
}
void thread_ctrl::lock_notify()
{
if (UNLIKELY(g_tls_this_thread == this))
{
@ -1443,16 +1524,19 @@ void thread_ctrl::lock_notify() const
m_data->cond.notify_one();
}
void thread_ctrl::notify() const
void thread_ctrl::notify()
{
initialize_once();
m_data->cond.notify_one();
}
thread_ctrl::internal* thread_ctrl::get_data() const
void thread_ctrl::set_exception(std::exception_ptr e)
{
initialize_once();
return m_data;
m_data->exception = e;
}
void thread_ctrl::sleep(u64 useconds)
{
std::this_thread::sleep_for(std::chrono::microseconds(useconds));
}
@ -1462,7 +1546,6 @@ named_thread::named_thread()
named_thread::~named_thread()
{
LOG_TRACE(GENERAL, "%s", __func__);
}
std::string named_thread::get_name() const

View file

@ -1,8 +1,8 @@
#pragma once
#include <exception>
#include <string>
#include <memory>
#include <thread>
#include "Platform.h"
#include "Atomic.h"
@ -28,38 +28,41 @@ class task_stack
}
};
template<typename F>
struct task_type : task_base
{
std::remove_reference_t<F> func;
task_type(F&& func)
: func(std::forward<F>(func))
{
}
void exec() override
{
func();
task_base::exec();
}
};
std::unique_ptr<task_base> m_stack;
public:
task_stack() = default;
template<typename F>
void push(F&& func)
task_stack(F&& func)
: m_stack(new task_type<F>(std::forward<F>(func)))
{
struct task_t : task_base
{
std::remove_reference_t<F> func;
}
task_t(F&& func)
: func(std::forward<F>(func))
{
}
void exec() override
{
func();
task_base::exec();
}
};
auto _top = new task_t(std::forward<F>(func));
void push(task_stack stack)
{
auto _top = stack.m_stack.release();
auto _next = m_stack.release();
m_stack.reset(_top);
#ifndef _MSC_VER
while (UNLIKELY(_top->next)) _top = _top->next.get();
_top->next.reset(_next);
#else
auto& next = _top->next;
next.release();
next.reset(_next);
#endif
}
void reset()
@ -79,42 +82,48 @@ public:
// Thread control class
class thread_ctrl final
{
public: // TODO
struct internal;
private:
static thread_local thread_ctrl* g_tls_this_thread;
// Thread handle
std::thread m_thread;
// Thread handle storage
std::aligned_storage_t<16> m_thread;
// Thread join contention counter
atomic_t<uint> m_joining{};
atomic_t<u32> m_joining{};
// Thread internals
atomic_t<internal*> m_data{};
// Fixed name
std::string m_name;
// Thread internals
mutable atomic_t<internal*> m_data{};
// Start thread
static void start(const std::shared_ptr<thread_ctrl>&, task_stack);
// Called at the thread start
void initialize();
// Set std::current_exception
void set_exception() noexcept;
// Called at the thread end
void finalize() noexcept;
// Get atexit function
task_stack& get_atexit() const;
void push_atexit(task_stack);
// Start waiting
void wait_start(u64 timeout);
// Proceed waiting
bool wait_wait(u64 timeout);
// Check exception
void test();
public:
template<typename N>
thread_ctrl(N&& name)
: m_name(std::forward<N>(name))
{
}
thread_ctrl(std::string&& name);
// Disable copy/move constructors and operators
thread_ctrl(const thread_ctrl&) = delete;
~thread_ctrl();
@ -126,54 +135,139 @@ public:
}
// Initialize internal data
void initialize_once() const;
void initialize_once();
// Get thread result (may throw, simultaneous joining allowed)
void join();
// Lock thread mutex
void lock();
// Lock conditionally (double-checked)
template<typename F>
bool lock_if(F&& pred)
{
if (pred())
{
lock();
try
{
if (LIKELY(pred()))
{
return true;
}
else
{
unlock();
return false;
}
}
catch (...)
{
unlock();
throw;
}
}
else
{
return false;
}
}
// Unlock thread mutex (internal data must be initialized)
void unlock();
// Lock, unlock, notify the thread (required if the condition changed locklessly)
void lock_notify() const;
void lock_notify();
// Notify the thread, beware the condition change
void notify() const;
// Notify the thread (internal data must be initialized)
void notify();
//
internal* get_data() const;
// Set exception (internal data must be initialized, thread mutex must be locked)
void set_exception(std::exception_ptr);
// Current thread sleeps for specified amount of microseconds.
// Wrapper for std::this_thread::sleep, doesn't require valid thread_ctrl.
[[deprecated]] static void sleep(u64 useconds);
// Wait until pred(). Abortable, may throw. Thread must be locked.
// Timeout in microseconds (zero means infinite).
template<typename F>
static inline auto wait(u64 useconds, F&& pred)
{
g_tls_this_thread->wait_start(useconds);
while (true)
{
g_tls_this_thread->test();
if (auto&& result = pred())
{
return result;
}
else if (!g_tls_this_thread->wait_wait(useconds) && useconds)
{
return result;
}
}
}
// Wait until pred(). Abortable, may throw. Thread must be locked.
template<typename F>
static inline auto wait(F&& pred)
{
while (true)
{
g_tls_this_thread->test();
if (auto&& result = pred())
{
return result;
}
g_tls_this_thread->wait_wait(0);
}
}
// Wait once. Thread must be locked.
static inline void wait()
{
g_tls_this_thread->test();
g_tls_this_thread->wait_wait(0);
g_tls_this_thread->test();
}
// Wait unconditionally until aborted. Thread must be locked.
[[noreturn]] static inline void eternalize()
{
while (true)
{
g_tls_this_thread->test();
g_tls_this_thread->wait_wait(0);
}
}
// Get current thread (may be nullptr)
static const thread_ctrl* get_current()
static thread_ctrl* get_current()
{
return g_tls_this_thread;
}
// Register function at thread exit (for the current thread)
template<typename F>
static inline void at_exit(F&& func)
static inline void atexit(F&& func)
{
return g_tls_this_thread->get_atexit().push(std::forward<F>(func));
return g_tls_this_thread->push_atexit(std::forward<F>(func));
}
// Named thread factory
template<typename N, typename F, typename... Args>
static inline std::shared_ptr<thread_ctrl> spawn(N&& name, F&& func, Args&&... args)
template<typename N, typename F>
static inline std::shared_ptr<thread_ctrl> spawn(N&& name, F&& func)
{
auto ctrl = std::make_shared<thread_ctrl>(std::forward<N>(name));
ctrl->m_thread = std::thread([ctrl, task = std::forward<F>(func)](Args&&... args)
{
try
{
ctrl->initialize();
task(std::forward<Args>(args)...);
}
catch (...)
{
ctrl->set_exception();
}
ctrl->finalize();
}, std::forward<Args>(args)...);
thread_ctrl::start(ctrl, std::forward<F>(func));
return ctrl;
}
@ -218,22 +312,43 @@ public:
m_thread->join();
}
// Get thread_ctrl
const thread_ctrl* operator->() const
// Access thread_ctrl
thread_ctrl* operator->() const
{
return m_thread.get();
}
};
// Lock mutex, notify condition variable
void lock_notify() const
// Simple thread mutex locker
class thread_lock final
{
thread_ctrl* m_thread;
public:
thread_lock(const thread_lock&) = delete;
// Lock specified thread
thread_lock(thread_ctrl* thread)
: m_thread(thread)
{
m_thread->lock_notify();
m_thread->lock();
}
// Notify condition variable
void notify() const
// Lock specified named_thread
thread_lock(named_thread& thread)
: thread_lock(thread.operator->())
{
m_thread->notify();
}
// Lock current thread
thread_lock()
: thread_lock(thread_ctrl::get_current())
{
}
~thread_lock()
{
m_thread->unlock();
}
};

View file

@ -17,10 +17,10 @@ namespace memory_helper
{
#ifdef _WIN32
void* ret = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
Ensures(ret != NULL);
ENSURES(ret != NULL);
#else
void* ret = mmap(nullptr, size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
Ensures(ret != 0);
ENSURES(ret != 0);
#endif
return ret;
}
@ -28,18 +28,18 @@ namespace memory_helper
void commit_page_memory(void* pointer, size_t page_size)
{
#ifdef _WIN32
ASSERT(VirtualAlloc((u8*)pointer, page_size, MEM_COMMIT, PAGE_READWRITE) != NULL);
VERIFY(VirtualAlloc((u8*)pointer, page_size, MEM_COMMIT, PAGE_READWRITE) != NULL);
#else
ASSERT(mprotect((u8*)pointer, page_size, PROT_READ | PROT_WRITE) != -1);
VERIFY(mprotect((u8*)pointer, page_size, PROT_READ | PROT_WRITE) != -1);
#endif
}
void free_reserved_memory(void* pointer, size_t size)
{
#ifdef _WIN32
ASSERT(VirtualFree(pointer, 0, MEM_RELEASE) != 0);
VERIFY(VirtualFree(pointer, 0, MEM_RELEASE) != 0);
#else
ASSERT(munmap(pointer, size) == 0);
VERIFY(munmap(pointer, size) == 0);
#endif
}
}

105
Utilities/lockless.h Normal file
View file

@ -0,0 +1,105 @@
#pragma once
#include "types.h"
#include "Atomic.h"
#include "Platform.h"
//! Simple sizeless array base for concurrent access. Cannot shrink, only growths automatically.
//! There is no way to know the current size. The smaller index is, the faster it's accessed.
//!
//! T is the type of elements. Currently, default constructor of T shall be constexpr.
//! N is initial element count, available without any memory allocation and only stored contiguously.
template<typename T, std::size_t N>
class lf_array
{
// Data (default-initialized)
T m_data[N]{};
// Next array block
atomic_t<lf_array*> m_next{};
public:
constexpr lf_array() = default;
~lf_array()
{
for (auto ptr = m_next.raw(); UNLIKELY(ptr);)
{
delete std::exchange(ptr, std::exchange(ptr->m_next.raw(), nullptr));
}
}
T& operator [](std::size_t index)
{
if (LIKELY(index < N))
{
return m_data[index];
}
else if (UNLIKELY(!m_next))
{
// Create new array block. It's not a full-fledged once-synchronization, unlikely needed.
for (auto _new = new lf_array, ptr = this; UNLIKELY(ptr);)
{
// Install the pointer. If failed, go deeper.
ptr = ptr->m_next.compare_and_swap(nullptr, _new);
}
}
// Access recursively
return (*m_next)[index - N];
}
};
//! Simple lock-free FIFO queue base. Based on lf_array<T, N> itself. Currently uses 32-bit counters.
//! There is no "push_end" or "pop_begin" provided, the queue element must signal its state on its own.
template<typename T, std::size_t N>
class lf_fifo : public lf_array<T, N>
{
struct alignas(8) ctrl_t
{
u32 push;
u32 pop;
};
atomic_t<ctrl_t> m_ctrl{};
public:
constexpr lf_fifo() = default;
// Get current "push" position
u32 size()
{
return reinterpret_cast<atomic_t<u32>&>(m_ctrl).load(); // Hack
}
// Acquire the place for one or more elements.
u32 push_begin(u32 count = 1)
{
return reinterpret_cast<atomic_t<u32>&>(m_ctrl).fetch_add(count); // Hack
}
// Get current "pop" position
u32 peek()
{
return m_ctrl.load().pop;
}
// Acknowledge processed element, return number of the next one.
// Perform clear if possible, zero is returned in this case.
u32 pop_end(u32 count = 1)
{
return m_ctrl.atomic_op([&](ctrl_t& ctrl)
{
ctrl.pop += count;
if (ctrl.pop == ctrl.push)
{
// Clean if possible
ctrl.push = 0;
ctrl.pop = 0;
}
return ctrl.pop;
});
}
};

192
Utilities/sync.h Normal file
View file

@ -0,0 +1,192 @@
#pragma once
/* For internal use. Don't include. */
#include "types.h"
#include "Macro.h"
#include "Atomic.h"
#ifdef _WIN32
#include <Windows.h>
#define DYNAMIC_IMPORT(handle, name) do { name = reinterpret_cast<decltype(name)>(GetProcAddress(handle, #name)); } while (0)
static NTSTATUS(*NtSetTimerResolution)(ULONG DesiredResolution, BOOLEAN SetResolution, PULONG CurrentResolution);
static NTSTATUS(*NtWaitForKeyedEvent)(HANDLE Handle, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout);
static NTSTATUS(*NtReleaseKeyedEvent)(HANDLE Handle, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout);
namespace util
{
static const bool keyed_init = []
{
const auto handle = LoadLibraryA("ntdll.dll");
DYNAMIC_IMPORT(handle, NtSetTimerResolution);
DYNAMIC_IMPORT(handle, NtWaitForKeyedEvent);
DYNAMIC_IMPORT(handle, NtReleaseKeyedEvent);
FreeLibrary(handle);
ULONG res = 100;
NtSetTimerResolution(100, TRUE, &res);
return NtWaitForKeyedEvent && NtReleaseKeyedEvent;
}();
// Wait for specified condition. func() acknowledges success by value modification.
template<typename F>
inline void keyed_wait(atomic_t<u32>& key, F&& func)
{
while (true)
{
NtWaitForKeyedEvent(NULL, &key, FALSE, NULL);
u32 read = key.load();
u32 copy = read;
while (pred(read), read != copy)
{
read = key.compare_and_swap(copy, read);
if (copy == read)
{
break;
}
copy = read;
}
}
}
// Try to wake up a thread.
inline bool keyed_post(atomic_t<u32>& key, u32 acknowledged_value)
{
LARGE_INTEGER zero;
zero.QuadPart = 0;
while (UNLIKELY(NtReleaseKeyedEvent(NULL, &key, FALSE, &zero) == WAIT_TIMEOUT))
{
if (key.load() != acknowledged_value)
return false;
//NtReleaseKeyedEvent(NULL, &key, FALSE, NULL);
//return true;
}
return true;
}
struct native_rwlock
{
SRWLOCK rwlock = SRWLOCK_INIT;
constexpr native_rwlock() = default;
native_rwlock(const native_rwlock&) = delete;
void lock()
{
AcquireSRWLockExclusive(&rwlock);
}
bool try_lock()
{
return TryAcquireSRWLockExclusive(&rwlock) != 0;
}
void unlock()
{
ReleaseSRWLockExclusive(&rwlock);
}
void lock_shared()
{
AcquireSRWLockShared(&rwlock);
}
bool try_lock_shared()
{
return TryAcquireSRWLockShared(&rwlock) != 0;
}
void unlock_shared()
{
ReleaseSRWLockShared(&rwlock);
}
};
struct native_cond
{
CONDITION_VARIABLE cond = CONDITION_VARIABLE_INIT;
constexpr native_cond() = default;
native_cond(const native_cond&) = delete;
void notify_one()
{
WakeConditionVariable(&cond);
}
void notify_all()
{
WakeAllConditionVariable(&cond);
}
void wait(native_rwlock& rwlock)
{
SleepConditionVariableSRW(&cond, &rwlock.rwlock, INFINITE, 0);
}
void wait_shared(native_rwlock& rwlock)
{
SleepConditionVariableSRW(&cond, &rwlock.rwlock, INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED);
}
};
class exclusive_lock
{
native_rwlock& m_rwlock;
public:
exclusive_lock(native_rwlock& rwlock)
: m_rwlock(rwlock)
{
m_rwlock.lock();
}
~exclusive_lock()
{
m_rwlock.unlock();
}
};
class shared_lock
{
native_rwlock& m_rwlock;
public:
shared_lock(native_rwlock& rwlock)
: m_rwlock(rwlock)
{
m_rwlock.lock_shared();
}
~shared_lock()
{
m_rwlock.unlock_shared();
}
};
}
#else
namespace util
{
struct native_rwlock;
struct native_cond;
}
#endif
CHECK_SIZE_ALIGN(util::native_rwlock, sizeof(void*), alignof(void*));
CHECK_SIZE_ALIGN(util::native_cond, sizeof(void*), alignof(void*));

View file

@ -407,12 +407,22 @@ struct ignore
}
};
// Simplified hash algorithm for pointers. May be used in std::unordered_(map|set).
template<typename T, std::size_t Align = alignof(T)>
struct pointer_hash
{
std::size_t operator()(T* ptr) const
{
return reinterpret_cast<std::uintptr_t>(ptr) / Align;
}
};
// Contains value of any POD type with fixed size and alignment. TT<> is the type converter applied.
// For example, `simple_t` may be used to remove endianness.
template<template<typename> class TT, std::size_t S, std::size_t A = S>
struct alignas(A) any_pod
{
enum class byte : char {} data[S];
std::aligned_storage_t<S, A> data;
any_pod() = default;

View file

@ -40,7 +40,7 @@ if(NOT MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1") # fix for travis gcc OoM crash. Might be fixed with the move to containers.
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fexceptions")
add_compile_options(-msse -msse2 -mcx16 -mssse3)
add_compile_options(-msse -msse2 -mcx16 -mssse3 -march=native)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:throwingNew /D _CRT_SECURE_NO_DEPRECATE=1 /D _CRT_NON_CONFORMING_SWPRINTFS=1 /D _SCL_SECURE_NO_WARNINGS=1")
endif()

View file

@ -1 +0,0 @@
#pragma once

View file

@ -24,7 +24,7 @@ void AudioDumper::WriteData(const void* buffer, u32 size)
{
if (GetCh())
{
ASSERT(m_output.write(buffer, size) == size);
VERIFY(m_output.write(buffer, size) == size);
m_header.Size += size;
m_header.RIFF.Size += size;
}

View file

@ -1,15 +1,15 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/Cell/RawSPUThread.h"
#include "Emu/ARMv7/ARMv7Thread.h"
#include "CPUThread.h"
#include <mutex>
#include <condition_variable>
thread_local cpu_thread* g_tls_current_cpu_thread = nullptr;
extern std::mutex& get_current_thread_mutex();
extern std::condition_variable& get_current_thread_cv();
void cpu_thread::on_task()
{
state -= cpu_state::exit;
@ -61,7 +61,7 @@ void cpu_thread::on_task()
void cpu_thread::on_stop()
{
state += cpu_state::exit;
lock_notify();
(*this)->lock_notify();
}
cpu_thread::~cpu_thread()
@ -121,35 +121,3 @@ bool cpu_thread::check_status()
return false;
}
[[noreturn]] void cpu_thread::xsleep()
{
throw std::runtime_error("cpu_thread: sleep()/awake() inconsistency");
}
std::vector<std::shared_ptr<cpu_thread>> get_all_cpu_threads()
{
std::vector<std::shared_ptr<cpu_thread>> result;
for (auto& t : idm::get_all<PPUThread>())
{
result.emplace_back(t);
}
for (auto& t : idm::get_all<SPUThread>())
{
result.emplace_back(t);
}
for (auto& t : idm::get_all<RawSPUThread>())
{
result.emplace_back(t);
}
for (auto& t : idm::get_all<ARMv7Thread>())
{
result.emplace_back(t);
}
return result;
}

View file

@ -40,7 +40,6 @@ public:
const std::string name;
const cpu_type type;
const id_value<> id{};
cpu_thread(cpu_type type, const std::string& name);
@ -48,36 +47,34 @@ public:
// Public thread state
atomic_t<bitset_t<cpu_state>> state{ cpu_state::stop };
// Recursively enter sleep state
void sleep()
{
if (!++m_sleep) xsleep();
}
// Public recursive sleep state counter
atomic_t<u32> sleep_counter{};
// Leave sleep state
void awake()
{
if (!m_sleep--) xsleep();
}
// Object associated with sleep state, possibly synchronization primitive (mutex, semaphore, etc.)
atomic_t<void*> owner{};
// Process thread state, return true if the checker must return
bool check_status();
virtual std::string dump() const = 0; // Print CPU state
// Increse sleep counter
void sleep()
{
if (!sleep_counter++) return; //handle_interrupt();
}
// Decrese sleep counter
void awake()
{
if (!--sleep_counter) owner = nullptr;
}
// Print CPU state
virtual std::string dump() const = 0;
virtual void cpu_init() {}
virtual void cpu_task() = 0;
virtual bool handle_interrupt() { return false; }
private:
[[noreturn]] void xsleep();
// Sleep/Awake counter
atomic_t<u32> m_sleep{};
};
extern std::mutex& get_current_thread_mutex();
extern std::condition_variable& get_current_thread_cv();
inline cpu_thread* get_current_cpu_thread() noexcept
{
extern thread_local cpu_thread* g_tls_current_cpu_thread;
@ -85,4 +82,26 @@ inline cpu_thread* get_current_cpu_thread() noexcept
return g_tls_current_cpu_thread;
}
extern std::vector<std::shared_ptr<cpu_thread>> get_all_cpu_threads();
// Helper for cpu_thread.
// 1) Calls sleep() and locks the thread in the constructor.
// 2) Calls awake() and unlocks the thread in the destructor.
class cpu_thread_lock final
{
cpu_thread& m_thread;
public:
cpu_thread_lock(const cpu_thread_lock&) = delete;
cpu_thread_lock(cpu_thread& thread)
: m_thread(thread)
{
m_thread.sleep();
m_thread->lock();
}
~cpu_thread_lock()
{
m_thread.awake();
m_thread->unlock();
}
};

View file

@ -110,9 +110,12 @@ struct ppu_error_code
{
}
// Helper
enum class not_an_error : s32 {};
// Silence any error
constexpr ppu_error_code(s32 value, const std::nothrow_t&)
: value(value)
constexpr ppu_error_code(not_an_error value)
: value(static_cast<s32>(value))
{
}
@ -124,7 +127,7 @@ struct ppu_error_code
};
// Helper macro for silencing possible error checks on returning ppu_error_code values
#define NOT_AN_ERROR(value) { static_cast<s32>(value), std::nothrow }
#define NOT_AN_ERROR(...) static_cast<ppu_error_code::not_an_error>(__VA_ARGS__)
template<typename T, typename>
struct ppu_gpr_cast_impl;

View file

@ -15,7 +15,9 @@ extern "C"
#include "cellPamf.h"
#include "cellAdec.h"
LOG_CHANNEL(cellAdec);
#include <thread>
logs::channel cellAdec("cellAdec", logs::level::notice);
AudioDecoder::AudioDecoder(s32 type, u32 addr, u32 size, vm::ptr<CellAdecCbMsg> func, u32 arg)
: type(type)
@ -468,7 +470,7 @@ void adecOpen(u32 adec_id) // TODO: call from the constructor
adec.adecCb->cpu_init();
adec.adecCb->state -= cpu_state::stop;
adec.adecCb->lock_notify();
(*adec.adecCb)->lock_notify();
}
bool adecCheckType(s32 type)
@ -569,7 +571,7 @@ s32 cellAdecClose(u32 handle)
{
CHECK_EMU_STATUS;
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
std::this_thread::sleep_for(1ms); // hack
}
idm::remove<PPUThread>(adec->adecCb->id);
@ -682,7 +684,7 @@ s32 cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
AdecFrame af;
if (!adec->frames.try_pop(af))
{
//std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
//std::this_thread::sleep_for(1ms); // hack
return CELL_ADEC_ERROR_EMPTY;
}
@ -798,7 +800,7 @@ s32 cellAdecGetPcmItem(u32 handle, vm::pptr<CellAdecPcmItem> pcmItem)
AdecFrame af;
if (!adec->frames.try_peek(af))
{
//std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
//std::this_thread::sleep_for(1ms); // hack
return CELL_ADEC_ERROR_EMPTY;
}

View file

@ -4,7 +4,7 @@
#include "cellAtrac.h"
LOG_CHANNEL(cellAtrac);
logs::channel cellAtrac("cellAtrac", logs::level::notice);
s32 cellAtracSetDataAndGetMemSize(vm::ptr<CellAtracHandle> pHandle, vm::ptr<u8> pucBufferAddr, u32 uiReadByte, u32 uiBufferByte, vm::ptr<u32> puiWorkMemByte)
{

View file

@ -4,7 +4,7 @@
#include "cellAtracMulti.h"
LOG_CHANNEL(cellAtracMulti);
logs::channel cellAtracMulti("cellAtracMulti", logs::level::notice);
s32 cellAtracMultiSetDataAndGetMemSize(vm::ptr<CellAtracMultiHandle> pHandle, vm::ptr<u8> pucBufferAddr, u32 uiReadByte, u32 uiBufferByte, u32 uiOutputChNum, vm::ptr<s32> piTrackArray, vm::ptr<u32> puiWorkMemByte)
{

View file

@ -1,4 +1,5 @@
#include "stdafx.h"
#include "Utilities/Config.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
@ -8,7 +9,9 @@
#include "Emu/Audio/AudioThread.h"
#include "cellAudio.h"
LOG_CHANNEL(cellAudio);
#include <thread>
logs::channel cellAudio("cellAudio", logs::level::notice);
cfg::bool_entry g_cfg_audio_dump_to_file(cfg::root.audio, "Dump to file");
cfg::bool_entry g_cfg_audio_convert_to_u16(cfg::root.audio, "Convert to 16 bit");

View file

@ -3,7 +3,7 @@
#include "cellAudioOut.h"
extern _log::channel cellSysutil;
extern logs::channel cellSysutil;
s32 cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
{

View file

@ -6,7 +6,7 @@
#include "cellAudioOut.h"
#include "cellVideoOut.h"
LOG_CHANNEL(cellAvconfExt);
logs::channel cellAvconfExt("cellAvconfExt", logs::level::notice);
vm::gvar<f32> g_gamma; // TODO

View file

@ -2,7 +2,7 @@
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellBGDL);
logs::channel cellBGDL("cellBGDL", logs::level::notice);
// Return Codes
enum

View file

@ -1,11 +1,12 @@
#include "stdafx.h"
#include "Utilities/Config.h"
#include "Emu/IdManager.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "cellCamera.h"
LOG_CHANNEL(cellCamera);
logs::channel cellCamera("cellCamera", logs::level::notice);
cfg::map_entry<bool> g_cfg_camera(cfg::root.io, "Camera",
{

View file

@ -2,7 +2,7 @@
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellCelp8Enc);
logs::channel cellCelp8Enc("cellCelp8Enc", logs::level::notice);
// Return Codes
enum

View file

@ -2,7 +2,7 @@
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellCelpEnc);
logs::channel cellCelpEnc("cellCelpEnc", logs::level::notice);
// Return Codes
enum

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellDaisy);
logs::channel cellDaisy("cellDaisy", logs::level::notice);
s32 _ZN4cell5Daisy17LFQueue2PushCloseEPNS0_8LFQueue2EPFiPvjE()
{

View file

@ -6,7 +6,9 @@
#include "cellPamf.h"
#include "cellDmux.h"
LOG_CHANNEL(cellDmux);
#include <thread>
logs::channel cellDmux("cellDmux", logs::level::notice);
PesHeader::PesHeader(DemuxerStream& stream)
: pts(CODEC_TS_INVALID)
@ -142,7 +144,7 @@ void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool ra
u32 addr;
{
std::lock_guard<std::mutex> lock(m_mutex);
ASSERT(!is_full(size));
VERIFY(!is_full(size));
if (put + size + 128 > memAddr + memSize)
{
@ -183,7 +185,7 @@ void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool ra
put_count++;
}
ASSERT(entries.push(addr, &dmux->is_closed));
VERIFY(entries.push(addr, &dmux->is_closed));
}
void ElementaryStream::push(DemuxerStream& stream, u32 size)
@ -447,7 +449,7 @@ void dmuxOpen(u32 dmux_id) // TODO: call from the constructor
if (es.raw_data.size() > 1024 * 1024)
{
stream = backup;
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
std::this_thread::sleep_for(1ms); // hack
continue;
}
@ -543,7 +545,7 @@ void dmuxOpen(u32 dmux_id) // TODO: call from the constructor
if (es.isfull(old_size))
{
stream = backup;
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
std::this_thread::sleep_for(1ms); // hack
continue;
}
@ -711,7 +713,7 @@ void dmuxOpen(u32 dmux_id) // TODO: call from the constructor
{
if (Emu.IsStopped() || dmux.is_closed) break;
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
std::this_thread::sleep_for(1ms); // hack
}
es.push_au(old_size, es.last_dts, es.last_pts, stream.userdata, false, 0);
@ -759,7 +761,7 @@ void dmuxOpen(u32 dmux_id) // TODO: call from the constructor
dmux.dmuxCb->cpu_init();
dmux.dmuxCb->state -= cpu_state::stop;
dmux.dmuxCb->lock_notify();
(*dmux.dmuxCb)->lock_notify();
}
s32 cellDmuxQueryAttr(vm::cptr<CellDmuxType> type, vm::ptr<CellDmuxAttr> attr)
@ -865,7 +867,7 @@ s32 cellDmuxClose(u32 handle)
return CELL_OK;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
std::this_thread::sleep_for(1ms); // hack
}
idm::remove<PPUThread>(dmux->dmuxCb->id);
@ -886,7 +888,7 @@ s32 cellDmuxSetStream(u32 handle, u32 streamAddress, u32 streamSize, b8 disconti
if (dmux->is_running.exchange(true))
{
//std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
//std::this_thread::sleep_for(1ms); // hack
return CELL_DMUX_ERROR_BUSY;
}
@ -943,7 +945,7 @@ s32 cellDmuxResetStreamAndWaitDone(u32 handle)
cellDmux.warning("cellDmuxResetStreamAndWaitDone(%d) aborted", handle);
return CELL_OK;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
std::this_thread::sleep_for(1ms); // hack
}
return CELL_OK;

View file

@ -4,7 +4,7 @@
#include "cellFiber.h"
LOG_CHANNEL(cellFiber);
logs::channel cellFiber("cellFiber", logs::level::notice);
s32 _cellFiberPpuInitialize()
{

View file

@ -8,7 +8,7 @@
#include "cellFont.h"
LOG_CHANNEL(cellFont);
logs::channel cellFont("cellFont", logs::level::notice);
// Functions
s32 cellFontInitializeWithRevision(u64 revisionFlags, vm::ptr<CellFontConfig> config)

View file

@ -3,7 +3,7 @@
#include "cellFontFT.h"
LOG_CHANNEL(cellFontFT);
logs::channel cellFontFT("cellFontFT", logs::level::notice);
s32 cellFontInitLibraryFreeTypeWithRevision(u64 revisionFlags, vm::ptr<CellFontLibraryConfigFT> config, vm::pptr<CellFontLibrary> lib)
{

View file

@ -8,7 +8,7 @@
#include "Utilities/StrUtil.h"
LOG_CHANNEL(cellFs);
logs::channel cellFs("cellFs", logs::level::notice);
s32 cellFsOpen(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, vm::cptr<void> arg, u64 size)
{
@ -527,7 +527,7 @@ s32 cellFsStReadStart(u32 fd, u64 offset, u64 size)
}
}
file->cv.wait_for(lock, std::chrono::milliseconds(1));
file->cv.wait_for(lock, 1ms);
}
file->st_status.compare_and_swap(SSS_STOPPED, SSS_INITIALIZED);
@ -688,7 +688,7 @@ s32 cellFsStReadWait(u32 fd, u64 size)
{
CHECK_EMU_STATUS;
file->cv.wait_for(lock, std::chrono::milliseconds(1));
file->cv.wait_for(lock, 1ms);
}
return CELL_OK;

View file

@ -10,7 +10,9 @@
#include "Loader/PSF.h"
#include "Utilities/StrUtil.h"
LOG_CHANNEL(cellGame);
#include <thread>
logs::channel cellGame("cellGame", logs::level::notice);
// Normal content directory (if is_temporary is not involved):
// contentInfo = dir
@ -308,7 +310,7 @@ ppu_error_code cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentIn
}
// Create PARAM.SFO
fs::file(dir + "/PARAM.SFO", fs::rewrite).write(psf::save_object(prm->sfo));
psf::save_object(fs::file(dir + "/PARAM.SFO", fs::rewrite), prm->sfo);
// Disable deletion
prm->is_temporary = false;
@ -555,7 +557,7 @@ ppu_error_code cellGameGetParamString(s32 id, vm::ptr<char> buf, u32 bufsize)
std::string&& value = psf::get_string(prm->sfo, key);
value.resize(bufsize - 1);
std::copy_n(value.c_str(), value.size() + 1, buf.get_ptr());
std::memcpy(buf.get_ptr(), value.c_str(), bufsize);
return CELL_OK;
}

View file

@ -3,7 +3,7 @@
#include "cellGame.h"
LOG_CHANNEL(cellGameExec);
logs::channel cellGameExec("cellGameExec", logs::level::notice);
s32 cellGameSetExitParam()
{

View file

@ -8,7 +8,9 @@
#include "Emu/RSX/GSRender.h"
#include "cellGcmSys.h"
LOG_CHANNEL(cellGcmSys);
#include <thread>
logs::channel cellGcmSys("cellGcmSys", logs::level::notice);
extern s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count);
@ -933,7 +935,7 @@ s32 cellGcmMapEaIoAddressWithFlags(u32 ea, u32 io, u32 size, u32 flags)
{
cellGcmSys.warning("cellGcmMapEaIoAddressWithFlags(ea=0x%x, io=0x%x, size=0x%x, flags=0x%x)", ea, io, size, flags);
ASSERT(flags == 2 /*CELL_GCM_IOMAP_FLAG_STRICT_ORDERING*/);
VERIFY(flags == 2 /*CELL_GCM_IOMAP_FLAG_STRICT_ORDERING*/);
return gcmMapEaIoAddress(ea, io, size, true);
}
@ -1257,7 +1259,7 @@ static std::pair<u32, u32> getNextCommandBufferBeginEnd(u32 current)
static u32 getOffsetFromAddress(u32 address)
{
const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits
Expects(upper != 0xFFFF);
EXPECTS(upper != 0xFFFF);
return (upper << 20) | (address & 0xFFFFF);
}

View file

@ -4,7 +4,7 @@
#include "cellGem.h"
LOG_CHANNEL(cellGem);
logs::channel cellGem("cellGem", logs::level::notice);
struct gem_t
{

View file

@ -9,7 +9,7 @@
#include "Emu/Cell/lv2/sys_fs.h"
#include "cellGifDec.h"
LOG_CHANNEL(cellGifDec);
logs::channel cellGifDec("cellGifDec", logs::level::notice);
// cellGifDec aliases (only for cellGifDec.cpp)
using PPMainHandle = vm::pptr<GifDecoder>;

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellHttp);
logs::channel cellHttp("cellHttp", logs::level::notice);
s32 cellHttpInit()
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellHttpUtil);
logs::channel cellHttpUtil("cellHttpUtil", logs::level::notice);
s32 cellHttpUtilParseUri()
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellImeJp);
logs::channel cellImeJp("cellImeJp", logs::level::notice);
// Return Codes
enum

View file

@ -9,7 +9,7 @@
#include "Emu/Cell/lv2/sys_fs.h"
#include "cellJpgDec.h"
LOG_CHANNEL(cellJpgDec);
logs::channel cellJpgDec("cellJpgDec", logs::level::notice);
s32 cellJpgDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellJpgEnc);
logs::channel cellJpgEnc("cellJpgEnc", logs::level::notice);
// Error Codes
enum

View file

@ -6,7 +6,7 @@
#include "Emu/Io/KeyboardHandler.h"
#include "cellKb.h"
extern _log::channel sys_io;
extern logs::channel sys_io;
s32 cellKbInit(u32 max_connect)
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellKey2char);
logs::channel cellKey2char("cellKey2char", logs::level::notice);
// Return Codes
enum

View file

@ -14,7 +14,7 @@ typedef const char *HostCode;
#include "cellL10n.h"
LOG_CHANNEL(cellL10n);
logs::channel cellL10n("cellL10n", logs::level::notice);
// Translate code id to code name. some codepage may has another name.
// If this makes your compilation fail, try replace the string code with one in "iconv -l"

View file

@ -4,7 +4,7 @@
#include "cellMic.h"
LOG_CHANNEL(cellMic);
logs::channel cellMic("cellMic", logs::level::notice);
s32 cellMicInit()
{

View file

@ -6,7 +6,7 @@
#include "Emu/Io/MouseHandler.h"
#include "cellMouse.h"
extern _log::channel sys_io;
extern logs::channel sys_io;
s32 cellMouseInit(u32 max_connect)
{

View file

@ -6,7 +6,9 @@
#include "cellSysutil.h"
#include "cellMsgDialog.h"
extern _log::channel cellSysutil;
#include <thread>
extern logs::channel cellSysutil;
s32 cellMsgDialogOpen()
{

View file

@ -5,7 +5,7 @@
#include "cellMusic.h"
LOG_CHANNEL(cellMusic);
logs::channel cellMusic("cellMusic", logs::level::notice);
struct music2_t
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellMusicDecode);
logs::channel cellMusicDecode("cellMusicDecode", logs::level::notice);
// Return Codes
enum

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellMusicExport);
logs::channel cellMusicExport("cellMusicExport", logs::level::notice);
// Return Codes
enum

View file

@ -1,4 +1,5 @@
#include "stdafx.h"
#include "Utilities/Config.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
@ -7,7 +8,7 @@
#include "Utilities/StrUtil.h"
LOG_CHANNEL(cellNetCtl);
logs::channel cellNetCtl("cellNetCtl", logs::level::notice);
cfg::map_entry<s32> g_cfg_net_status(cfg::root.net, "Connection status",
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellOskDialog);
logs::channel cellOskDialog("cellOskDialog", logs::level::notice);
s32 cellOskDialogLoadAsync()
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellOvis);
logs::channel cellOvis("cellOvis", logs::level::notice);
// Return Codes
enum

View file

@ -6,7 +6,7 @@
#include "Emu/Io/PadHandler.h"
#include "cellPad.h"
extern _log::channel sys_io;
extern logs::channel sys_io;
s32 cellPadInit(u32 max_connect)
{

View file

@ -12,12 +12,12 @@ bool squeue_test_exit()
return Emu.IsStopped();
}
LOG_CHANNEL(cellPamf);
logs::channel cellPamf("cellPamf", logs::level::notice);
s32 pamfStreamTypeToEsFilterId(u8 type, u8 ch, CellCodecEsFilterId& pEsFilterId)
{
// convert type and ch to EsFilterId
Expects(ch < 16);
EXPECTS(ch < 16);
pEsFilterId.supplementalInfo1 = type == CELL_PAMF_STREAM_TYPE_AVC;
pEsFilterId.supplementalInfo2 = 0;
@ -117,7 +117,7 @@ s32 pamfStreamTypeToEsFilterId(u8 type, u8 ch, CellCodecEsFilterId& pEsFilterId)
u8 pamfGetStreamType(vm::ptr<CellPamfReader> pSelf, u32 stream)
{
// TODO: get stream type correctly
Expects(stream < (u32)pSelf->pAddr->stream_count);
EXPECTS(stream < (u32)pSelf->pAddr->stream_count);
auto& header = pSelf->pAddr->stream_headers[stream];
switch (header.type)
@ -138,7 +138,7 @@ u8 pamfGetStreamType(vm::ptr<CellPamfReader> pSelf, u32 stream)
u8 pamfGetStreamChannel(vm::ptr<CellPamfReader> pSelf, u32 stream)
{
// TODO: get stream channel correctly
Expects(stream < (u32)pSelf->pAddr->stream_count);
EXPECTS(stream < (u32)pSelf->pAddr->stream_count);
auto& header = pSelf->pAddr->stream_headers[stream];
switch (header.type)
@ -146,29 +146,29 @@ u8 pamfGetStreamChannel(vm::ptr<CellPamfReader> pSelf, u32 stream)
case 0x1b: // AVC
case 0x02: // M2V
{
Expects((header.fid_major & 0xf0) == 0xe0 && header.fid_minor == 0);
EXPECTS((header.fid_major & 0xf0) == 0xe0 && header.fid_minor == 0);
return header.fid_major % 16;
}
case 0xdc: // ATRAC3PLUS
{
Expects(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0);
EXPECTS(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0);
return header.fid_minor % 16;
}
case 0x80: // LPCM
{
Expects(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x40);
EXPECTS(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x40);
return header.fid_minor % 16;
}
case 0x81: // AC3
{
Expects(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x30);
EXPECTS(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x30);
return header.fid_minor % 16;
}
case 0xdd:
{
Expects(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x20);
EXPECTS(header.fid_major == 0xbd && (header.fid_minor & 0xf0) == 0x20);
return header.fid_minor % 16;
}
}
@ -454,7 +454,7 @@ s32 cellPamfReaderGetEsFilterId(vm::ptr<CellPamfReader> pSelf, vm::ptr<CellCodec
// always returns CELL_OK
Expects((u32)pSelf->stream < (u32)pSelf->pAddr->stream_count);
EXPECTS((u32)pSelf->stream < (u32)pSelf->pAddr->stream_count);
auto& header = pSelf->pAddr->stream_headers[pSelf->stream];
pEsFilterId->filterIdMajor = header.fid_major;
pEsFilterId->filterIdMinor = header.fid_minor;
@ -467,7 +467,7 @@ s32 cellPamfReaderGetStreamInfo(vm::ptr<CellPamfReader> pSelf, vm::ptr<void> pIn
{
cellPamf.warning("cellPamfReaderGetStreamInfo(pSelf=*0x%x, pInfo=*0x%x, size=%d)", pSelf, pInfo, size);
Expects((u32)pSelf->stream < (u32)pSelf->pAddr->stream_count);
EXPECTS((u32)pSelf->stream < (u32)pSelf->pAddr->stream_count);
auto& header = pSelf->pAddr->stream_headers[pSelf->stream];
const u8 type = pamfGetStreamType(pSelf, pSelf->stream);
const u8 ch = pamfGetStreamChannel(pSelf, pSelf->stream);

View file

@ -400,6 +400,8 @@ CHECK_SIZE(CellPamfReader, 128);
s32 cellPamfReaderInitialize(vm::ptr<CellPamfReader> pSelf, vm::cptr<PamfHeader> pAddr, u64 fileSize, u32 attribute);
#include <mutex>
#include <condition_variable>
extern const std::function<bool()> SQUEUE_ALWAYS_EXIT;
extern const std::function<bool()> SQUEUE_NEVER_EXIT;
@ -462,8 +464,8 @@ public:
while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
{
Expects(sync.count <= sq_size);
Expects(sync.position < sq_size);
EXPECTS(sync.count <= sq_size);
EXPECTS(sync.position < sq_size);
if (sync.push_lock)
{
@ -492,9 +494,9 @@ public:
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
Expects(sync.count <= sq_size);
Expects(sync.position < sq_size);
Expects(sync.push_lock);
EXPECTS(sync.count <= sq_size);
EXPECTS(sync.position < sq_size);
EXPECTS(sync.push_lock);
sync.push_lock = 0;
sync.count++;
});
@ -525,8 +527,8 @@ public:
while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
{
Expects(sync.count <= sq_size);
Expects(sync.position < sq_size);
EXPECTS(sync.count <= sq_size);
EXPECTS(sync.position < sq_size);
if (!sync.count)
{
@ -555,9 +557,9 @@ public:
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
Expects(sync.count <= sq_size);
Expects(sync.position < sq_size);
Expects(sync.pop_lock);
EXPECTS(sync.count <= sq_size);
EXPECTS(sync.position < sq_size);
EXPECTS(sync.pop_lock);
sync.pop_lock = 0;
sync.position++;
sync.count--;
@ -589,13 +591,13 @@ public:
bool peek(T& data, u32 start_pos, const std::function<bool()>& test_exit)
{
Expects(start_pos < sq_size);
EXPECTS(start_pos < sq_size);
u32 pos = 0;
while (u32 res = m_sync.atomic_op([&pos, start_pos](squeue_sync_var_t& sync) -> u32
{
Expects(sync.count <= sq_size);
Expects(sync.position < sq_size);
EXPECTS(sync.count <= sq_size);
EXPECTS(sync.position < sq_size);
if (sync.count <= start_pos)
{
@ -624,9 +626,9 @@ public:
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
Expects(sync.count <= sq_size);
Expects(sync.position < sq_size);
Expects(sync.pop_lock);
EXPECTS(sync.count <= sq_size);
EXPECTS(sync.position < sq_size);
EXPECTS(sync.pop_lock);
sync.pop_lock = 0;
});
@ -665,7 +667,7 @@ public:
public:
T& operator [] (u32 index)
{
Expects(index < m_count);
EXPECTS(index < m_count);
index += m_pos;
index = index < sq_size ? index : index - sq_size;
return m_data[index];
@ -678,8 +680,8 @@ public:
while (m_sync.atomic_op([&pos, &count](squeue_sync_var_t& sync) -> u32
{
Expects(sync.count <= sq_size);
Expects(sync.position < sq_size);
EXPECTS(sync.count <= sq_size);
EXPECTS(sync.position < sq_size);
if (sync.pop_lock || sync.push_lock)
{
@ -701,9 +703,9 @@ public:
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
Expects(sync.count <= sq_size);
Expects(sync.position < sq_size);
Expects(sync.pop_lock && sync.push_lock);
EXPECTS(sync.count <= sq_size);
EXPECTS(sync.position < sq_size);
EXPECTS(sync.pop_lock && sync.push_lock);
sync.pop_lock = 0;
sync.push_lock = 0;
});
@ -716,8 +718,8 @@ public:
{
while (m_sync.atomic_op([](squeue_sync_var_t& sync) -> u32
{
Expects(sync.count <= sq_size);
Expects(sync.position < sq_size);
EXPECTS(sync.count <= sq_size);
EXPECTS(sync.position < sq_size);
if (sync.pop_lock || sync.push_lock)
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellPhotoDecode);
logs::channel cellPhotoDecode("cellPhotoDecode", logs::level::notice);
// Return Codes
enum

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellPhotoExport);
logs::channel cellPhotoExport("cellPhotoExport", logs::level::notice);
// Return Codes
enum

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellPhotoImportUtil);
logs::channel cellPhotoImportUtil("cellPhotoImportUtil", logs::level::notice);
// Return Codes
enum

View file

@ -7,7 +7,7 @@
#include "png.h"
#include "cellPngDec.h"
LOG_CHANNEL(cellPngDec);
logs::channel cellPngDec("cellPngDec", logs::level::notice);
// cellPngDec aliases to improve readability
using PPHandle = vm::pptr<PngHandle>;

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellPngEnc);
logs::channel cellPngEnc("cellPngEnc", logs::level::notice);
// Error Codes
enum

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellPrint);
logs::channel cellPrint("cellPrint", logs::level::notice);
// Error Codes
enum

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellRec);
logs::channel cellRec("cellRec", logs::level::notice);
s32 cellRecOpen()
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellRemotePlay);
logs::channel cellRemotePlay("cellRemotePlay", logs::level::notice);
s32 cellRemotePlayGetStatus()
{

View file

@ -6,7 +6,7 @@
#include "Emu/RSX/GCM.h"
#include "cellResc.h"
LOG_CHANNEL(cellResc);
logs::channel cellResc("cellResc", logs::level::notice);
s32 cellRescInit(vm::ptr<CellRescInitConfig> initConfig)
{

View file

@ -3,7 +3,7 @@
#include "cellRtc.h"
LOG_CHANNEL(cellRtc);
logs::channel cellRtc("cellRtc", logs::level::notice);
s64 convertToUNIXTime(u16 seconds, u16 minutes, u16 hours, u16 days, s32 years)
{

View file

@ -5,7 +5,7 @@
#include "cellRudp.h"
LOG_CHANNEL(cellRudp);
logs::channel cellRudp("cellRudp", logs::level::notice);
struct rudp_t
{

View file

@ -5,7 +5,7 @@
#include "cellSail.h"
#include "cellPamf.h"
LOG_CHANNEL(cellSail);
logs::channel cellSail("cellSail", logs::level::notice);
void playerBoot(vm::ptr<CellSailPlayer> pSelf, u64 userParam)
{
@ -818,7 +818,7 @@ s32 cellSailPlayerCreateDescriptor(vm::ptr<CellSailPlayer> pSelf, s32 streamType
u32 buffer = vm::alloc(size, vm::main);
auto bufPtr = vm::cptr<PamfHeader>::make(buffer);
PamfHeader *buf = const_cast<PamfHeader*>(bufPtr.get_ptr());
ASSERT(f.read(buf, size) == size);
VERIFY(f.read(buf, size) == size);
u32 sp_ = vm::alloc(sizeof(CellPamfReader), vm::main);
auto sp = vm::ptr<CellPamfReader>::make(sp_);
u32 reader = cellPamfReaderInitialize(sp, bufPtr, size, 0);

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellSailRec);
logs::channel cellSailRec("cellSailRec", logs::level::notice);
// Error Codes
enum

View file

@ -7,7 +7,9 @@
#include "Loader/PSF.h"
#include "Utilities/StrUtil.h"
LOG_CHANNEL(cellSaveData);
#include <algorithm>
logs::channel cellSaveData("cellSaveData", logs::level::notice);
// cellSaveData aliases (only for cellSaveData.cpp)
using PSetList = vm::ptr<CellSaveDataSetList>;
@ -609,7 +611,7 @@ static never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version,
// Write PARAM.SFO
if (psf.size())
{
fs::file(sfo_path, fs::rewrite).write(psf::save_object(psf));
psf::save_object(fs::file(sfo_path, fs::rewrite), psf);
}
return CELL_OK;

View file

@ -4,7 +4,7 @@
#include "cellScreenshot.h"
LOG_CHANNEL(cellScreenshot);
logs::channel cellScreenshot("cellScreenshot", logs::level::notice);
s32 cellScreenShotSetParameter() //const CellScreenShotSetParam *param
{

View file

@ -4,7 +4,7 @@
#include "cellSearch.h"
LOG_CHANNEL(cellSearch);
logs::channel cellSearch("cellSearch", logs::level::notice);
s32 cellSearchInitialize(CellSearchMode mode, u32 container, vm::ptr<CellSearchSystemCallback> func, vm::ptr<u32> userData)
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellSheap);
logs::channel cellSheap("cellSheap", logs::level::notice);
// Return Codes
enum

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellSpudll);
logs::channel cellSpudll("cellSpudll", logs::level::notice);
s32 cellSpudllGetImageSize(vm::ptr<u32> psize, vm::cptr<void> so_elf, vm::cptr<struct CellSpudllHandleConfig> config)
{

View file

@ -15,7 +15,7 @@
#include "sysPrxForUser.h"
#include "cellSpurs.h"
LOG_CHANNEL(cellSpurs);
logs::channel cellSpurs("cellSpurs", logs::level::notice);
// TODO
struct cell_error_t
@ -30,6 +30,28 @@ struct cell_error_t
#define CHECK_SUCCESS(expr) if (cell_error_t error{expr}) throw fmt::exception("Failure: %s -> 0x%x" HERE, #expr, error.value)
static u32 ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, const std::string& name, std::function<void(PPUThread&)> task)
{
const auto ppu = idm::make_ptr<PPUThread>(name);
ppu->prio = prio;
ppu->stack_size = stacksize;
ppu->custom_task = std::move(task);
ppu->cpu_init();
if (entry)
{
ppu->pc = vm::read32(entry);
ppu->GPR[2] = vm::read32(entry + 4); // rtoc
}
ppu->GPR[3] = arg;
ppu->state -= cpu_state::stop;
(*ppu)->lock_notify();
return ppu->id;
}
//----------------------------------------------------------------------------
// Function prototypes
//----------------------------------------------------------------------------
@ -588,7 +610,7 @@ void _spurs::handler_entry(PPUThread& ppu, vm::ptr<CellSpurs> spurs)
if ((spurs->flags1 & SF1_EXIT_IF_NO_WORK) == 0)
{
ASSERT(spurs->handlerExiting == 1);
VERIFY(spurs->handlerExiting == 1);
return sys_ppu_thread_exit(ppu, 0);
}
@ -651,16 +673,16 @@ s32 _spurs::wakeup_shutdown_completion_waiter(PPUThread& ppu, vm::ptr<CellSpurs>
{
wklF->hook(ppu, spurs, wid, wklF->hookArg);
ASSERT(wklEvent->load() & 0x01);
ASSERT(wklEvent->load() & 0x02);
ASSERT((wklEvent->load() & 0x20) == 0);
VERIFY(wklEvent->load() & 0x01);
VERIFY(wklEvent->load() & 0x02);
VERIFY((wklEvent->load() & 0x20) == 0);
wklEvent->fetch_or(0x20);
}
s32 rc = CELL_OK;
if (!wklF->hook || wklEvent->load() & 0x10)
{
ASSERT(wklF->x28 == 2);
VERIFY(wklF->x28 == 2);
rc = sys_semaphore_post((u32)wklF->sem, 1);
}
@ -1027,7 +1049,7 @@ s32 _spurs::initialize(PPUThread& ppu, vm::ptr<CellSpurs> spurs, u32 revision, u
// Import SPURS kernel
spurs->spuImg.type = SYS_SPU_IMAGE_TYPE_USER;
spurs->spuImg.segs = { vm::alloc(0x40000, vm::main), vm::addr };
spurs->spuImg.segs = vm::cast(vm::alloc(0x40000, vm::main));
spurs->spuImg.entry_point = isSecond ? CELL_SPURS_KERNEL2_ENTRY_ADDR : CELL_SPURS_KERNEL1_ENTRY_ADDR;
spurs->spuImg.nsegs = 1;
@ -2117,8 +2139,8 @@ s32 _spurs::add_workload(vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid, vm::cptr<vo
u32 index = wnum & 0xf;
if (wnum <= 15)
{
ASSERT((spurs->wklCurrentContention[wnum] & 0xf) == 0);
ASSERT((spurs->wklPendingContention[wnum] & 0xf) == 0);
VERIFY((spurs->wklCurrentContention[wnum] & 0xf) == 0);
VERIFY((spurs->wklPendingContention[wnum] & 0xf) == 0);
spurs->wklState1[wnum] = 1;
spurs->wklStatus1[wnum] = 0;
spurs->wklEvent1[wnum] = 0;
@ -2153,8 +2175,8 @@ s32 _spurs::add_workload(vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid, vm::cptr<vo
}
else
{
ASSERT((spurs->wklCurrentContention[index] & 0xf0) == 0);
ASSERT((spurs->wklPendingContention[index] & 0xf0) == 0);
VERIFY((spurs->wklCurrentContention[index] & 0xf0) == 0);
VERIFY((spurs->wklPendingContention[index] & 0xf0) == 0);
spurs->wklState2[index] = 1;
spurs->wklStatus2[index] = 0;
spurs->wklEvent2[index] = 0;
@ -2233,7 +2255,7 @@ s32 _spurs::add_workload(vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid, vm::cptr<vo
v = mask | (0x80000000u >> wnum);
});
ASSERT(res_wkl <= 31);
VERIFY(res_wkl <= 31);
spurs->wklState(wnum).exchange(2);
spurs->sysSrvMsgUpdateWorkload.exchange(0xff);
spurs->sysSrvMessage.exchange(0xff);

View file

@ -8,7 +8,7 @@
#include "cellSpurs.h"
#include "cellSpursJq.h"
LOG_CHANNEL(cellSpursJq);
logs::channel cellSpursJq("cellSpursJq", logs::level::notice);
s32 cellSpursJobQueueAttributeInitialize()
{

View file

@ -9,11 +9,15 @@
#include "Emu/Cell/lv2/sys_spu.h"
#include "cellSpurs.h"
#include <thread>
//----------------------------------------------------------------------------
// Externs
//----------------------------------------------------------------------------
extern _log::channel cellSpurs;
extern logs::channel cellSpurs;
extern std::mutex& get_current_thread_mutex();
//----------------------------------------------------------------------------
// Function prototypes
@ -685,7 +689,7 @@ bool spursKernelEntry(SPUThread& spu)
{
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(100ms);
CHECK_EMU_STATUS;
}
@ -861,7 +865,7 @@ void spursSysServiceIdleHandler(SPUThread& spu, SpursKernelContext* ctxt)
// The system service blocks by making a reservation and waiting on the lock line reservation lost event.
CHECK_EMU_STATUS;
if (!lock) lock.lock();
get_current_thread_cv().wait_for(lock, std::chrono::milliseconds(1));
get_current_thread_cv().wait_for(lock, 1ms);
continue;
}

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellSsl);
logs::channel cellSsl("cellSsl", logs::level::notice);
s32 cellSslInit()
{

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
extern _log::channel cellSysutil;
extern logs::channel cellSysutil;
s32 cellStorageDataImportMove()
{

View file

@ -3,7 +3,7 @@
#include "cellSubdisplay.h"
LOG_CHANNEL(cellSubdisplay);
logs::channel cellSubdisplay("cellSubdisplay", logs::level::notice);
s32 cellSubDisplayInit()
{

View file

@ -8,7 +8,9 @@
#include "Emu/Memory/wait_engine.h"
LOG_CHANNEL(cellSync);
#include <thread>
logs::channel cellSync("cellSync", logs::level::notice);
namespace _sync
{
@ -32,12 +34,12 @@ ppu_error_code cellSyncMutexInitialize(vm::ptr<CellSyncMutex> mutex)
{
cellSync.trace("cellSyncMutexInitialize(mutex=*0x%x)", mutex);
if (!mutex)
if (UNLIKELY(!mutex))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!mutex.aligned())
if (UNLIKELY(!mutex.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -51,12 +53,12 @@ ppu_error_code cellSyncMutexLock(vm::ptr<CellSyncMutex> mutex)
{
cellSync.trace("cellSyncMutexLock(mutex=*0x%x)", mutex);
if (!mutex)
if (UNLIKELY(!mutex))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!mutex.aligned())
if (UNLIKELY(!mutex.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -76,12 +78,12 @@ ppu_error_code cellSyncMutexTryLock(vm::ptr<CellSyncMutex> mutex)
{
cellSync.trace("cellSyncMutexTryLock(mutex=*0x%x)", mutex);
if (!mutex)
if (UNLIKELY(!mutex))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!mutex.aligned())
if (UNLIKELY(!mutex.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -98,12 +100,12 @@ ppu_error_code cellSyncMutexUnlock(vm::ptr<CellSyncMutex> mutex)
{
cellSync.trace("cellSyncMutexUnlock(mutex=*0x%x)", mutex);
if (!mutex)
if (UNLIKELY(!mutex))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!mutex.aligned())
if (UNLIKELY(!mutex.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -119,17 +121,17 @@ ppu_error_code cellSyncBarrierInitialize(vm::ptr<CellSyncBarrier> barrier, u16 t
{
cellSync.trace("cellSyncBarrierInitialize(barrier=*0x%x, total_count=%d)", barrier, total_count);
if (!barrier)
if (UNLIKELY(!barrier))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!barrier.aligned())
if (UNLIKELY(!barrier.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
if (!total_count || total_count > 32767)
if (UNLIKELY(!total_count || total_count > 32767))
{
return CELL_SYNC_ERROR_INVAL;
}
@ -144,12 +146,12 @@ ppu_error_code cellSyncBarrierNotify(vm::ptr<CellSyncBarrier> barrier)
{
cellSync.trace("cellSyncBarrierNotify(barrier=*0x%x)", barrier);
if (!barrier)
if (UNLIKELY(!barrier))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!barrier.aligned())
if (UNLIKELY(!barrier.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -165,12 +167,12 @@ ppu_error_code cellSyncBarrierTryNotify(vm::ptr<CellSyncBarrier> barrier)
{
cellSync.trace("cellSyncBarrierTryNotify(barrier=*0x%x)", barrier);
if (!barrier)
if (UNLIKELY(!barrier))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!barrier.aligned())
if (UNLIKELY(!barrier.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -191,12 +193,12 @@ ppu_error_code cellSyncBarrierWait(vm::ptr<CellSyncBarrier> barrier)
{
cellSync.trace("cellSyncBarrierWait(barrier=*0x%x)", barrier);
if (!barrier)
if (UNLIKELY(!barrier))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!barrier.aligned())
if (UNLIKELY(!barrier.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -214,12 +216,12 @@ ppu_error_code cellSyncBarrierTryWait(vm::ptr<CellSyncBarrier> barrier)
{
cellSync.trace("cellSyncBarrierTryWait(barrier=*0x%x)", barrier);
if (!barrier)
if (UNLIKELY(!barrier))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!barrier.aligned())
if (UNLIKELY(!barrier.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -240,17 +242,17 @@ ppu_error_code cellSyncRwmInitialize(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buf
{
cellSync.trace("cellSyncRwmInitialize(rwm=*0x%x, buffer=*0x%x, buffer_size=0x%x)", rwm, buffer, buffer_size);
if (!rwm || !buffer)
if (UNLIKELY(!rwm || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!rwm.aligned() || buffer % 128)
if (UNLIKELY(!rwm.aligned() || buffer % 128))
{
return CELL_SYNC_ERROR_ALIGN;
}
if (buffer_size % 128 || buffer_size > 0x4000)
if (UNLIKELY(buffer_size % 128 || buffer_size > 0x4000))
{
return CELL_SYNC_ERROR_INVAL;
}
@ -269,12 +271,12 @@ ppu_error_code cellSyncRwmRead(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer)
{
cellSync.trace("cellSyncRwmRead(rwm=*0x%x, buffer=*0x%x)", rwm, buffer);
if (!rwm || !buffer)
if (UNLIKELY(!rwm || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!rwm.aligned())
if (UNLIKELY(!rwm.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -300,12 +302,12 @@ ppu_error_code cellSyncRwmTryRead(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer
{
cellSync.trace("cellSyncRwmTryRead(rwm=*0x%x, buffer=*0x%x)", rwm, buffer);
if (!rwm || !buffer)
if (UNLIKELY(!rwm || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!rwm.aligned())
if (UNLIKELY(!rwm.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -334,12 +336,12 @@ ppu_error_code cellSyncRwmWrite(vm::ptr<CellSyncRwm> rwm, vm::cptr<void> buffer)
{
cellSync.trace("cellSyncRwmWrite(rwm=*0x%x, buffer=*0x%x)", rwm, buffer);
if (!rwm || !buffer)
if (UNLIKELY(!rwm || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!rwm.aligned())
if (UNLIKELY(!rwm.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -365,12 +367,12 @@ ppu_error_code cellSyncRwmTryWrite(vm::ptr<CellSyncRwm> rwm, vm::cptr<void> buff
{
cellSync.trace("cellSyncRwmTryWrite(rwm=*0x%x, buffer=*0x%x)", rwm, buffer);
if (!rwm || !buffer)
if (UNLIKELY(!rwm || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!rwm.aligned())
if (UNLIKELY(!rwm.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -396,22 +398,22 @@ ppu_error_code cellSyncQueueInitialize(vm::ptr<CellSyncQueue> queue, vm::ptr<u8>
{
cellSync.trace("cellSyncQueueInitialize(queue=*0x%x, buffer=*0x%x, size=0x%x, depth=0x%x)", queue, buffer, size, depth);
if (!queue)
if (UNLIKELY(!queue))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (size && !buffer)
if (UNLIKELY(size && !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned() || buffer % 16)
if (UNLIKELY(!queue.aligned() || buffer % 16))
{
return CELL_SYNC_ERROR_ALIGN;
}
if (!depth || size % 16)
if (UNLIKELY(!depth || size % 16))
{
return CELL_SYNC_ERROR_INVAL;
}
@ -431,12 +433,12 @@ ppu_error_code cellSyncQueuePush(vm::ptr<CellSyncQueue> queue, vm::cptr<void> bu
{
cellSync.trace("cellSyncQueuePush(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
if (UNLIKELY(!queue || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -462,12 +464,12 @@ ppu_error_code cellSyncQueueTryPush(vm::ptr<CellSyncQueue> queue, vm::cptr<void>
{
cellSync.trace("cellSyncQueueTryPush(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
if (UNLIKELY(!queue || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -496,12 +498,12 @@ ppu_error_code cellSyncQueuePop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buff
{
cellSync.trace("cellSyncQueuePop(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
if (UNLIKELY(!queue || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -527,12 +529,12 @@ ppu_error_code cellSyncQueueTryPop(vm::ptr<CellSyncQueue> queue, vm::ptr<void> b
{
cellSync.trace("cellSyncQueueTryPop(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
if (UNLIKELY(!queue || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -561,12 +563,12 @@ ppu_error_code cellSyncQueuePeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void> buf
{
cellSync.trace("cellSyncQueuePeek(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
if (UNLIKELY(!queue || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -592,12 +594,12 @@ ppu_error_code cellSyncQueueTryPeek(vm::ptr<CellSyncQueue> queue, vm::ptr<void>
{
cellSync.trace("cellSyncQueueTryPeek(queue=*0x%x, buffer=*0x%x)", queue, buffer);
if (!queue || !buffer)
if (UNLIKELY(!queue || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -626,12 +628,12 @@ ppu_error_code cellSyncQueueSize(vm::ptr<CellSyncQueue> queue)
{
cellSync.trace("cellSyncQueueSize(queue=*0x%x)", queue);
if (!queue)
if (UNLIKELY(!queue))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -645,12 +647,12 @@ ppu_error_code cellSyncQueueClear(vm::ptr<CellSyncQueue> queue)
{
cellSync.trace("cellSyncQueueClear(queue=*0x%x)", queue);
if (!queue)
if (UNLIKELY(!queue))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -713,30 +715,30 @@ ppu_error_code cellSyncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::cpt
{
cellSync.warning("cellSyncLFQueueInitialize(queue=*0x%x, buffer=*0x%x, size=0x%x, depth=0x%x, direction=%d, eaSignal=*0x%x)", queue, buffer, size, depth, direction, eaSignal);
if (!queue)
if (UNLIKELY(!queue))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (size)
{
if (!buffer)
if (UNLIKELY(!buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (size > 0x4000 || size % 16)
if (UNLIKELY(size > 0x4000 || size % 16))
{
return CELL_SYNC_ERROR_INVAL;
}
}
if (!depth || depth > 0x7fff || direction > 3)
if (UNLIKELY(!depth || depth > 0x7fff || direction > 3))
{
return CELL_SYNC_ERROR_INVAL;
}
if (!queue.aligned() || buffer % 16)
if (UNLIKELY(!queue.aligned() || buffer % 16))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -764,7 +766,7 @@ ppu_error_code cellSyncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::cpt
if (old)
{
if (sdk_ver > 0x17ffff && old != 2)
if (UNLIKELY(sdk_ver > 0x17ffff && old != 2))
{
return CELL_SYNC_ERROR_STAT;
}
@ -777,7 +779,7 @@ ppu_error_code cellSyncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::cpt
{
for (const auto& data : vm::_ref<u64[16]>(queue.addr()))
{
if (data)
if (UNLIKELY(data))
{
return CELL_SYNC_ERROR_STAT;
}
@ -793,14 +795,14 @@ ppu_error_code cellSyncLFQueueInitialize(vm::ptr<CellSyncLFQueue> queue, vm::cpt
if (old_value == 2)
{
if (queue->m_size != size || queue->m_depth != depth || queue->m_buffer != buffer)
if (UNLIKELY(queue->m_size != size || queue->m_depth != depth || queue->m_buffer != buffer))
{
return CELL_SYNC_ERROR_INVAL;
}
if (sdk_ver > 0x17ffff)
{
if (queue->m_eaSignal != eaSignal || queue->m_direction != direction)
if (UNLIKELY(queue->m_eaSignal != eaSignal || queue->m_direction != direction))
{
return CELL_SYNC_ERROR_INVAL;
}
@ -822,7 +824,7 @@ ppu_error_code _cellSyncLFQueueGetPushPointer(PPUThread& ppu, vm::ptr<CellSyncLF
{
cellSync.warning("_cellSyncLFQueueGetPushPointer(queue=*0x%x, pointer=*0x%x, isBlocking=%d, useEventQueue=%d)", queue, pointer, isBlocking, useEventQueue);
if (queue->m_direction != CELL_SYNC_QUEUE_PPU2SPU)
if (UNLIKELY(queue->m_direction != CELL_SYNC_QUEUE_PPU2SPU))
{
return CELL_SYNC_ERROR_PERM;
}
@ -906,7 +908,7 @@ ppu_error_code _cellSyncLFQueueGetPushPointer(PPUThread& ppu, vm::ptr<CellSyncLF
}
}
ASSERT(sys_event_queue_receive(ppu, queue->m_eq_id, vm::null, 0) == CELL_OK);
VERIFY(sys_event_queue_receive(ppu, queue->m_eq_id, vm::null, 0) == CELL_OK);
var1 = 1;
}
}
@ -923,7 +925,7 @@ ppu_error_code _cellSyncLFQueueCompletePushPointer(PPUThread& ppu, vm::ptr<CellS
{
cellSync.warning("_cellSyncLFQueueCompletePushPointer(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x)", queue, pointer, fpSendSignal);
if (queue->m_direction != CELL_SYNC_QUEUE_PPU2SPU)
if (UNLIKELY(queue->m_direction != CELL_SYNC_QUEUE_PPU2SPU))
{
return CELL_SYNC_ERROR_PERM;
}
@ -997,7 +999,7 @@ ppu_error_code _cellSyncLFQueueCompletePushPointer(PPUThread& ppu, vm::ptr<CellS
if (var9 > 1 && (u32)var8 > 1)
{
ASSERT(16 - var2 <= 1);
VERIFY(16 - var2 <= 1);
}
s32 var11 = (pack >> 10) & 0x1f;
@ -1029,11 +1031,11 @@ ppu_error_code _cellSyncLFQueueCompletePushPointer(PPUThread& ppu, vm::ptr<CellS
if (queue->push2.compare_and_swap_test(old, push2))
{
ASSERT(var2 + var4 < 16);
VERIFY(var2 + var4 < 16);
if (var6 != -1)
{
ASSERT(queue->push3.compare_and_swap_test(old2, push3));
ASSERT(fpSendSignal);
VERIFY(queue->push3.compare_and_swap_test(old2, push3));
VERIFY(fpSendSignal);
return NOT_AN_ERROR(fpSendSignal(ppu, (u32)queue->m_eaSignal.addr(), var6));
}
else
@ -1064,12 +1066,12 @@ ppu_error_code _cellSyncLFQueuePushBody(PPUThread& ppu, vm::ptr<CellSyncLFQueue>
// cellSyncLFQueuePush has 1 in isBlocking param, cellSyncLFQueueTryPush has 0
cellSync.warning("_cellSyncLFQueuePushBody(queue=*0x%x, buffer=*0x%x, isBlocking=%d)", queue, buffer, isBlocking);
if (!queue || !buffer)
if (UNLIKELY(!queue || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned() || buffer % 16)
if (UNLIKELY(!queue.aligned() || buffer % 16))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1098,7 +1100,7 @@ ppu_error_code _cellSyncLFQueuePushBody(PPUThread& ppu, vm::ptr<CellSyncLFQueue>
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
std::this_thread::sleep_for(1ms); // hack
}
const s32 depth = queue->m_depth;
@ -1121,7 +1123,7 @@ ppu_error_code _cellSyncLFQueueGetPopPointer(PPUThread& ppu, vm::ptr<CellSyncLFQ
{
cellSync.warning("_cellSyncLFQueueGetPopPointer(queue=*0x%x, pointer=*0x%x, isBlocking=%d, arg4=%d, useEventQueue=%d)", queue, pointer, isBlocking, arg4, useEventQueue);
if (queue->m_direction != CELL_SYNC_QUEUE_SPU2PPU)
if (UNLIKELY(queue->m_direction != CELL_SYNC_QUEUE_SPU2PPU))
{
return CELL_SYNC_ERROR_PERM;
}
@ -1205,7 +1207,7 @@ ppu_error_code _cellSyncLFQueueGetPopPointer(PPUThread& ppu, vm::ptr<CellSyncLFQ
}
}
ASSERT(sys_event_queue_receive(ppu, queue->m_eq_id, vm::null, 0) == CELL_OK);
VERIFY(sys_event_queue_receive(ppu, queue->m_eq_id, vm::null, 0) == CELL_OK);
var1 = 1;
}
}
@ -1223,7 +1225,7 @@ ppu_error_code _cellSyncLFQueueCompletePopPointer(PPUThread& ppu, vm::ptr<CellSy
// arguments copied from _cellSyncLFQueueCompletePushPointer + unknown argument (noQueueFull taken from LFQueue2CompletePopPointer)
cellSync.warning("_cellSyncLFQueueCompletePopPointer(queue=*0x%x, pointer=%d, fpSendSignal=*0x%x, noQueueFull=%d)", queue, pointer, fpSendSignal, noQueueFull);
if (queue->m_direction != CELL_SYNC_QUEUE_SPU2PPU)
if (UNLIKELY(queue->m_direction != CELL_SYNC_QUEUE_SPU2PPU))
{
return CELL_SYNC_ERROR_PERM;
}
@ -1301,7 +1303,7 @@ ppu_error_code _cellSyncLFQueueCompletePopPointer(PPUThread& ppu, vm::ptr<CellSy
if (var9 > 1 && (u32)var8 > 1)
{
ASSERT(16 - var2 <= 1);
VERIFY(16 - var2 <= 1);
}
s32 var11 = (pack >> 10) & 0x1f;
@ -1331,8 +1333,8 @@ ppu_error_code _cellSyncLFQueueCompletePopPointer(PPUThread& ppu, vm::ptr<CellSy
{
if (var6 != -1)
{
ASSERT(queue->pop3.compare_and_swap_test(old2, pop3));
ASSERT(fpSendSignal);
VERIFY(queue->pop3.compare_and_swap_test(old2, pop3));
VERIFY(fpSendSignal);
return NOT_AN_ERROR(fpSendSignal(ppu, (u32)queue->m_eaSignal.addr(), var6));
}
else
@ -1363,12 +1365,12 @@ ppu_error_code _cellSyncLFQueuePopBody(PPUThread& ppu, vm::ptr<CellSyncLFQueue>
// cellSyncLFQueuePop has 1 in isBlocking param, cellSyncLFQueueTryPop has 0
cellSync.warning("_cellSyncLFQueuePopBody(queue=*0x%x, buffer=*0x%x, isBlocking=%d)", queue, buffer, isBlocking);
if (!queue || !buffer)
if (UNLIKELY(!queue || !buffer))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned() || buffer % 16)
if (UNLIKELY(!queue.aligned() || buffer % 16))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1397,7 +1399,7 @@ ppu_error_code _cellSyncLFQueuePopBody(PPUThread& ppu, vm::ptr<CellSyncLFQueue>
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
std::this_thread::sleep_for(1ms); // hack
}
const s32 depth = queue->m_depth;
@ -1420,12 +1422,12 @@ ppu_error_code cellSyncLFQueueClear(vm::ptr<CellSyncLFQueue> queue)
{
cellSync.warning("cellSyncLFQueueClear(queue=*0x%x)", queue);
if (!queue)
if (UNLIKELY(!queue))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1471,12 +1473,12 @@ ppu_error_code cellSyncLFQueueSize(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32>
{
cellSync.warning("cellSyncLFQueueSize(queue=*0x%x, size=*0x%x)", queue, size);
if (!queue || !size)
if (UNLIKELY(!queue || !size))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1508,12 +1510,12 @@ ppu_error_code cellSyncLFQueueDepth(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u32>
{
cellSync.trace("cellSyncLFQueueDepth(queue=*0x%x, depth=*0x%x)", queue, depth);
if (!queue || !depth)
if (UNLIKELY(!queue || !depth))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1527,12 +1529,12 @@ ppu_error_code _cellSyncLFQueueGetSignalAddress(vm::cptr<CellSyncLFQueue> queue,
{
cellSync.trace("_cellSyncLFQueueGetSignalAddress(queue=*0x%x, ppSignal=**0x%x)", queue, ppSignal);
if (!queue || !ppSignal)
if (UNLIKELY(!queue || !ppSignal))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1546,12 +1548,12 @@ ppu_error_code cellSyncLFQueueGetDirection(vm::cptr<CellSyncLFQueue> queue, vm::
{
cellSync.trace("cellSyncLFQueueGetDirection(queue=*0x%x, direction=*0x%x)", queue, direction);
if (!queue || !direction)
if (UNLIKELY(!queue || !direction))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}
@ -1565,12 +1567,12 @@ ppu_error_code cellSyncLFQueueGetEntrySize(vm::cptr<CellSyncLFQueue> queue, vm::
{
cellSync.trace("cellSyncLFQueueGetEntrySize(queue=*0x%x, entry_size=*0x%x)", queue, entry_size);
if (!queue || !entry_size)
if (UNLIKELY(!queue || !entry_size))
{
return CELL_SYNC_ERROR_NULL_POINTER;
}
if (!queue.aligned())
if (UNLIKELY(!queue.aligned()))
{
return CELL_SYNC_ERROR_ALIGN;
}

View file

@ -6,7 +6,7 @@
#include "Utilities/StrUtil.h"
LOG_CHANNEL(cellSync2);
logs::channel cellSync2("cellSync2", logs::level::notice);
vm::gvar<CellSync2CallerThreadType> gCellSync2CallerThreadTypePpuThread;
vm::gvar<CellSync2Notifier> gCellSync2NotifierPpuThread;

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellSysconf);
logs::channel cellSysconf("cellSysconf", logs::level::notice);
s32 cellSysconfAbort()
{

View file

@ -2,7 +2,7 @@
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellSysmodule);
logs::channel cellSysmodule("cellSysmodule", logs::level::notice);
enum
{

View file

@ -1,4 +1,5 @@
#include "stdafx.h"
#include "Utilities/Config.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
@ -7,7 +8,7 @@
#include "Utilities/StrUtil.h"
LOG_CHANNEL(cellSysutil);
logs::channel cellSysutil("cellSysutil", logs::level::notice);
// Temporarily
using sys_callbacks_t = std::array<std::pair<vm::ptr<CellSysutilCallback>, vm::ptr<void>>, 4>;
@ -53,43 +54,47 @@ cfg::map_entry<s32> g_cfg_sys_language(cfg::root.sys, "Language",
{ "English (UK)", CELL_SYSUTIL_LANG_ENGLISH_GB },
});
static const char* get_systemparam_id_name(s32 id)
{
static thread_local char tls_id_name[16]; // for test
switch (id)
{
case CELL_SYSUTIL_SYSTEMPARAM_ID_LANG: return "ID_LANG";
case CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN: return "ID_ENTER_BUTTON_ASSIGN";
case CELL_SYSUTIL_SYSTEMPARAM_ID_DATE_FORMAT: return "ID_DATE_FORMAT";
case CELL_SYSUTIL_SYSTEMPARAM_ID_TIME_FORMAT: return "ID_TIME_FORMAT";
case CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE: return "ID_TIMEZONE";
case CELL_SYSUTIL_SYSTEMPARAM_ID_SUMMERTIME: return "ID_SUMMERTIME";
case CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL: return "ID_GAME_PARENTAL_LEVEL";
case CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL0_RESTRICT: return "ID_GAME_PARENTAL_LEVEL0_RESTRICT";
case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USER_HAS_NP_ACCOUNT: return "ID_CURRENT_USER_HAS_NP_ACCOUNT";
case CELL_SYSUTIL_SYSTEMPARAM_ID_CAMERA_PLFREQ: return "ID_CAMERA_PLFREQ";
case CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_RUMBLE: return "ID_PAD_RUMBLE";
case CELL_SYSUTIL_SYSTEMPARAM_ID_KEYBOARD_TYPE: return "ID_KEYBOARD_TYPE";
case CELL_SYSUTIL_SYSTEMPARAM_ID_JAPANESE_KEYBOARD_ENTRY_METHOD: return "ID_JAPANESE_KEYBOARD_ENTRY_METHOD";
case CELL_SYSUTIL_SYSTEMPARAM_ID_CHINESE_KEYBOARD_ENTRY_METHOD: return "ID_CHINESE_KEYBOARD_ENTRY_METHOD";
case CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_AUTOOFF: return "ID_PAD_AUTOOFF";
case CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME: return "ID_NICKNAME";
case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME: return "ID_CURRENT_USERNAME";
}
std::snprintf(tls_id_name, sizeof(tls_id_name), "0x%04X", id);
return tls_id_name;
}
enum class systemparam_id_name : s32 {};
template<>
struct unveil<systemparam_id_name, void>
{
static inline const char* get(systemparam_id_name arg)
struct temp
{
return get_systemparam_id_name((s32)arg);
s32 value;
char buf[12];
temp(systemparam_id_name value)
: value(s32(value))
{
}
};
static inline const char* get(temp&& in)
{
switch (in.value)
{
case CELL_SYSUTIL_SYSTEMPARAM_ID_LANG: return "ID_LANG";
case CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN: return "ID_ENTER_BUTTON_ASSIGN";
case CELL_SYSUTIL_SYSTEMPARAM_ID_DATE_FORMAT: return "ID_DATE_FORMAT";
case CELL_SYSUTIL_SYSTEMPARAM_ID_TIME_FORMAT: return "ID_TIME_FORMAT";
case CELL_SYSUTIL_SYSTEMPARAM_ID_TIMEZONE: return "ID_TIMEZONE";
case CELL_SYSUTIL_SYSTEMPARAM_ID_SUMMERTIME: return "ID_SUMMERTIME";
case CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL: return "ID_GAME_PARENTAL_LEVEL";
case CELL_SYSUTIL_SYSTEMPARAM_ID_GAME_PARENTAL_LEVEL0_RESTRICT: return "ID_GAME_PARENTAL_LEVEL0_RESTRICT";
case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USER_HAS_NP_ACCOUNT: return "ID_CURRENT_USER_HAS_NP_ACCOUNT";
case CELL_SYSUTIL_SYSTEMPARAM_ID_CAMERA_PLFREQ: return "ID_CAMERA_PLFREQ";
case CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_RUMBLE: return "ID_PAD_RUMBLE";
case CELL_SYSUTIL_SYSTEMPARAM_ID_KEYBOARD_TYPE: return "ID_KEYBOARD_TYPE";
case CELL_SYSUTIL_SYSTEMPARAM_ID_JAPANESE_KEYBOARD_ENTRY_METHOD: return "ID_JAPANESE_KEYBOARD_ENTRY_METHOD";
case CELL_SYSUTIL_SYSTEMPARAM_ID_CHINESE_KEYBOARD_ENTRY_METHOD: return "ID_CHINESE_KEYBOARD_ENTRY_METHOD";
case CELL_SYSUTIL_SYSTEMPARAM_ID_PAD_AUTOOFF: return "ID_PAD_AUTOOFF";
case CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME: return "ID_NICKNAME";
case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME: return "ID_CURRENT_USERNAME";
}
std::snprintf(in.buf, sizeof(in.buf), "!0x%04X", in.value);
return in.buf;
}
};
@ -170,7 +175,7 @@ s32 cellSysutilGetSystemParamInt(s32 id, vm::ptr<s32> value)
s32 cellSysutilGetSystemParamString(s32 id, vm::ptr<char> buf, u32 bufsize)
{
cellSysutil.trace("cellSysutilGetSystemParamString(id=0x%x(%s), buf=*0x%x, bufsize=%d)", id, get_systemparam_id_name(id), buf, bufsize);
cellSysutil.trace("cellSysutilGetSystemParamString(id=0x%x(%s), buf=*0x%x, bufsize=%d)", id, systemparam_id_name(id), buf, bufsize);
memset(buf.get_ptr(), 0, bufsize);
@ -255,7 +260,7 @@ s32 cellSysCacheMount(vm::ptr<CellSysCacheParam> param)
cellSysutil.warning("cellSysCacheMount(param=*0x%x)", param);
const std::string& cache_id = param->cacheId;
ASSERT(cache_id.size() < sizeof(param->cacheId));
VERIFY(cache_id.size() < sizeof(param->cacheId));
const std::string& cache_path = "/dev_hdd1/cache/" + cache_id + '/';
strcpy_trunc(param->getCachePath, cache_path);

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellSysutilAp);
logs::channel cellSysutilAp("cellSysutilAp", logs::level::notice);
// Return Codes
enum

View file

@ -1,7 +1,7 @@
#include "stdafx.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(cellSysutilAvc);
logs::channel cellSysutilAvc("cellSysutilAvc", logs::level::notice);
s32 cellSysutilAvcByeRequest()
{

Some files were not shown because too many files have changed in this diff Show more