#27792

windows/tcc: bundled kernel32.def lacks GetQueuedCompletionStatusEx / SetFileCompletionNotificationModes exports (IOCP batch dequeue cannot link)

Openenghitaloopened 3mo ago

V version: V 0.5.2 bf6762e, Windows 11, default C backend (bundled tcc 0.9.27 from vlang/tccbin, branch thirdparty-windows-amd64).

What happened

The bundled tcc's lib/kernel32.def is missing the exports for two kernel32 APIs that high-performance IOCP servers need, so any V program calling them fails to link under the default Windows toolchain:

  • GetQueuedCompletionStatusEx — batch completion dequeue (one syscall returns N completions; the IOCP equivalent of epoll_wait returning many events). Available since Windows Vista.
  • SetFileCompletionNotificationModes — FILE_SKIP_COMPLETION_PORT_ON_SUCCESS, the standard optimization that skips the completion-port round-trip when an overlapped op completes synchronously (used by libuv, mio, etc.). Available since Windows Vista.

The single-shot GetQueuedCompletionStatus, CreateIoCompletionPort, PostQueuedCompletionStatus and even CancelIoEx (also Vista+) are all already present in the .def, so this looks like an accidental gap rather than a deliberate XP-era cutoff.

Context: while implementing an IOCP backend for an HTTP server (vlang/vanilla-style, one completion port per worker), the single-dequeue path works fine with tcc, but the batch-dequeue upgrade cannot be linked — the only workarounds are GetProcAddress at runtime or switching to gcc/msvc.

Reproduction

module main

#include <winsock2.h>
#include <windows.h>

@[typedef]
pub struct C.OVERLAPPED {
pub mut:
	Internal     usize
	InternalHigh usize
	Offset       u32
	OffsetHigh   u32
	hEvent       voidptr
}

// Declared as a plain V struct: tcc's bundled winapi headers do not define
// OVERLAPPED_ENTRY either (secondary gap; this part is easy to work around).
pub struct OverlappedEntry {
pub mut:
	completion_key    usize
	overlapped        &C.OVERLAPPED = unsafe { nil }
	internal          usize
	bytes_transferred u32
}

fn C.CreateIoCompletionPort(file_handle voidptr, existing voidptr, key usize, n u32) voidptr
fn C.GetQueuedCompletionStatusEx(port voidptr, entries &OverlappedEntry, count u32, removed &u32, ms u32, alertable bool) bool

fn main() {
	port := C.CreateIoCompletionPort(C.INVALID_HANDLE_VALUE, unsafe { nil }, 0, 1)
	mut entries := [16]OverlappedEntry{}
	mut removed := u32(0)
	ok := C.GetQueuedCompletionStatusEx(port, &entries[0], 16, &removed, 0, false)
	println('ok=${ok} removed=${removed}')
}
$ v run gqcse.v
================== C compilation error (from thirdparty\tcc\tcc.exe): ==============
cc: tcc: error: undefined symbol 'GetQueuedCompletionStatusEx'

Verification of the gap

$ grep -x "GetQueuedCompletionStatus" thirdparty/tcc/lib/kernel32.def
GetQueuedCompletionStatus
$ grep -x "GetQueuedCompletionStatusEx" thirdparty/tcc/lib/kernel32.def
(no match)
$ grep -x "SetFileCompletionNotificationModes" thirdparty/tcc/lib/kernel32.def
(no match)

Same on the current vlang/tccbin thirdparty-windows-amd64 branch: https://github.com/vlang/tccbin/blob/thirdparty-windows-amd64/lib/kernel32.def

Expected / proposed fix

Add two lines to lib/kernel32.def in the vlang/tccbin thirdparty-windows-* branches (tcc .def files are plain export-name lists, so this needs no rebuild of tcc itself):

GetQueuedCompletionStatusEx
SetFileCompletionNotificationModes

Optionally also add the OVERLAPPED_ENTRY struct + GetQueuedCompletionStatusEx / SetFileCompletionNotificationModes prototypes to the bundled winapi headers, but the .def entries are the hard blocker — the prototypes can be declared from V.

NOTE

You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.

Activity

0

No activity yet.