mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-21 20:24:42 +00:00
Merge pull request #1778 from lightpanda-io/wp/mrdimidium/libcurl-malloc
Use zig allocator for libcurl
This commit is contained in:
@@ -51,8 +51,120 @@ wakeup_pipe: [2]posix.fd_t = .{ -1, -1 },
|
|||||||
|
|
||||||
shutdown: std.atomic.Value(bool) = .init(false),
|
shutdown: std.atomic.Value(bool) = .init(false),
|
||||||
|
|
||||||
fn globalInit() void {
|
const ZigToCurlAllocator = struct {
|
||||||
libcurl.curl_global_init(.{ .ssl = true }) catch |err| {
|
// C11 requires malloc to return memory aligned to max_align_t (16 bytes on x86_64).
|
||||||
|
// We match this guarantee since libcurl expects malloc-compatible alignment.
|
||||||
|
const alignment = 16;
|
||||||
|
|
||||||
|
const Block = extern struct {
|
||||||
|
size: usize = 0,
|
||||||
|
_padding: [alignment - @sizeOf(usize)]u8 = .{0} ** (alignment - @sizeOf(usize)),
|
||||||
|
|
||||||
|
inline fn fullsize(bytes: usize) usize {
|
||||||
|
return alignment + bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fn fromPtr(ptr: *anyopaque) *Block {
|
||||||
|
const raw: [*]u8 = @ptrCast(ptr);
|
||||||
|
return @ptrCast(@alignCast(raw - @sizeOf(Block)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fn data(self: *Block) [*]u8 {
|
||||||
|
const ptr: [*]u8 = @ptrCast(self);
|
||||||
|
return ptr + @sizeOf(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fn slice(self: *Block) []align(alignment) u8 {
|
||||||
|
const base: [*]align(alignment) u8 = @ptrCast(@alignCast(self));
|
||||||
|
return base[0 .. alignment + self.size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
std.debug.assert(@sizeOf(Block) == alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
var instance: ?ZigToCurlAllocator = null;
|
||||||
|
|
||||||
|
allocator: Allocator,
|
||||||
|
|
||||||
|
pub fn init(allocator: Allocator) void {
|
||||||
|
lp.assert(instance == null, "Initialization of curl must happen only once", .{});
|
||||||
|
instance = .{ .allocator = allocator };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn interface() libcurl.CurlAllocator {
|
||||||
|
return .{
|
||||||
|
.free = free,
|
||||||
|
.strdup = strdup,
|
||||||
|
.malloc = malloc,
|
||||||
|
.calloc = calloc,
|
||||||
|
.realloc = realloc,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _allocBlock(size: usize) ?*Block {
|
||||||
|
const slice = instance.?.allocator.alignedAlloc(u8, .fromByteUnits(alignment), Block.fullsize(size)) catch return null;
|
||||||
|
const block: *Block = @ptrCast(@alignCast(slice.ptr));
|
||||||
|
block.size = size;
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _freeBlock(header: *Block) void {
|
||||||
|
instance.?.allocator.free(header.slice());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn malloc(size: usize) ?*anyopaque {
|
||||||
|
const block = _allocBlock(size) orelse return null;
|
||||||
|
return @ptrCast(block.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calloc(nmemb: usize, size: usize) ?*anyopaque {
|
||||||
|
const total = nmemb * size;
|
||||||
|
const block = _allocBlock(total) orelse return null;
|
||||||
|
const ptr = block.data();
|
||||||
|
@memset(ptr[0..total], 0); // for historical reasons, calloc zeroes memory, but malloc does not.
|
||||||
|
return @ptrCast(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn realloc(ptr: ?*anyopaque, size: usize) ?*anyopaque {
|
||||||
|
const p = ptr orelse return malloc(size);
|
||||||
|
const block = Block.fromPtr(p);
|
||||||
|
|
||||||
|
const old_size = block.size;
|
||||||
|
if (size == old_size) return ptr;
|
||||||
|
|
||||||
|
if (instance.?.allocator.resize(block.slice(), alignment + size)) {
|
||||||
|
block.size = size;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const copy_size = @min(old_size, size);
|
||||||
|
const new_block = _allocBlock(size) orelse return null;
|
||||||
|
@memcpy(new_block.data()[0..copy_size], block.data()[0..copy_size]);
|
||||||
|
_freeBlock(block);
|
||||||
|
return @ptrCast(new_block.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free(ptr: ?*anyopaque) void {
|
||||||
|
const p = ptr orelse return;
|
||||||
|
_freeBlock(Block.fromPtr(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strdup(str: [*:0]const u8) ?[*:0]u8 {
|
||||||
|
const len = std.mem.len(str);
|
||||||
|
const header = _allocBlock(len + 1) orelse return null;
|
||||||
|
const ptr = header.data();
|
||||||
|
@memcpy(ptr[0..len], str[0..len]);
|
||||||
|
ptr[len] = 0;
|
||||||
|
return ptr[0..len :0];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn globalInit(allocator: Allocator) void {
|
||||||
|
ZigToCurlAllocator.init(allocator);
|
||||||
|
|
||||||
|
libcurl.curl_global_init(.{ .ssl = true }, ZigToCurlAllocator.interface()) catch |err| {
|
||||||
lp.assert(false, "curl global init", .{ .err = err });
|
lp.assert(false, "curl global init", .{ .err = err });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -62,7 +174,7 @@ fn globalDeinit() void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, config: *const Config) !Runtime {
|
pub fn init(allocator: Allocator, config: *const Config) !Runtime {
|
||||||
globalInit();
|
globalInit(allocator);
|
||||||
errdefer globalDeinit();
|
errdefer globalDeinit();
|
||||||
|
|
||||||
const pipe = try posix.pipe2(.{ .NONBLOCK = true, .CLOEXEC = true });
|
const pipe = try posix.pipe2(.{ .NONBLOCK = true, .CLOEXEC = true });
|
||||||
|
|||||||
@@ -41,6 +41,20 @@ pub const CurlHeaderFunction = fn ([*]const u8, usize, usize, *anyopaque) usize;
|
|||||||
pub const CurlWriteFunction = fn ([*]const u8, usize, usize, *anyopaque) usize;
|
pub const CurlWriteFunction = fn ([*]const u8, usize, usize, *anyopaque) usize;
|
||||||
pub const curl_writefunc_error: usize = c.CURL_WRITEFUNC_ERROR;
|
pub const curl_writefunc_error: usize = c.CURL_WRITEFUNC_ERROR;
|
||||||
|
|
||||||
|
pub const FreeCallback = fn (ptr: ?*anyopaque) void;
|
||||||
|
pub const StrdupCallback = fn (str: [*:0]const u8) ?[*:0]u8;
|
||||||
|
pub const MallocCallback = fn (size: usize) ?*anyopaque;
|
||||||
|
pub const CallocCallback = fn (nmemb: usize, size: usize) ?*anyopaque;
|
||||||
|
pub const ReallocCallback = fn (ptr: ?*anyopaque, size: usize) ?*anyopaque;
|
||||||
|
|
||||||
|
pub const CurlAllocator = struct {
|
||||||
|
free: FreeCallback,
|
||||||
|
strdup: StrdupCallback,
|
||||||
|
malloc: MallocCallback,
|
||||||
|
calloc: CallocCallback,
|
||||||
|
realloc: ReallocCallback,
|
||||||
|
};
|
||||||
|
|
||||||
pub const CurlGlobalFlags = packed struct(u8) {
|
pub const CurlGlobalFlags = packed struct(u8) {
|
||||||
ssl: bool = false,
|
ssl: bool = false,
|
||||||
_reserved: u7 = 0,
|
_reserved: u7 = 0,
|
||||||
@@ -449,8 +463,41 @@ pub const CurlMsg = struct {
|
|||||||
data: CurlMsgData,
|
data: CurlMsgData,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn curl_global_init(flags: CurlGlobalFlags) Error!void {
|
pub fn curl_global_init(flags: CurlGlobalFlags, comptime curl_allocator: ?CurlAllocator) Error!void {
|
||||||
try errorCheck(c.curl_global_init(flags.to_c()));
|
const alloc = curl_allocator orelse {
|
||||||
|
return errorCheck(c.curl_global_init(flags.to_c()));
|
||||||
|
};
|
||||||
|
|
||||||
|
// The purpose of these wrappers is to hide callconv
|
||||||
|
// and provide an easy place to add logging when debugging.
|
||||||
|
const free = struct {
|
||||||
|
fn cb(ptr: ?*anyopaque) callconv(.c) void {
|
||||||
|
alloc.free(ptr);
|
||||||
|
}
|
||||||
|
}.cb;
|
||||||
|
const strdup = struct {
|
||||||
|
fn cb(str: [*c]const u8) callconv(.c) [*c]u8 {
|
||||||
|
const s: [*:0]const u8 = @ptrCast(str orelse return null);
|
||||||
|
return @ptrCast(alloc.strdup(s));
|
||||||
|
}
|
||||||
|
}.cb;
|
||||||
|
const malloc = struct {
|
||||||
|
fn cb(size: usize) callconv(.c) ?*anyopaque {
|
||||||
|
return alloc.malloc(size);
|
||||||
|
}
|
||||||
|
}.cb;
|
||||||
|
const calloc = struct {
|
||||||
|
fn cb(nmemb: usize, size: usize) callconv(.c) ?*anyopaque {
|
||||||
|
return alloc.calloc(nmemb, size);
|
||||||
|
}
|
||||||
|
}.cb;
|
||||||
|
const realloc = struct {
|
||||||
|
fn cb(ptr: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque {
|
||||||
|
return alloc.realloc(ptr, size);
|
||||||
|
}
|
||||||
|
}.cb;
|
||||||
|
|
||||||
|
try errorCheck(c.curl_global_init_mem(flags.to_c(), malloc, free, realloc, strdup, calloc));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn curl_global_cleanup() void {
|
pub fn curl_global_cleanup() void {
|
||||||
|
|||||||
Reference in New Issue
Block a user