pipe read short mode; pipe tests

This commit is contained in:
nakst 2022-01-07 09:59:28 +00:00
parent 9c4c48505d
commit 3595c43fd7
5 changed files with 131 additions and 11 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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.

View File

@ -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) {

View File

@ -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;
}