// Native would-block and queue-timeout contract smoke test. // Verifies that queue try, finite-timeout, and infinite-wait requests return distinct statuses. #include #include #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) { while (true) 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 == NTLSTATUS_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 == NTLSTATUS_WOULD_BLOCK) break; if (s != NTLSTATUS_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 != NTLSTATUS_SUCCESS) fail_status("create empty queue", s); TEST_QUEUE_MESSAGE msg = {0}; expect_status("empty nonblocking receive", recv_queue(queue, &msg, 0), NTLSTATUS_WOULD_BLOCK); expect_status("empty finite receive", recv_queue(queue, &msg, 20), NTLSTATUS_TIMEOUT); SysCloseHandle(queue); queue = 0; s = SysCreateQueue(&queue); if (s != NTLSTATUS_SUCCESS) fail_status("create full queue", s); fill_until_would_block(queue); expect_status("full nonblocking send", send_queue(queue, &msg, 0), NTLSTATUS_WOULD_BLOCK); expect_status("full finite send", send_queue(queue, &msg, 20), NTLSTATUS_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 != NTLSTATUS_SUCCESS) fail_status("create wake queue", s); TEST_SENDER_CONTEXT ctx = { queue, NTLSTATUS_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 != NTLSTATUS_SUCCESS) fail_status("create sender", s); TEST_QUEUE_MESSAGE msg = {0}; s = recv_queue(queue, &msg, SYS_WAIT_TIMEOUT_INFINITE); if (s != NTLSTATUS_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 != NTLSTATUS_SUCCESS) fail_status("wait sender", s); if (ctx.Status != NTLSTATUS_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 != NTLSTATUS_SUCCESS) fail_status("create validation queue", s); TEST_QUEUE_MESSAGE msg = {0}; expect_status("null send request", SysSendQueue((const SYS_QUEUE_SEND_REQUEST*)0), NTLSTATUS_INVALID_PARAMETER); expect_status("null recv request", SysRecvQueue((const SYS_QUEUE_RECV_REQUEST*)0), NTLSTATUS_INVALID_PARAMETER); SYS_QUEUE_SEND_REQUEST sendReq = { 0, queue, SYS_QUEUE_FLAG_NONE, 0, &msg, }; expect_status("bad send size", SysSendQueue(&sendReq), NTLSTATUS_INVALID_PARAMETER); sendReq.Size = sizeof(sendReq); sendReq.Flags = 1; expect_status("bad send flags", SysSendQueue(&sendReq), NTLSTATUS_INVALID_PARAMETER); sendReq.Flags = SYS_QUEUE_FLAG_NONE; sendReq.Message = (const void*)0; expect_status("bad send message", SysSendQueue(&sendReq), NTLSTATUS_INVALID_PARAMETER); SYS_QUEUE_RECV_REQUEST recvReq = { sizeof(recvReq), queue, SYS_QUEUE_FLAG_NONE, 0, (void*)0, }; expect_status("bad recv message", SysRecvQueue(&recvReq), NTLSTATUS_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); }