cellFsAioWrite implemented

This commit is contained in:
Nekotekina 2015-03-14 14:29:26 +03:00
parent ea8473943b
commit 5cb1a2f26d

View File

@ -634,97 +634,70 @@ s32 cellFsSdataOpenByFd(u32 mself_fd, s32 flags, vm::ptr<u32> sdata_fd, u64 offs
return CELL_OK; return CELL_OK;
} }
std::atomic<s32> g_FsAioReadID(0); std::mutex g_fs_aio_mutex;
std::atomic<s32> g_FsAioReadCur(0);
bool aio_init = false;
void fsAioRead(u32 fd, vm::ptr<CellFsAio> aio, int xid, vm::ptr<void(vm::ptr<CellFsAio> xaio, int error, int xid, u64 size)> func) using fs_aio_cb_t = vm::ptr<void(vm::ptr<CellFsAio> xaio, s32 error, s32 xid, u64 size)>;
void fsAioRead(vm::ptr<CellFsAio> aio, s32 xid, fs_aio_cb_t func)
{ {
while (g_FsAioReadCur != xid) std::lock_guard<std::mutex> lock(g_fs_aio_mutex);
s32 error = CELL_OK;
u64 nread = 0;
std::shared_ptr<fs_file_t> file;
if (!Emu.GetIdManager().GetIDData(aio->fd, file) || file->flags & CELL_FS_O_WRONLY)
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack error = CELL_FS_EBADF;
if (Emu.IsStopped()) }
{ else
cellFs.Warning("fsAioRead() aborted"); {
return; const auto old_position = file->file->Tell();
}
file->file->Seek(aio->offset);
nread = file->file->Read(aio->buf.get_ptr(), aio->size);
file->file->Seek(old_position);
} }
u32 error = CELL_OK; // should be executed directly by FS AIO thread
u64 res = 0; Emu.GetCallbackManager().Async([func, aio, error, xid, nread](PPUThread& CPU)
{ {
std::shared_ptr<fs_file_t> orig_file; func(CPU, aio, error, xid, nread);
if (!Emu.GetIdManager().GetIDData(fd, orig_file)) });
{
cellFs.Error("Wrong fd (%s)", fd);
Emu.Pause();
return;
}
u64 nbytes = aio->size;
vfsStream& file = *orig_file->file;
const u64 old_pos = file.Tell();
file.Seek((u64)aio->offset);
if (nbytes != (u32)nbytes)
{
error = CELL_ENOMEM;
}
else
{
res = nbytes ? file.Read(aio->buf.get_ptr(), nbytes) : 0;
}
file.Seek(old_pos);
cellFs.Log("*** fsAioRead(fd=%d, offset=0x%llx, buf=0x%x, size=0x%llx, error=0x%x, res=0x%llx, xid=0x%x)",
fd, aio->offset, aio->buf, aio->size, error, res, xid);
}
if (func)
{
Emu.GetCallbackManager().Async([func, aio, error, xid, res](PPUThread& CPU)
{
func(CPU, aio, error, xid, res);
});
}
g_FsAioReadCur++;
} }
s32 cellFsAioRead(vm::ptr<CellFsAio> aio, vm::ptr<s32> id, vm::ptr<void(vm::ptr<CellFsAio> xaio, s32 error, s32 xid, u64 size)> func) void fsAioWrite(vm::ptr<CellFsAio> aio, s32 xid, fs_aio_cb_t func)
{ {
cellFs.Warning("cellFsAioRead(aio=*0x%x, id=*0x%x, func=*0x%x)", aio, id, func); std::lock_guard<std::mutex> lock(g_fs_aio_mutex);
if (!aio_init) s32 error = CELL_OK;
u64 nwritten = 0;
std::shared_ptr<fs_file_t> file;
if (!Emu.GetIdManager().GetIDData(aio->fd, file) || !(file->flags & CELL_FS_O_ACCMODE))
{ {
return CELL_ENXIO; error = CELL_FS_EBADF;
}
else
{
const auto old_position = file->file->Tell();
file->file->Seek(aio->offset);
nwritten = file->file->Write(aio->buf.get_ptr(), aio->size);
file->file->Seek(old_position);
} }
std::shared_ptr<fs_file_t> orig_file; // should be executed directly by FS AIO thread
u32 fd = aio->fd; Emu.GetCallbackManager().Async([func, aio, error, xid, nwritten](PPUThread& CPU)
if (!Emu.GetIdManager().GetIDData(fd, orig_file))
{ {
return CELL_EBADF; func(CPU, aio, error, xid, nwritten);
} });
//get a unique id for the callback (may be used by cellFsAioCancel)
const s32 xid = g_FsAioReadID++;
*id = xid;
thread_t t("CellFsAio Reading Thread", std::bind(fsAioRead, fd, aio, xid, func));
return CELL_OK;
}
s32 cellFsAioWrite(vm::ptr<CellFsAio> aio, vm::ptr<s32> id, vm::ptr<void(vm::ptr<CellFsAio> xaio, s32 error, s32 xid, u64 size)> func)
{
cellFs.Todo("cellFsAioWrite(aio=*0x%x, id=*0x%x, func=*0x%x)", aio, id, func);
// TODO:
return CELL_OK;
} }
s32 cellFsAioInit(vm::ptr<const char> mount_point) s32 cellFsAioInit(vm::ptr<const char> mount_point)
@ -732,7 +705,8 @@ s32 cellFsAioInit(vm::ptr<const char> mount_point)
cellFs.Warning("cellFsAioInit(mount_point=*0x%x)", mount_point); cellFs.Warning("cellFsAioInit(mount_point=*0x%x)", mount_point);
cellFs.Warning("*** mount_point = '%s'", mount_point.get_ptr()); cellFs.Warning("*** mount_point = '%s'", mount_point.get_ptr());
aio_init = true; // TODO: create AIO thread (if not exists) for specified mount point
return CELL_OK; return CELL_OK;
} }
@ -741,10 +715,54 @@ s32 cellFsAioFinish(vm::ptr<const char> mount_point)
cellFs.Warning("cellFsAioFinish(mount_point=*0x%x)", mount_point); cellFs.Warning("cellFsAioFinish(mount_point=*0x%x)", mount_point);
cellFs.Warning("*** mount_point = '%s'", mount_point.get_ptr()); cellFs.Warning("*** mount_point = '%s'", mount_point.get_ptr());
//aio_init = false; // TODO: delete existing AIO thread for specified mount point
return CELL_OK; return CELL_OK;
} }
std::atomic<s32> g_fs_aio_id(0);
s32 cellFsAioRead(vm::ptr<CellFsAio> aio, vm::ptr<s32> id, fs_aio_cb_t func)
{
cellFs.Warning("cellFsAioRead(aio=*0x%x, id=*0x%x, func=*0x%x)", aio, id, func);
if (!Emu.GetIdManager().CheckID<fs_file_t>(aio->fd))
{
return CELL_FS_EBADF;
}
// TODO: detect mount point and send AIO request to the AIO thread of this mount point
thread_t("FS AIO Read Thread", std::bind(fsAioRead, aio, (*id = ++g_fs_aio_id), func)).detach();
return CELL_OK;
}
s32 cellFsAioWrite(vm::ptr<CellFsAio> aio, vm::ptr<s32> id, fs_aio_cb_t func)
{
cellFs.Todo("cellFsAioWrite(aio=*0x%x, id=*0x%x, func=*0x%x)", aio, id, func);
if (!Emu.GetIdManager().CheckID<fs_file_t>(aio->fd))
{
return CELL_FS_EBADF;
}
// TODO: detect mount point and send AIO request to the AIO thread of this mount point
thread_t("FS AIO Write Thread", std::bind(fsAioWrite, aio, (*id = ++g_fs_aio_id), func)).detach();
return CELL_OK;
}
s32 cellFsAioCancel(s32 id)
{
cellFs.Todo("cellFsAioCancel(id=%d) -> CELL_FS_EINVAL", id);
// TODO: cancelled requests return CELL_FS_ECANCELED through their own callbacks
return CELL_FS_EINVAL;
}
s32 cellFsSetDefaultContainer(u32 id, u32 total_limit) s32 cellFsSetDefaultContainer(u32 id, u32 total_limit)
{ {
cellFs.Todo("cellFsSetDefaultContainer(id=%d, total_limit=%d)", id, total_limit); cellFs.Todo("cellFsSetDefaultContainer(id=%d, total_limit=%d)", id, total_limit);
@ -765,10 +783,6 @@ s32 cellFsSetIoBufferFromDefaultContainer(u32 fd, u32 buffer_size, u32 page_type
Module cellFs("cellFs", []() Module cellFs("cellFs", []()
{ {
g_FsAioReadID = 0;
g_FsAioReadCur = 0;
aio_init = false;
REG_FUNC(cellFs, cellFsOpen); REG_FUNC(cellFs, cellFsOpen);
REG_FUNC(cellFs, cellFsSdataOpen); REG_FUNC(cellFs, cellFsSdataOpen);
REG_FUNC(cellFs, cellFsSdataOpenByFd); REG_FUNC(cellFs, cellFsSdataOpenByFd);
@ -790,10 +804,11 @@ Module cellFs("cellFs", []()
REG_FUNC(cellFs, cellFsFtruncate); REG_FUNC(cellFs, cellFsFtruncate);
REG_FUNC(cellFs, cellFsTruncate); REG_FUNC(cellFs, cellFsTruncate);
REG_FUNC(cellFs, cellFsFGetBlockSize); REG_FUNC(cellFs, cellFsFGetBlockSize);
REG_FUNC(cellFs, cellFsAioRead);
REG_FUNC(cellFs, cellFsAioWrite);
REG_FUNC(cellFs, cellFsAioInit); REG_FUNC(cellFs, cellFsAioInit);
REG_FUNC(cellFs, cellFsAioFinish); REG_FUNC(cellFs, cellFsAioFinish);
REG_FUNC(cellFs, cellFsAioRead);
REG_FUNC(cellFs, cellFsAioWrite);
REG_FUNC(cellFs, cellFsAioCancel);
REG_FUNC(cellFs, cellFsGetBlockSize); REG_FUNC(cellFs, cellFsGetBlockSize);
REG_FUNC(cellFs, cellFsGetFreeSize); REG_FUNC(cellFs, cellFsGetFreeSize);
REG_FUNC(cellFs, cellFsReadWithOffset); REG_FUNC(cellFs, cellFsReadWithOffset);