mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-09-08 19:12:56 +02:00
Implement save state serialization for WASI file descriptors in libretro builds
This commit is contained in:
parent
057b6dc95d
commit
e957af931c
5 changed files with 57 additions and 7 deletions
|
@ -125,6 +125,10 @@ sandbox::~sandbox() {
|
||||||
wasm2c_ruby_free(RB);
|
wasm2c_ruby_free(RB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sandbox::sandbox_serialize_fdtable(void *&data, wasm_size_t &max_size) const {
|
||||||
|
return wasi->sandbox_serialize(data, max_size);
|
||||||
|
}
|
||||||
|
|
||||||
Movie *sandbox::get_movie_from_main_thread() {
|
Movie *sandbox::get_movie_from_main_thread() {
|
||||||
return movie.load(std::memory_order_relaxed); // No need for synchronization because we always set the movie from the main thread
|
return movie.load(std::memory_order_relaxed); // No need for synchronization because we always set the movie from the main thread
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ namespace mkxp_sandbox {
|
||||||
inline struct mkxp_sandbox::bindings *operator->() noexcept { return &*bindings; }
|
inline struct mkxp_sandbox::bindings *operator->() noexcept { return &*bindings; }
|
||||||
sandbox();
|
sandbox();
|
||||||
~sandbox();
|
~sandbox();
|
||||||
|
bool sandbox_serialize_fdtable(void *&data, wasm_size_t &max_size) const;
|
||||||
Movie *get_movie_from_main_thread();
|
Movie *get_movie_from_main_thread();
|
||||||
Movie *get_movie_from_audio_thread();
|
Movie *get_movie_from_audio_thread();
|
||||||
void set_movie(Movie *new_movie);
|
void set_movie(Movie *new_movie);
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "wasi.h"
|
#include "wasi.h"
|
||||||
#include "binding-base.h"
|
#include "binding-base.h"
|
||||||
|
#include "sandbox-serial-util.h"
|
||||||
|
|
||||||
using namespace mkxp_sandbox;
|
using namespace mkxp_sandbox;
|
||||||
|
|
||||||
|
@ -36,11 +37,11 @@ static inline size_t strlen_safe(const char *str, size_t max_length) {
|
||||||
return ptr == nullptr ? max_length : ptr - str;
|
return ptr == nullptr ? max_length : ptr - str;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fs_dir *wasi_file_entry::dir_handle() {
|
struct fs_dir *wasi_file_entry::dir_handle() const noexcept {
|
||||||
return (struct fs_dir *)handle;
|
return (struct fs_dir *)handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileSystem::File *wasi_file_entry::file_handle() {
|
struct FileSystem::File *wasi_file_entry::file_handle() const noexcept {
|
||||||
return (struct FileSystem::File *)handle;
|
return (struct FileSystem::File *)handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +129,42 @@ const char *wasi_t::str(wasm_ptr_t address) const noexcept {
|
||||||
return sandbox_str(*ruby, address);
|
return sandbox_str(*ruby, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wasi_t::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const {
|
||||||
|
if (!::sandbox_serialize((wasm_size_t)fdtable.size(), data, max_size)) return false;
|
||||||
|
|
||||||
|
wasm_size_t num_free_handles = 0;
|
||||||
|
|
||||||
|
for (const struct wasi_file_entry &entry : fdtable) {
|
||||||
|
if (entry.type == wasi_fd_type::FSDIR) {
|
||||||
|
if (num_free_handles > 0) {
|
||||||
|
if (!::sandbox_serialize((uint8_t)0, data, max_size)) return false;
|
||||||
|
if (!::sandbox_serialize(num_free_handles, data, max_size)) return false;
|
||||||
|
num_free_handles = 0;
|
||||||
|
}
|
||||||
|
if (!::sandbox_serialize((uint8_t)1, data, max_size)) return false;
|
||||||
|
if (!::sandbox_serialize(entry.dir_handle()->path, data, max_size)) return false;
|
||||||
|
if (!::sandbox_serialize(entry.dir_handle()->root->path, data, max_size)) return false;
|
||||||
|
} else if (entry.type == wasi_fd_type::FSFILE) {
|
||||||
|
if (num_free_handles > 0) {
|
||||||
|
if (!::sandbox_serialize((uint8_t)0, data, max_size)) return false;
|
||||||
|
if (!::sandbox_serialize(num_free_handles, data, max_size)) return false;
|
||||||
|
num_free_handles = 0;
|
||||||
|
}
|
||||||
|
if (!::sandbox_serialize((uint8_t)2, data, max_size)) return false;
|
||||||
|
if (!::sandbox_serialize(entry.file_handle()->path(), data, max_size)) return false;
|
||||||
|
} else {
|
||||||
|
++num_free_handles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num_free_handles > 0) {
|
||||||
|
if (!::sandbox_serialize((uint8_t)0, data, max_size)) return false;
|
||||||
|
if (!::sandbox_serialize(num_free_handles, data, max_size)) return false;
|
||||||
|
num_free_handles = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" uint32_t w2c_wasi__snapshot__preview1_args_get(wasi_t *wasi, wasm_ptr_t argv, wasm_ptr_t argv_buf) {
|
extern "C" uint32_t w2c_wasi__snapshot__preview1_args_get(wasi_t *wasi, wasm_ptr_t argv, wasm_ptr_t argv_buf) {
|
||||||
return WASI_ESUCCESS;
|
return WASI_ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,8 +181,8 @@ struct wasi_file_entry {
|
||||||
// The file/directory handle that the file descriptor corresponds to. The exact type of this handle depends on the type of file descriptor.
|
// The file/directory handle that the file descriptor corresponds to. The exact type of this handle depends on the type of file descriptor.
|
||||||
void *handle;
|
void *handle;
|
||||||
|
|
||||||
struct fs_dir *dir_handle();
|
struct fs_dir *dir_handle() const noexcept;
|
||||||
struct FileSystem::File *file_handle();
|
struct FileSystem::File *file_handle() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct w2c_wasi__snapshot__preview1 {
|
typedef struct w2c_wasi__snapshot__preview1 {
|
||||||
|
@ -230,6 +230,8 @@ typedef struct w2c_wasi__snapshot__preview1 {
|
||||||
template <typename T> void arycpy(mkxp_sandbox::wasm_ptr_t dst_address, const T *src, mkxp_sandbox::wasm_size_t num_elements) const noexcept {
|
template <typename T> void arycpy(mkxp_sandbox::wasm_ptr_t dst_address, const T *src, mkxp_sandbox::wasm_size_t num_elements) const noexcept {
|
||||||
mkxp_sandbox::sandbox_arycpy(*ruby, dst_address, src, num_elements);
|
mkxp_sandbox::sandbox_arycpy(*ruby, dst_address, src, num_elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const;
|
||||||
} wasi_t;
|
} wasi_t;
|
||||||
|
|
||||||
#endif /* MKXPZ_SANDBOX_WASI_H */
|
#endif /* MKXPZ_SANDBOX_WASI_H */
|
||||||
|
|
12
src/core.cpp
12
src/core.cpp
|
@ -1639,10 +1639,12 @@ extern "C" RETRO_API bool retro_serialize(void *data, size_t len) {
|
||||||
if (!Graphics::sandbox_serialize_movie(sb().get_movie_from_main_thread(), data, max_size)) return false;
|
if (!Graphics::sandbox_serialize_movie(sb().get_movie_from_main_thread(), data, max_size)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: write the file descriptor table
|
// Write the open WASI file descriptors
|
||||||
|
if (!sb().sandbox_serialize_fdtable(data, max_size)) return false;
|
||||||
|
|
||||||
// Write each object
|
// Write the number of objects, then each object
|
||||||
OBJECTS_BEGIN;
|
OBJECTS_BEGIN;
|
||||||
|
if (!sandbox_serialize((wasm_size_t)sb()->get_objects().size(), data, max_size)) OBJECTS_END_FAIL;
|
||||||
wasm_size_t num_free_objects = 0;
|
wasm_size_t num_free_objects = 0;
|
||||||
for (const auto &object : sb()->get_objects()) {
|
for (const auto &object : sb()->get_objects()) {
|
||||||
if (object.typenum == 0) {
|
if (object.typenum == 0) {
|
||||||
|
@ -1665,7 +1667,10 @@ extern "C" RETRO_API bool retro_serialize(void *data, size_t len) {
|
||||||
num_free_objects = 0;
|
num_free_objects = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write each extra object that was found during serialization of the normal objects
|
// Write the number of extra objects that were found during serialization of the normal objects, then each such object
|
||||||
|
if (max_size < sizeof(wasm_size_t)) OBJECTS_END_FAIL;
|
||||||
|
wasm_size_t *num_extra_objects_ptr = (wasm_size_t *)data;
|
||||||
|
ADVANCE(sizeof(wasm_size_t));
|
||||||
for (size_t i = 0; i < extra_objects.size(); ++i) { // More items can be added to this vector during iteration
|
for (size_t i = 0; i < extra_objects.size(); ++i) { // More items can be added to this vector during iteration
|
||||||
const void *ptr = std::get<0>(extra_objects[i]);
|
const void *ptr = std::get<0>(extra_objects[i]);
|
||||||
wasm_size_t typenum = std::get<1>(extra_objects[i]);
|
wasm_size_t typenum = std::get<1>(extra_objects[i]);
|
||||||
|
@ -1683,6 +1688,7 @@ extern "C" RETRO_API bool retro_serialize(void *data, size_t len) {
|
||||||
if (!sandbox_serialize(num_free_objects, data, max_size)) OBJECTS_END_FAIL;
|
if (!sandbox_serialize(num_free_objects, data, max_size)) OBJECTS_END_FAIL;
|
||||||
num_free_objects = 0;
|
num_free_objects = 0;
|
||||||
}
|
}
|
||||||
|
*num_extra_objects_ptr = (wasm_size_t)extra_objects.size();
|
||||||
|
|
||||||
OBJECTS_END;
|
OBJECTS_END;
|
||||||
std::memset(data, 0, max_size);
|
std::memset(data, 0, max_size);
|
||||||
|
|
Loading…
Add table
Reference in a new issue