add ntfs.sys standalone driver target, change default usb vhd layout formatting to ntfs, implement Fat32CreateDir for directory creation support in the fat32 file system driver, add a dedicated HAL serial output endpoint for COM1 writes in hal_serial.c and subscribe serial to HAL text streams, introduce waitable kernel timers with KeTimerCreate, KeTimerSet, and KeTimerCancel alongside spinlock-protected global timer list initialization and scheduler tick tracking, implement SyscallWriteFileAsync system call for asynchronous non-blocking file writes, refactor NetSocketConnect and NetSocketSendTo to use generic SYS_SOCKET_ADDRESS_K structures instead of being hardcoded to IPv4, update gethostbyname and DNS name resolution to support IPv6 parsing via ResolveNameFamily, update tcpserve.exe with -4 and -6 command-line flags to accept and display IPv6 addresses, append size and version headers to all kernel telemetry and statistics structures including SYS_PMM_STATS, SYS_CPU_STATS, and SYS_SCHEDULER_STATS, update winmm timeGetTime to look up high-resolution hardware frequencies via SysGetTickFrequency, integrate 14 native smoke test applications.
This commit is contained in:
1 parent
2c4a68a75f
commit
ed3d065abd
156 files changed
+10509
-2643
No files matched your search
@@ -0,0 +1,246 @@
|
||||
// Native would-block and queue-timeout contract smoke test.
|
||||
// Verifies that queue try, finite-timeout, and infinite-wait requests return distinct statuses.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
#define TEST_FILL_LIMIT 1024u
|
||||
#define TEST_MESSAGE_WAKE 0x77616b65u
|
||||
#define TEST_WAKE_VALUE 0x12345678u
|
||||
|
||||
typedef struct TEST_QUEUE_MESSAGE {
|
||||
uint32_t Type;
|
||||
uint32_t Flags;
|
||||
uint64_t Param[6];
|
||||
} TEST_QUEUE_MESSAGE;
|
||||
|
||||
typedef char TEST_QUEUE_MESSAGE_SIZE_CHECK[
|
||||
(sizeof(TEST_QUEUE_MESSAGE) == SYS_QUEUE_MESSAGE_SIZE) ? 1 : -1
|
||||
];
|
||||
|
||||
typedef struct TEST_SENDER_CONTEXT {
|
||||
uint32_t Queue;
|
||||
volatile uint32_t Status;
|
||||
} TEST_SENDER_CONTEXT;
|
||||
|
||||
// Sends one message with the queue timeout request ABI.
|
||||
static uint32_t send_queue(uint32_t queue, const TEST_QUEUE_MESSAGE* msg, uint64_t timeoutMilliseconds) {
|
||||
SYS_QUEUE_SEND_REQUEST req = {
|
||||
sizeof(req),
|
||||
queue,
|
||||
SYS_QUEUE_FLAG_NONE,
|
||||
timeoutMilliseconds,
|
||||
msg,
|
||||
};
|
||||
return SysSendQueue(&req);
|
||||
}
|
||||
|
||||
// Receives one message with the queue timeout request ABI.
|
||||
static uint32_t recv_queue(uint32_t queue, TEST_QUEUE_MESSAGE* msg, uint64_t timeoutMilliseconds) {
|
||||
SYS_QUEUE_RECV_REQUEST req = {
|
||||
sizeof(req),
|
||||
queue,
|
||||
SYS_QUEUE_FLAG_NONE,
|
||||
timeoutMilliseconds,
|
||||
msg,
|
||||
};
|
||||
return SysRecvQueue(&req);
|
||||
}
|
||||
|
||||
// Prints one NUL-terminated string to the kernel console.
|
||||
static void print(const char* s) {
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
|
||||
// Prints one unsigned integer to the kernel console.
|
||||
static void print_u64(uint64_t v) {
|
||||
char buf[32];
|
||||
int i = 0;
|
||||
if (v == 0) {
|
||||
print("0");
|
||||
return;
|
||||
}
|
||||
while (v && i < (int)sizeof(buf)) {
|
||||
buf[i++] = (char)('0' + (v % 10));
|
||||
v /= 10;
|
||||
}
|
||||
while (i--) {
|
||||
char c = buf[i];
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
}
|
||||
|
||||
// Terminates the current test process.
|
||||
static void exit_now(int code) {
|
||||
for (;;) SysExitProcess(code);
|
||||
}
|
||||
|
||||
// Fails the test with one plain message.
|
||||
static void fail(const char* msg) {
|
||||
print("would_block_smoke: ");
|
||||
print(msg);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Fails the test with one status value.
|
||||
static void fail_status(const char* what, uint32_t status) {
|
||||
print("would_block_smoke: ");
|
||||
print(what);
|
||||
print(" status=");
|
||||
print_u64(status);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Requires one exact status value.
|
||||
static void expect_status(const char* what, uint32_t got, uint32_t expected) {
|
||||
if (got == expected) return;
|
||||
print("would_block_smoke: ");
|
||||
print(what);
|
||||
print(" got=");
|
||||
print_u64(got);
|
||||
print(" expected=");
|
||||
print_u64(expected);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Sends one wake message after the receiver has had a chance to block.
|
||||
static void sender_thread(uintptr_t arg) {
|
||||
TEST_SENDER_CONTEXT* ctx = (TEST_SENDER_CONTEXT*)arg;
|
||||
if (!ctx) SysExitThread(1);
|
||||
|
||||
SysSleep(20);
|
||||
|
||||
TEST_QUEUE_MESSAGE msg = {0};
|
||||
msg.Type = TEST_MESSAGE_WAKE;
|
||||
msg.Param[0] = TEST_WAKE_VALUE;
|
||||
ctx->Status = send_queue(ctx->Queue, &msg, SYS_WAIT_TIMEOUT_INFINITE);
|
||||
SysExitThread(ctx->Status == STATUS_SUCCESS ? 0 : 1);
|
||||
}
|
||||
|
||||
// Fills one queue with immediate sends until the queue reports would-block.
|
||||
static void fill_until_would_block(uint32_t queue) {
|
||||
TEST_QUEUE_MESSAGE msg = {0};
|
||||
msg.Type = 1;
|
||||
|
||||
uint32_t sends = 0;
|
||||
for (; sends < TEST_FILL_LIMIT; sends++) {
|
||||
msg.Param[0] = sends;
|
||||
uint32_t s = send_queue(queue, &msg, 0);
|
||||
if (s == STATUS_WOULD_BLOCK)
|
||||
break;
|
||||
if (s != STATUS_SUCCESS)
|
||||
fail_status("fill send", s);
|
||||
}
|
||||
|
||||
if (sends == 0 || sends == TEST_FILL_LIMIT)
|
||||
fail("queue fill did not reach would-block");
|
||||
}
|
||||
|
||||
// Verifies queue try and finite-timeout status distinctions.
|
||||
static void test_queue_empty_and_full(void) {
|
||||
uint32_t queue = 0;
|
||||
uint32_t s = SysCreateQueue(&queue);
|
||||
if (s != STATUS_SUCCESS) fail_status("create empty queue", s);
|
||||
|
||||
TEST_QUEUE_MESSAGE msg = {0};
|
||||
expect_status("empty nonblocking receive", recv_queue(queue, &msg, 0), STATUS_WOULD_BLOCK);
|
||||
expect_status("empty finite receive", recv_queue(queue, &msg, 20), STATUS_TIMEOUT);
|
||||
SysCloseHandle(queue);
|
||||
|
||||
queue = 0;
|
||||
s = SysCreateQueue(&queue);
|
||||
if (s != STATUS_SUCCESS) fail_status("create full queue", s);
|
||||
|
||||
fill_until_would_block(queue);
|
||||
expect_status("full nonblocking send", send_queue(queue, &msg, 0), STATUS_WOULD_BLOCK);
|
||||
expect_status("full finite send", send_queue(queue, &msg, 20), STATUS_TIMEOUT);
|
||||
SysCloseHandle(queue);
|
||||
}
|
||||
|
||||
// Verifies that an infinite receive composes with a sender wakeup.
|
||||
static void test_queue_infinite_receive_wakeup(void) {
|
||||
uint32_t queue = 0;
|
||||
uint32_t s = SysCreateQueue(&queue);
|
||||
if (s != STATUS_SUCCESS) fail_status("create wake queue", s);
|
||||
|
||||
TEST_SENDER_CONTEXT ctx = { queue, STATUS_PENDING };
|
||||
uint32_t threadHandle = 0;
|
||||
uint32_t threadId = 0;
|
||||
SYS_CREATE_THREAD_REQUEST req = {
|
||||
(uintptr_t)sender_thread,
|
||||
(uintptr_t)&ctx,
|
||||
1,
|
||||
0,
|
||||
&threadHandle,
|
||||
&threadId
|
||||
};
|
||||
s = SysCreateThread(&req);
|
||||
if (s != STATUS_SUCCESS) fail_status("create sender", s);
|
||||
|
||||
TEST_QUEUE_MESSAGE msg = {0};
|
||||
s = recv_queue(queue, &msg, SYS_WAIT_TIMEOUT_INFINITE);
|
||||
if (s != STATUS_SUCCESS) fail_status("infinite receive", s);
|
||||
if (msg.Type != TEST_MESSAGE_WAKE || msg.Param[0] != TEST_WAKE_VALUE)
|
||||
fail("wake message payload mismatch");
|
||||
|
||||
s = SysWait(threadHandle, SYS_WAIT_FLAG_NONE);
|
||||
if (s != STATUS_SUCCESS) fail_status("wait sender", s);
|
||||
if (ctx.Status != STATUS_SUCCESS) fail_status("sender status", ctx.Status);
|
||||
|
||||
SysCloseHandle(threadHandle);
|
||||
SysCloseHandle(queue);
|
||||
}
|
||||
|
||||
// Verifies that request metadata is part of the queue ABI contract.
|
||||
static void test_queue_request_validation(void) {
|
||||
uint32_t queue = 0;
|
||||
uint32_t s = SysCreateQueue(&queue);
|
||||
if (s != STATUS_SUCCESS) fail_status("create validation queue", s);
|
||||
|
||||
TEST_QUEUE_MESSAGE msg = {0};
|
||||
expect_status("null send request", SysSendQueue((const SYS_QUEUE_SEND_REQUEST*)0), STATUS_INVALID_PARAMETER);
|
||||
expect_status("null recv request", SysRecvQueue((const SYS_QUEUE_RECV_REQUEST*)0), STATUS_INVALID_PARAMETER);
|
||||
|
||||
SYS_QUEUE_SEND_REQUEST sendReq = {
|
||||
0,
|
||||
queue,
|
||||
SYS_QUEUE_FLAG_NONE,
|
||||
0,
|
||||
&msg,
|
||||
};
|
||||
expect_status("bad send size", SysSendQueue(&sendReq), STATUS_INVALID_PARAMETER);
|
||||
|
||||
sendReq.Size = sizeof(sendReq);
|
||||
sendReq.Flags = 1;
|
||||
expect_status("bad send flags", SysSendQueue(&sendReq), STATUS_INVALID_PARAMETER);
|
||||
|
||||
sendReq.Flags = SYS_QUEUE_FLAG_NONE;
|
||||
sendReq.Message = (const void*)0;
|
||||
expect_status("bad send message", SysSendQueue(&sendReq), STATUS_INVALID_PARAMETER);
|
||||
|
||||
SYS_QUEUE_RECV_REQUEST recvReq = {
|
||||
sizeof(recvReq),
|
||||
queue,
|
||||
SYS_QUEUE_FLAG_NONE,
|
||||
0,
|
||||
(void*)0,
|
||||
};
|
||||
expect_status("bad recv message", SysRecvQueue(&recvReq), STATUS_INVALID_PARAMETER);
|
||||
|
||||
SysCloseHandle(queue);
|
||||
}
|
||||
|
||||
// Runs the native would-block smoke test.
|
||||
int main(void) {
|
||||
print("would_block_smoke: start\n");
|
||||
test_queue_request_validation();
|
||||
test_queue_empty_and_full();
|
||||
test_queue_infinite_receive_wakeup();
|
||||
print("would_block_smoke: PASS\n");
|
||||
exit_now(0);
|
||||
}
|
||||
Reference in new issue
Block a user