mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-01-22 01:30:35 -05:00
3ds: Various fixes, optimizations.
This commit does the following changes: - Fix mkdir implementation not reporting EEXIST error. - Fix database build feature. - Small speed-up when parsing directories and files. - Fix buffering thread hogging cpu and preventing other threads to run. - Fix sdl plugins not compiling by re-adding ctru specific cflags in sdl.make. Change-Id: I507c0dcc85cdbcc607ab9c9c6d0b42e6a80caa5a
This commit is contained in:
parent
0777add596
commit
752467dee4
6 changed files with 240 additions and 78 deletions
|
|
@ -39,6 +39,12 @@ SDLFLAGS = -I$(SDL_SRCDIR)/include $(filter-out -O%,$(PLUGINFLAGS)) \
|
|||
#-ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations \
|
||||
#-D_GNU_SOURCE=1 -D_REENTRANT -DSDL -DELF
|
||||
|
||||
# CTRU does need these to avoid compiler errors
|
||||
ifeq ($(APP_TYPE),ctru-app)
|
||||
SDLFLAGS += -Wno-int-conversion -Wno-incompatible-pointer-types \
|
||||
-Wno-implicit-function-declaration -Wno-implicit-int
|
||||
endif
|
||||
|
||||
ifndef APP_TYPE
|
||||
### no target has a big enough plugin buffer
|
||||
ROCKS += $(SDL_OBJDIR)/duke3d.ovl
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@
|
|||
|
||||
#include "bfile.h"
|
||||
|
||||
/* Define LOGF_ENABLE to enable logf output in this file */
|
||||
#if 0
|
||||
#define LOGF_ENABLE
|
||||
#endif
|
||||
#include "logf.h"
|
||||
|
||||
// rw mutex implementation
|
||||
void sync_RWMutexInit(sync_RWMutex *m) {
|
||||
LightLock_Init(&m->shared);
|
||||
|
|
@ -63,12 +69,14 @@ void sync_RWMutexUnlock(sync_RWMutex *m) {
|
|||
file_error_t readPage(PageReader *p, u64 offset)
|
||||
{
|
||||
u32 read_bytes = 0;
|
||||
if (R_FAILED(FSFILE_Read(p->file,
|
||||
&read_bytes,
|
||||
offset,
|
||||
p->buffer,
|
||||
p->size))) {
|
||||
printf("readPage: FSFILE_Read failed (I/O Error)\n");
|
||||
Result res;
|
||||
res = FSFILE_Read(p->file,
|
||||
&read_bytes,
|
||||
offset,
|
||||
p->buffer,
|
||||
p->size);
|
||||
if (R_FAILED(res)) {
|
||||
logf("readPage: 0x%lx\n", R_DESCRIPTION(res));
|
||||
return "I/O Error";
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +89,7 @@ file_error_t readPage(PageReader *p, u64 offset)
|
|||
p->start = offset;
|
||||
p->end = offset + p->size;
|
||||
|
||||
/* printf("page: 0x%llx, 0x%llx, %lld (last_page: %s)\n", p->start, p->end, p->size, p->isLastPage == true ? "true": "false"); */
|
||||
logf("page: 0x%llx, 0x%llx, %lld (last_page: %s)\n", p->start, p->end, p->size, p->isLastPage == true ? "true": "false");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -89,18 +97,18 @@ PageReader* NewPageReader(Handle file, s64 pageSize)
|
|||
{
|
||||
PageReader *p = (PageReader *) malloc(sizeof(PageReader));
|
||||
if (p == NULL) {
|
||||
printf("NewPageReader: memory error\n");
|
||||
logf("NewPageReader: memory error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->buffer = (u8 *) malloc(sizeof(u8) * pageSize);
|
||||
p->buffer = malloc(sizeof(u8) * pageSize);
|
||||
if (p->buffer == NULL) {
|
||||
printf("NewPagereader: memory error (buffer)\n");
|
||||
logf("NewPagereader: memory error (buffer)\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// clear buffer data
|
||||
memset(p->buffer, 0x0, sizeof(u8) + pageSize);
|
||||
memset(p->buffer, 0x0, sizeof(u8) * pageSize);
|
||||
|
||||
p->start = 0;
|
||||
p->end = 0;
|
||||
|
|
@ -140,6 +148,27 @@ int_error_t PageReader_ReadAt(PageReader *p, u8 *buffer, size_t size, off_t offs
|
|||
{
|
||||
bool eof = false;
|
||||
|
||||
// only use page_reader if buffer size is smaller than page size
|
||||
if (size > p->size) {
|
||||
// direct file access (fs.h)
|
||||
u32 bytes_read = 0;
|
||||
Result res = FSFILE_Read(p->file,
|
||||
&bytes_read,
|
||||
offset,
|
||||
buffer,
|
||||
size);
|
||||
if (R_FAILED(res)) {
|
||||
return (int_error_t) { R_DESCRIPTION(res), "I/O Error" };
|
||||
}
|
||||
|
||||
// io.EOF
|
||||
if (bytes_read == 0) {
|
||||
return (int_error_t) { 0, "io.EOF" };
|
||||
}
|
||||
|
||||
return (int_error_t) { bytes_read, NULL };
|
||||
}
|
||||
|
||||
// higher probability, buffer is in cached page range
|
||||
if ((offset >= p->start) && ((offset + size) < p->end)) {
|
||||
copyPage(p, buffer, size, offset);
|
||||
|
|
@ -147,16 +176,14 @@ int_error_t PageReader_ReadAt(PageReader *p, u8 *buffer, size_t size, off_t offs
|
|||
}
|
||||
|
||||
// less higher probability, read new page at offset
|
||||
if (p->isLastPage == false) {
|
||||
file_error_t err = readPage(p, offset);
|
||||
if (err != NULL) {
|
||||
return (int_error_t) { -1, "I/O Error" };
|
||||
}
|
||||
|
||||
// we could have reached last page here so continue to
|
||||
// last page handling
|
||||
file_error_t err = readPage(p, offset);
|
||||
if (err != NULL) {
|
||||
return (int_error_t) { -1, "I/O Error" };
|
||||
}
|
||||
|
||||
// we could have reached last page here so continue to
|
||||
// last page handling
|
||||
|
||||
// lower probability, we are at the last page
|
||||
|
||||
// trying to read past end of file
|
||||
|
|
@ -173,3 +200,130 @@ int_error_t PageReader_ReadAt(PageReader *p, u8 *buffer, size_t size, off_t offs
|
|||
copyPage(p, buffer, size, offset);
|
||||
return (int_error_t) { size, eof == true ? "io.EOF" : NULL };
|
||||
}
|
||||
|
||||
int_error_t PageReader_WriteAt(PageReader *p, u8 *buffer, size_t size, off_t offset, bool flush_cache)
|
||||
{
|
||||
// we will use direct file access for writing (fs.h)
|
||||
u32 written = 0;
|
||||
Result res = FSFILE_Write(p->file,
|
||||
&written,
|
||||
offset,
|
||||
buffer,
|
||||
size,
|
||||
FS_WRITE_FLUSH);
|
||||
if (R_FAILED(res)) {
|
||||
return (int_error_t) { -1, "I/O Error" };
|
||||
}
|
||||
|
||||
if (flush_cache) {
|
||||
/* logf("PageReader_WriteAt: flush cache\n"); */
|
||||
// reload current page for O_RDWR files
|
||||
// read ahead first page buffer from file
|
||||
file_error_t err = readPage(p, p->start);
|
||||
if (err != NULL) {
|
||||
return (int_error_t) { -1, "I/O Error" };
|
||||
}
|
||||
}
|
||||
|
||||
return (int_error_t) { written, NULL };
|
||||
}
|
||||
|
||||
// page reader implementation for directory entries
|
||||
file_error_t readPageDirectory(PageReader *p)
|
||||
{
|
||||
u32 entries_read = 0;
|
||||
FS_DirectoryEntry *dirEntries = (FS_DirectoryEntry *) p->buffer;
|
||||
Result result = FSDIR_Read(p->file,
|
||||
&entries_read,
|
||||
p->size,
|
||||
dirEntries);
|
||||
|
||||
if (R_FAILED(result)) {
|
||||
logf("FSDIR_Read: 0x%lx\n", R_DESCRIPTION(result));
|
||||
return "I/O Error";
|
||||
}
|
||||
|
||||
// we reached directory end
|
||||
if (entries_read == 0) {
|
||||
return "io.EOF";
|
||||
}
|
||||
|
||||
if (entries_read < p->size) {
|
||||
p->isLastPage = true;
|
||||
}
|
||||
|
||||
p->size = entries_read;
|
||||
p->start = 0;
|
||||
p->end = p->size;
|
||||
|
||||
/* logf("page: 0x%llx, 0x%llx, %lld (last_page: %s)\n", p->start, p->end, p->size, p->isLastPage == true ? "true": "false"); */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PageReader *NewPageReaderDirectory(Handle file, s64 pageSize)
|
||||
{
|
||||
PageReader *p = (PageReader *) malloc(sizeof(PageReader));
|
||||
if (p == NULL) {
|
||||
logf("NewPageReaderDirectory: memory error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// round buffer size to sizeof(FS_DirectoryEntry)
|
||||
int maxDirEntries = pageSize / sizeof(FS_DirectoryEntry);
|
||||
|
||||
p->buffer = malloc(sizeof(FS_DirectoryEntry) * maxDirEntries);
|
||||
if (p->buffer == NULL) {
|
||||
logf("NewPageReaderDirectory: memory error (buffer)\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// clear buffer data
|
||||
memset(p->buffer, 0x0, sizeof(FS_DirectoryEntry) * maxDirEntries);
|
||||
|
||||
p->start = 0;
|
||||
p->end = 0;
|
||||
p->isLastPage = false;
|
||||
p->size = maxDirEntries;
|
||||
p->file = file;
|
||||
|
||||
// read ahead first page buffer from file
|
||||
file_error_t err = readPageDirectory(p);
|
||||
if (err != NULL) {
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline void copyEntry(PageReader *p, FS_DirectoryEntry *entry)
|
||||
{
|
||||
const FS_DirectoryEntry *dirEntries = (FS_DirectoryEntry *) p->buffer;
|
||||
memcpy(entry, &dirEntries[p->start], sizeof(FS_DirectoryEntry));
|
||||
p->start ++;
|
||||
}
|
||||
|
||||
int_error_t PageReader_ReadDir(PageReader *p, FS_DirectoryEntry *entry)
|
||||
{
|
||||
// higher probability, entry is in cached page range
|
||||
if (p->start < p->end) {
|
||||
copyEntry(p, entry);
|
||||
return (int_error_t) { 1, NULL};
|
||||
}
|
||||
|
||||
// less higher probability, read a new page
|
||||
file_error_t err = readPageDirectory(p);
|
||||
|
||||
// end of directory?
|
||||
if (err != NULL) {
|
||||
if (!strcmp(err, "io.EOF")) {
|
||||
return (int_error_t) { 0, "io.EOF" };
|
||||
}
|
||||
else {
|
||||
return (int_error_t) { -1, "I/O Error" };
|
||||
}
|
||||
}
|
||||
|
||||
copyEntry(p, entry);
|
||||
return (int_error_t) { 1, NULL};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,24 @@
|
|||
|
||||
#include "bfile-internal.h"
|
||||
|
||||
static const int defaultPageSize = 0x80000; // default page buffer size, 512 kB
|
||||
static const int defaultPageSize = 0x20000; // default page buffer size, 128 kB
|
||||
|
||||
// NewPageReader creates a new PageReader struct with pageSize
|
||||
// NewPageReader creates a new PageReader struct with pageSize.
|
||||
PageReader *NewPageReader(Handle file, s64 pageSize);
|
||||
|
||||
// Free all memory associated to the PageReader pointer
|
||||
// Free all memory associated to the PageReader pointer.
|
||||
void PageReader_Free(PageReader *p);
|
||||
|
||||
// ReadAt reads size bytes from the PageReader starting at offset.
|
||||
int_error_t PageReader_ReadAt(PageReader *p, u8 *buffer, size_t size, off_t offset);
|
||||
|
||||
// WriteAt writes size bytes from the PageReader starting at offset.
|
||||
int_error_t PageReader_WriteAt(PageReader *p, u8 *buffer, size_t size, off_t offset, bool flush_cache);
|
||||
|
||||
// NewPageReader creates a new PageReader struct with pageSize, for directory use.
|
||||
PageReader *NewPageReaderDirectory(Handle file, s64 pageSize);
|
||||
|
||||
// ReadAt reads one directory entry from memory.
|
||||
int_error_t PageReader_ReadDir(PageReader *p, FS_DirectoryEntry *entry);
|
||||
|
||||
#endif /* _B_FILE_H_ */
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ static struct dirstr_desc
|
|||
struct dirent entry; /* current parsed entry information */
|
||||
} open_streams[MAX_OPEN_DIRS] =
|
||||
{
|
||||
[0 ... MAX_OPEN_FILES-1] = { .stream = { .handle = 0 } }
|
||||
[0 ... MAX_OPEN_FILES-1] = { .stream = { .cache = NULL } }
|
||||
};
|
||||
|
||||
extern FS_Archive sdmcArchive;
|
||||
|
|
@ -58,7 +58,7 @@ static struct dirstr_desc * get_dirstr(DIR *dirp)
|
|||
|
||||
if (!PTR_IN_ARRAY(open_streams, dir, MAX_OPEN_DIRS))
|
||||
dir = NULL;
|
||||
else if (dir->stream.handle != 0)
|
||||
else if (dir->stream.cache != NULL)
|
||||
return dir;
|
||||
|
||||
int errnum;
|
||||
|
|
@ -103,7 +103,7 @@ static struct dirstr_desc * alloc_dirstr(void)
|
|||
for (unsigned int dd = 0; dd < MAX_OPEN_DIRS; dd++)
|
||||
{
|
||||
struct dirstr_desc *dir = &open_streams[dd];
|
||||
if (dir->stream.handle == 0)
|
||||
if (dir->stream.cache == NULL)
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
|
@ -151,6 +151,11 @@ DIR * ctru_opendir(const char *dirname)
|
|||
FILE_ERROR(EMFILE, -1);
|
||||
}
|
||||
|
||||
dir->stream.cache = NewPageReaderDirectory(dir->stream.handle, defaultPageSize);
|
||||
if (dir->stream.cache == NULL) {
|
||||
FILE_ERROR(ERRNO, -2);
|
||||
}
|
||||
|
||||
dir->stream.size = 0;
|
||||
dir->stream.flags = 0;
|
||||
|
||||
|
|
@ -159,6 +164,10 @@ DIR * ctru_opendir(const char *dirname)
|
|||
|
||||
dirp = (DIR *)dir;
|
||||
file_error:
|
||||
if (dir->stream.handle != 0) {
|
||||
FSDIR_Close(dir->stream.handle);
|
||||
dir->stream.handle = 0;
|
||||
}
|
||||
file_internal_unlock_WRITER();
|
||||
return dirp;
|
||||
}
|
||||
|
|
@ -177,12 +186,15 @@ int ctru_closedir(DIR *dirp)
|
|||
|
||||
logf("closedir(dirname=\"%s\")\n", dir->stream.path);
|
||||
|
||||
if (dir->stream.handle == 0)
|
||||
if (dir->stream.cache == NULL)
|
||||
{
|
||||
logf("dir #%d: dir not open\n", (int)(dir - open_streams));
|
||||
FILE_ERROR(EBADF, -2);
|
||||
}
|
||||
|
||||
PageReader_Free(dir->stream.cache);
|
||||
dir->stream.cache = NULL;
|
||||
|
||||
Result res = FSDIR_Close(dir->stream.handle);
|
||||
if (R_FAILED(res))
|
||||
FILE_ERROR(ERRNO, -3);
|
||||
|
|
@ -233,16 +245,12 @@ struct dirent * ctru_readdir(DIR *dirp)
|
|||
|
||||
logf("readdir(dirname=\"%s\")\n", dir->stream.path);
|
||||
|
||||
u32 dataRead = 0;
|
||||
FS_DirectoryEntry dirEntry;
|
||||
Result result = FSDIR_Read(dir->stream.handle,
|
||||
&dataRead,
|
||||
1,
|
||||
&dirEntry);
|
||||
if (R_FAILED(result))
|
||||
int_error_t n_err = PageReader_ReadDir(dir->stream.cache, &dirEntry);
|
||||
if (n_err.n < 0)
|
||||
FILE_ERROR(EIO, _RC);
|
||||
|
||||
if (dataRead == 0) {
|
||||
if (n_err.n == 0) {
|
||||
/* directory end. return NULL value, no errno */
|
||||
res = NULL;
|
||||
goto file_error;
|
||||
|
|
@ -274,6 +282,15 @@ file_error:
|
|||
return res;
|
||||
}
|
||||
|
||||
/* libctru result.h description values appear to be missing
|
||||
FSUSER_CreateDirectory return values */
|
||||
|
||||
enum
|
||||
{
|
||||
RD_DIRECTORY_ALREADY_EXISTS = 0xBE,
|
||||
RD_MISSING_PARENT_DIRECTORY = 0x78,
|
||||
};
|
||||
|
||||
/* make a directory */
|
||||
int ctru_mkdir(const char *path)
|
||||
{
|
||||
|
|
@ -286,8 +303,14 @@ int ctru_mkdir(const char *path)
|
|||
Result res = FSUSER_CreateDirectory(sdmcArchive,
|
||||
fsMakePath(PATH_ASCII, path),
|
||||
0);
|
||||
if (R_FAILED(res))
|
||||
if (R_FAILED(res)) {
|
||||
if (R_DESCRIPTION(res) == RD_DIRECTORY_ALREADY_EXISTS)
|
||||
FILE_ERROR(ERRNO, EEXIST);
|
||||
if (R_DESCRIPTION(res) == RD_MISSING_PARENT_DIRECTORY)
|
||||
FILE_ERROR(ERRNO, ENOENT);
|
||||
/* Unknown error */
|
||||
FILE_ERROR(ERRNO, -1);
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
file_error:
|
||||
|
|
|
|||
|
|
@ -235,46 +235,17 @@ static ssize_t readwrite(struct filestr_desc *file, void *buf, size_t nbyte,
|
|||
int_error_t n_err;
|
||||
|
||||
if (write) {
|
||||
// we will use direct file access for writing
|
||||
u32 written = 0;
|
||||
Result res = FSFILE_Write(file->stream.handle,
|
||||
&written,
|
||||
AtomicLoad(&file->offset),
|
||||
buf,
|
||||
nbyte,
|
||||
FS_WRITE_FLUSH);
|
||||
if (R_FAILED(res)) {
|
||||
n_err.err = "I/O error";
|
||||
}
|
||||
|
||||
n_err.n = written;
|
||||
n_err = PageReader_WriteAt(file->stream.cache,
|
||||
buf,
|
||||
nbyte,
|
||||
AtomicLoad(&file->offset),
|
||||
file->stream.flags & O_RDWR ? true : false);
|
||||
}
|
||||
else {
|
||||
// only use page_reader if buffer size is smaller than page size
|
||||
if (nbyte < file->stream.cache->size) {
|
||||
n_err = PageReader_ReadAt(file->stream.cache,
|
||||
(u8 *) buf,
|
||||
nbyte,
|
||||
AtomicLoad(&file->offset));
|
||||
}
|
||||
else {
|
||||
u32 bytes_read = 0;
|
||||
Result res = FSFILE_Read(file->stream.handle,
|
||||
&bytes_read,
|
||||
AtomicLoad(&file->offset),
|
||||
buf,
|
||||
nbyte);
|
||||
if (R_FAILED(res)) {
|
||||
n_err.err = "I/O error";
|
||||
}
|
||||
|
||||
// io.EOF
|
||||
if (bytes_read == 0) {
|
||||
n_err.err = "io.EOF";
|
||||
}
|
||||
|
||||
n_err.n = bytes_read;
|
||||
}
|
||||
n_err = PageReader_ReadAt(file->stream.cache,
|
||||
buf,
|
||||
nbyte,
|
||||
AtomicLoad(&file->offset));
|
||||
}
|
||||
|
||||
if ((n_err.err != NULL) && strcmp(n_err.err, "io.EOF")) {
|
||||
|
|
|
|||
|
|
@ -78,12 +78,12 @@ int get_ctru_thread_priority(int priority)
|
|||
(priority == PRIORITY_REALTIME))
|
||||
return 0x18;
|
||||
else if (priority == PRIORITY_BUFFERING)
|
||||
return 0x18; /* Highest */
|
||||
return 0x2F;
|
||||
else if ((priority == PRIORITY_USER_INTERFACE) || (priority == PRIORITY_RECORDING) ||
|
||||
(priority == PRIORITY_PLAYBACK))
|
||||
return 0x30;
|
||||
else if (priority == PRIORITY_PLAYBACK_MAX)
|
||||
return 0x2F;
|
||||
else if (priority == PRIORITY_PLAYBACK_MAX)
|
||||
return 0x20;
|
||||
else if (priority == PRIORITY_SYSTEM)
|
||||
return 0x30;
|
||||
else if (priority == PRIORITY_BACKGROUND)
|
||||
|
|
@ -208,8 +208,8 @@ sysThread *sys_create_thread(int(*fn)(void *), const char *name, const size_t st
|
|||
thread->userdata = data;
|
||||
thread->stacksize = stacksize;
|
||||
|
||||
int cpu = -1;
|
||||
if (name && (strncmp(name, "tagcache", 8) == 0) && R_SUCCEEDED(APT_SetAppCpuTimeLimit(30))) {
|
||||
int cpu = 0;
|
||||
if (name && (strncmp(name, "buffering", 9) == 0) && R_SUCCEEDED(APT_SetAppCpuTimeLimit(30))) {
|
||||
cpu = 1;
|
||||
printf("thread: %s, running in cpu 1\n", name);
|
||||
}
|
||||
|
|
@ -400,4 +400,3 @@ int sys_cond_wait(sysCond *cond, RecursiveLock *mutex)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue