Skip to content

Commit 343ffeb

Browse files
committed
Fix Circular Buffer on Windows
1 parent 80f3278 commit 343ffeb

1 file changed

Lines changed: 42 additions & 6 deletions

File tree

src/circular_buffer.zig

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@ pub fn CircularBuffer(comptime T: type) type {
1111
read_offset: usize = 0,
1212
write_offset: usize = 0,
1313

14-
/// `capacity` * sizeof(T) must be a multiple of page size.
14+
/// `capacity` * sizeof(T) must be a multiple of page size on Linux (most likely 4k) or allocation granularity on Windows (most likely 64k).
1515
pub fn init(capacity: usize) !@This() {
1616
const byte_capacity = capacity * @sizeOf(T);
17-
if (byte_capacity % std.heap.pageSize() != 0) return error.InvalidSize;
17+
if (byte_capacity % allocation_granularity() != 0) return error.InvalidSize;
1818
switch (builtin.os.tag) {
1919
.windows => {
20-
// FIXME: UNTESTED!
2120
const fd = CreateFileMappingA(
2221
std.os.windows.INVALID_HANDLE_VALUE,
2322
null,
@@ -29,7 +28,7 @@ pub fn CircularBuffer(comptime T: type) type {
2928
defer _ = std.os.windows.CloseHandle(fd);
3029

3130
// FIXME: Use placeholders instead of the retry loop...
32-
while (true) {
31+
for (0..8) |_| {
3332
const reserve = VirtualAlloc(null, 2 * byte_capacity, MEM_RESERVE, PAGE_NOACCESS) orelse return error.VirtualAllocError;
3433
_ = VirtualFree(reserve, 0, MEM_RELEASE);
3534

@@ -44,6 +43,8 @@ pub fn CircularBuffer(comptime T: type) type {
4443
.buffer = @alignCast(std.mem.bytesAsSlice(T, @as([*]u8, @ptrCast(reserve))[0 .. 2 * byte_capacity])),
4544
};
4645
}
46+
std.log.err("Failed to allocate Circular Buffer: {}", .{std.os.windows.GetLastError()});
47+
return error.MapViewOfFileExError;
4748
},
4849
.linux => {
4950
const fd = try std.posix.memfd_create("Circular Buffer", 0);
@@ -66,10 +67,10 @@ pub fn CircularBuffer(comptime T: type) type {
6667
}
6768

6869
/// Initializes the buffer with at least `capacity` elements.
69-
/// Actual capacity may be greater to be a multiple of page size.
70+
/// Actual capacity may be greater to be a multiple of the required alignement.
7071
pub fn initAtLeast(capacity: usize) !@This() {
7172
const byte_capacity = capacity * @sizeOf(T);
72-
return init(std.mem.alignForward(usize, byte_capacity, std.heap.pageSize()) / @sizeOf(T));
73+
return init(std.mem.alignForward(usize, byte_capacity, allocation_granularity()) / @sizeOf(T));
7374
}
7475

7576
pub fn deinit(self: *@This()) void {
@@ -109,6 +110,18 @@ pub fn CircularBuffer(comptime T: type) type {
109110
pub fn view(self: *const @This()) []const T {
110111
return self.buffer[self.read_offset..self.write_offset];
111112
}
113+
114+
fn allocation_granularity() usize {
115+
switch (builtin.os.tag) {
116+
.windows => {
117+
var system_info: SYSTEM_INFO = undefined;
118+
GetSystemInfo(&system_info);
119+
return system_info.dwAllocationGranularity;
120+
},
121+
.linux => return std.heap.pageSize(),
122+
else => @compileError("Unsupported OS"),
123+
}
124+
}
112125
};
113126
}
114127

@@ -118,6 +131,29 @@ pub const MEM_RELEASE: std.os.windows.DWORD = 0x00008000;
118131
pub const PAGE_NOACCESS: std.os.windows.DWORD = 0x01;
119132
pub const PAGE_READWRITE: std.os.windows.DWORD = 0x04;
120133

134+
pub const SYSTEM_INFO = extern struct {
135+
id: extern union {
136+
dwOemId: std.os.windows.DWORD,
137+
other: extern struct {
138+
wProcessorArchitecture: std.os.windows.WORD,
139+
wReserved: std.os.windows.WORD,
140+
},
141+
},
142+
dwPageSize: std.os.windows.DWORD,
143+
lpMinimumApplicationAddress: std.os.windows.LPVOID,
144+
lpMaximumApplicationAddress: std.os.windows.LPVOID,
145+
dwActiveProcessorMask: std.os.windows.DWORD_PTR,
146+
dwNumberOfProcessors: std.os.windows.DWORD,
147+
dwProcessorType: std.os.windows.DWORD,
148+
dwAllocationGranularity: std.os.windows.DWORD,
149+
wProcessorLevel: std.os.windows.WORD,
150+
wProcessorRevision: std.os.windows.WORD,
151+
};
152+
153+
pub extern "kernel32" fn GetSystemInfo(
154+
lpSystemInfo: *SYSTEM_INFO,
155+
) callconv(.winapi) void;
156+
121157
pub extern "kernel32" fn CreateFileMappingA(
122158
hFile: std.os.windows.HANDLE,
123159
lpFileMappingAttributes: ?*std.os.windows.SECURITY_ATTRIBUTES,

0 commit comments

Comments
 (0)