mirror of https://gitlab.com/nakst/essence
pipe read short mode; pipe tests
This commit is contained in:
parent
9c4c48505d
commit
3595c43fd7
|
@ -1027,6 +1027,95 @@ bool UTF8Tests() {
|
|||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
EsHandle pipeRead, pipeWrite;
|
||||
|
||||
void PipeTestsThread2(EsGeneric) {
|
||||
for (uint16_t i = 0; i < 1000; i++) {
|
||||
EsPipeWrite(pipeWrite, &i, sizeof(i));
|
||||
}
|
||||
|
||||
uint16_t *buffer = (uint16_t *) EsHeapAllocate(10000, false);
|
||||
|
||||
for (uint16_t i = 0; i < 1000; i++) {
|
||||
for (uintptr_t i = 0; i < 5000; i++) buffer[i] = i;
|
||||
EsPipeWrite(pipeWrite, buffer, 10000);
|
||||
}
|
||||
|
||||
uint16_t s = 0x1234;
|
||||
EsPipeWrite(pipeWrite, &s, sizeof(s));
|
||||
EsSleep(2000);
|
||||
s = 0xFEDC;
|
||||
EsPipeWrite(pipeWrite, &s, sizeof(s));
|
||||
EsHandleClose(pipeWrite);
|
||||
|
||||
EsHeapFree(buffer);
|
||||
}
|
||||
|
||||
void PipeTestsThread3(EsGeneric) {
|
||||
uint8_t data[200];
|
||||
EsPipeRead(pipeRead, data, sizeof(data), false);
|
||||
EsHandleClose(pipeRead);
|
||||
}
|
||||
|
||||
bool PipeTests() {
|
||||
EsPipeCreate(&pipeRead, &pipeWrite);
|
||||
|
||||
int checkIndex = 0;
|
||||
EsThreadInformation information;
|
||||
CHECK(EsThreadCreate(PipeTestsThread2, &information, nullptr) == ES_SUCCESS);
|
||||
EsHandleClose(information.handle);
|
||||
|
||||
for (uint16_t i = 0; i < 1000; i++) {
|
||||
uint16_t j;
|
||||
CHECK(sizeof(j) == EsPipeRead(pipeRead, &j, sizeof(j), true));
|
||||
CHECK(i == j);
|
||||
}
|
||||
|
||||
uint16_t *buffer = (uint16_t *) EsHeapAllocate(10000, false);
|
||||
|
||||
for (uint16_t i = 0; i < 1000; i++) {
|
||||
EsMemoryZero(buffer, 10000);
|
||||
uintptr_t position = 0;
|
||||
|
||||
while (position < 10000) {
|
||||
size_t read = EsPipeRead(pipeRead, (uint8_t *) buffer + position, 10000 - position, i >= 500);
|
||||
if (i < 500) CHECK(read == 10000);
|
||||
CHECK(read);
|
||||
position += read;
|
||||
}
|
||||
|
||||
CHECK(position == 10000);
|
||||
|
||||
for (uintptr_t i = 0; i < 5000; i++) CHECK(buffer[i] == i);
|
||||
}
|
||||
|
||||
EsSleep(1000);
|
||||
|
||||
uint32_t s = 0x5678ABCD;
|
||||
CHECK(2 == EsPipeRead(pipeRead, &s, sizeof(s), true));
|
||||
CHECK(s == 0x56781234); // TODO Big endian support.
|
||||
s = 0x5678ABCD;
|
||||
CHECK(2 == EsPipeRead(pipeRead, &s, sizeof(s), false));
|
||||
CHECK(s == 0x5678FEDC); // TODO Big endian support.
|
||||
CHECK(0 == EsPipeRead(pipeRead, &s, sizeof(s), false));
|
||||
|
||||
EsHandleClose(pipeRead);
|
||||
|
||||
EsPipeCreate(&pipeRead, &pipeWrite);
|
||||
CHECK(EsThreadCreate(PipeTestsThread3, &information, nullptr) == ES_SUCCESS);
|
||||
EsHandleClose(information.handle);
|
||||
size_t written = EsPipeWrite(pipeWrite, buffer, 10000);
|
||||
CHECK(written > 0 && written < 10000); // The actual amountn written depends on the size of the internal pipe buffer, and whether the read happens in time.
|
||||
CHECK(0 == EsPipeWrite(pipeWrite, buffer, 10000));
|
||||
EsHandleClose(pipeWrite);
|
||||
|
||||
EsHeapFree(buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
|
||||
const Test tests[] = {
|
||||
|
@ -1041,6 +1130,7 @@ const Test tests[] = {
|
|||
TEST(ArenaRandomAllocations, 60),
|
||||
TEST(RangeSetTests, 60),
|
||||
TEST(UTF8Tests, 60),
|
||||
TEST(PipeTests, 60),
|
||||
};
|
||||
|
||||
#ifndef API_TESTS_FOR_RUNNER
|
||||
|
|
|
@ -1723,20 +1723,20 @@ void DesktopRequestThread(EsGeneric argument) {
|
|||
EsObjectID embeddedWindowID;
|
||||
|
||||
while (true) {
|
||||
bytes = EsPipeRead(process->desktopRequestPipe, &length, sizeof(length));
|
||||
bytes = EsPipeRead(process->desktopRequestPipe, &length, sizeof(length), false);
|
||||
if (bytes != sizeof(length)) break; // Process has terminated or closed the pipe.
|
||||
bytes = EsPipeRead(process->desktopRequestPipe, &embeddedWindowID, sizeof(embeddedWindowID));
|
||||
bytes = EsPipeRead(process->desktopRequestPipe, &embeddedWindowID, sizeof(embeddedWindowID), false);
|
||||
if (bytes != sizeof(embeddedWindowID)) break; // Process has terminated or closed the pipe.
|
||||
|
||||
if (length < 1 || length > DESKTOP_MESSAGE_SIZE_LIMIT) {
|
||||
// Discard the message.
|
||||
// TODO Crash the process.
|
||||
EsPipeRead(process->desktopRequestPipe, nullptr, length);
|
||||
EsPipeRead(process->desktopRequestPipe, nullptr, length, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
void *buffer = EsHeapAllocate(length, false);
|
||||
bytes = EsPipeRead(process->desktopRequestPipe, buffer, length);
|
||||
bytes = EsPipeRead(process->desktopRequestPipe, buffer, length, false);
|
||||
if (bytes != length) break; // Process has terminated or closed the pipe.
|
||||
|
||||
if (!buffer) {
|
||||
|
|
|
@ -2239,7 +2239,7 @@ function bool EsMouseIsMiddleHeld();
|
|||
// Pipes.
|
||||
|
||||
function void EsPipeCreate(EsHandle *readEnd, EsHandle *writeEnd);
|
||||
function size_t EsPipeRead(EsHandle pipe, void *buffer, size_t bytes); // If buffer is null, then the data is discarded.
|
||||
function size_t EsPipeRead(EsHandle pipe, void *buffer, size_t bytes, bool allowShortReads); // If buffer is null, then the data is discarded. If allowShortReads is false, then the call will block until the buffer is full or there are no writers; if allowShortReads is true, then the call will block until the buffer is non-empty or there are no writers. Note that the modes are equivalent iff bytes is 0 or 1.
|
||||
function size_t EsPipeWrite(EsHandle pipe, const void *buffer, size_t bytes);
|
||||
|
||||
// Synchronisation and timing.
|
||||
|
|
|
@ -769,12 +769,12 @@ void MessageDesktop(void *message, size_t messageBytes, EsHandle embeddedWindow
|
|||
EsPipeWrite(api.desktopRequestPipe, &length, sizeof(length));
|
||||
EsPipeWrite(api.desktopRequestPipe, &embeddedWindowID, sizeof(embeddedWindowID));
|
||||
EsPipeWrite(api.desktopRequestPipe, message, messageBytes);
|
||||
EsPipeRead(api.desktopResponsePipe, &length, sizeof(length));
|
||||
EsAssert(sizeof(length) == EsPipeRead(api.desktopResponsePipe, &length, sizeof(length), false));
|
||||
EsAssert((length != 0) == (responseBuffer != 0));
|
||||
|
||||
while (length) {
|
||||
char buffer[4096];
|
||||
size_t bytesRead = EsPipeRead(api.desktopResponsePipe, buffer, sizeof(buffer) > length ? length : sizeof(buffer));
|
||||
size_t bytesRead = EsPipeRead(api.desktopResponsePipe, buffer, sizeof(buffer) > length ? length : sizeof(buffer), false);
|
||||
if (!bytesRead) break;
|
||||
EsBufferWrite(responseBuffer, buffer, bytesRead);
|
||||
length -= bytesRead;
|
||||
|
@ -904,12 +904,37 @@ void EsPipeCreate(EsHandle *readEnd, EsHandle *writeEnd) {
|
|||
EsSyscall(ES_SYSCALL_PIPE_CREATE, (uintptr_t) readEnd, (uintptr_t) writeEnd, 0, 0);
|
||||
}
|
||||
|
||||
size_t EsPipeRead(EsHandle pipe, void *buffer, size_t bytes) {
|
||||
return EsSyscall(ES_SYSCALL_PIPE_READ, pipe, (uintptr_t) buffer, bytes, 0);
|
||||
size_t EsPipeRead(EsHandle pipe, void *buffer, size_t bytes, bool allowShortReads) {
|
||||
if (!bytes) {
|
||||
return 0;
|
||||
} else if (allowShortReads) {
|
||||
return EsSyscall(ES_SYSCALL_PIPE_READ, pipe, (uintptr_t) buffer, bytes, 0);
|
||||
} else {
|
||||
size_t position = 0;
|
||||
|
||||
while (position != bytes) {
|
||||
size_t read = EsPipeRead(pipe, buffer ? ((uint8_t *) buffer + position) : nullptr, bytes - position, true);
|
||||
|
||||
if (!read) {
|
||||
// There are no writers.
|
||||
break;
|
||||
} else {
|
||||
// Keeping reading until the buffer is full.
|
||||
position += read;
|
||||
EsAssert(position <= bytes);
|
||||
}
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
||||
size_t EsPipeWrite(EsHandle pipe, const void *buffer, size_t bytes) {
|
||||
return EsSyscall(ES_SYSCALL_PIPE_WRITE, pipe, (uintptr_t) buffer, bytes, 0);
|
||||
if (bytes) {
|
||||
return EsSyscall(ES_SYSCALL_PIPE_WRITE, pipe, (uintptr_t) buffer, bytes, 0);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
EsError EsDeviceControl(EsHandle handle, EsDeviceControlType type, void *dp, void *dq) {
|
||||
|
|
|
@ -778,6 +778,10 @@ void ParseApplicationManifest(const char *manifestPath) {
|
|||
manifest = s.buffer = (char *) LoadFile(manifestPath, &s.bytes);
|
||||
}
|
||||
|
||||
if (!manifest) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *require = "";
|
||||
bool needsNativeToolchain = false;
|
||||
bool disabled = false;
|
||||
|
@ -840,7 +844,8 @@ void ParseApplicationManifest(const char *manifestPath) {
|
|||
}
|
||||
|
||||
if (disabled || (require[0] && !FileExists(require))
|
||||
|| (needsNativeToolchain && !hasNativeToolchain)) {
|
||||
|| (needsNativeToolchain && !hasNativeToolchain)
|
||||
|| !application.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue