mirror of
https://github.com/rdmsr/zag.git
synced 2026-11-01 23:58:21 +00:00
mm/zone: more SMR features
This commit is contained in:
+33
-7
@@ -179,11 +179,16 @@ var cpu_zone: Zone = undefined;
|
|||||||
var smr_zone: TypedZone(ke.smr.Domain) = undefined;
|
var smr_zone: TypedZone(ke.smr.Domain) = undefined;
|
||||||
var smr_cpu_zone: Zone = undefined;
|
var smr_cpu_zone: Zone = undefined;
|
||||||
|
|
||||||
|
pub var smr_sys_domain: *ke.smr.Domain = undefined;
|
||||||
|
pub var smr_sys_preempt_domain: *ke.smr.Domain = undefined;
|
||||||
|
|
||||||
const alloc_poison: u32 = 0xBADDC0DE;
|
const alloc_poison: u32 = 0xBADDC0DE;
|
||||||
const free_poison: u32 = 0xDEADBEEF;
|
const free_poison: u32 = 0xDEADBEEF;
|
||||||
const is_poison_enabled = config.slab_poison;
|
const is_poison_enabled = config.slab_poison;
|
||||||
const should_check_poison = config.slab_check_poison;
|
const should_check_poison = config.slab_check_poison;
|
||||||
|
|
||||||
|
const AllocOpts = struct { policy: mm.WaitPolicy = .WaitForMemory };
|
||||||
|
|
||||||
/// A slab is a contiguous memory region that holds multiple objects of the same type.
|
/// A slab is a contiguous memory region that holds multiple objects of the same type.
|
||||||
const Slab = struct {
|
const Slab = struct {
|
||||||
/// Linkage into a zone's list of slabs.
|
/// Linkage into a zone's list of slabs.
|
||||||
@@ -495,6 +500,7 @@ pub const Zone = struct {
|
|||||||
reuse_policy: ReusePolicy,
|
reuse_policy: ReusePolicy,
|
||||||
|
|
||||||
smr: ?*ke.smr.Domain,
|
smr: ?*ke.smr.Domain,
|
||||||
|
smr_reclaim: ?*const fn (obj: *anyopaque) void,
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
@@ -505,6 +511,7 @@ pub const Zone = struct {
|
|||||||
magazines: bool = true,
|
magazines: bool = true,
|
||||||
reuse_policy: ReusePolicy = .FIFO,
|
reuse_policy: ReusePolicy = .FIFO,
|
||||||
smr: ?*ke.smr.Domain = null,
|
smr: ?*ke.smr.Domain = null,
|
||||||
|
smr_reclaim: ?*const fn (obj: *anyopaque) void = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Initialize a zone.
|
/// Initialize a zone.
|
||||||
@@ -538,6 +545,7 @@ pub const Zone = struct {
|
|||||||
// obtained by checking the list head.
|
// obtained by checking the list head.
|
||||||
self.reuse_policy = if (options.smr != null) .FIFO else options.reuse_policy;
|
self.reuse_policy = if (options.smr != null) .FIFO else options.reuse_policy;
|
||||||
self.smr = options.smr;
|
self.smr = options.smr;
|
||||||
|
self.smr_reclaim = options.smr_reclaim;
|
||||||
|
|
||||||
zone_list_lock.acquire();
|
zone_list_lock.acquire();
|
||||||
|
|
||||||
@@ -564,7 +572,7 @@ pub const Zone = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate an object from the zone.
|
/// Allocate an object from the zone.
|
||||||
pub fn alloc(self: *Self, opts: struct { policy: mm.WaitPolicy = .WaitForMemory }) mm.Error!*anyopaque {
|
pub fn alloc(self: *Self, opts: AllocOpts) mm.Error!*anyopaque {
|
||||||
var buf: *anyopaque = undefined;
|
var buf: *anyopaque = undefined;
|
||||||
|
|
||||||
// Try grabbing an object from the magazine layer.
|
// Try grabbing an object from the magazine layer.
|
||||||
@@ -802,6 +810,7 @@ pub const Zone = struct {
|
|||||||
if (self.smr) |smr| {
|
if (self.smr) |smr| {
|
||||||
// Direct frees must synchronize, the object is instantly reusable.
|
// Direct frees must synchronize, the object is instantly reusable.
|
||||||
_ = ke.smr.synchronize(smr);
|
_ = ke.smr.synchronize(smr);
|
||||||
|
if (self.smr_reclaim) |reclaim| reclaim(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.lock.acquire();
|
self.lock.acquire();
|
||||||
@@ -1087,7 +1096,11 @@ pub const Zone = struct {
|
|||||||
// Free its rounds to the slab layer.
|
// Free its rounds to the slab layer.
|
||||||
// For SMR zones the free-time work was deferred, do it now.
|
// For SMR zones the free-time work was deferred, do it now.
|
||||||
for (0..rounds) |i| {
|
for (0..rounds) |i| {
|
||||||
self.slab_free(magazine.rounds_ptr()[i], self.smr != null);
|
const obj = magazine.rounds_ptr()[i];
|
||||||
|
if (self.smr_reclaim) |reclaim| {
|
||||||
|
reclaim(obj);
|
||||||
|
}
|
||||||
|
self.slab_free(obj, self.smr != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the magazine.
|
// Free the magazine.
|
||||||
@@ -1204,16 +1217,17 @@ pub const Zone = struct {
|
|||||||
/// Deferred free-time work for SMR zones, ran when a full magazine
|
/// Deferred free-time work for SMR zones, ran when a full magazine
|
||||||
/// is reused after its grace period expired.
|
/// is reused after its grace period expired.
|
||||||
fn magazine_reuse(self: *Self, mag: *Magazine) void {
|
fn magazine_reuse(self: *Self, mag: *Magazine) void {
|
||||||
if (!is_poison_enabled or self.smr == null) return;
|
if (self.smr == null) return;
|
||||||
|
|
||||||
for (0..magazine_size.load()) |i| {
|
for (0..magazine_size.load()) |i| {
|
||||||
const obj = mag.rounds_ptr()[i];
|
const obj = mag.rounds_ptr()[i];
|
||||||
|
|
||||||
if (self.dtor) |dtor| {
|
if (self.smr_reclaim) |reclaim| reclaim(obj);
|
||||||
dtor(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
fill_with_poison(obj, self.obj_size, free_poison);
|
if (is_poison_enabled) {
|
||||||
|
if (self.dtor) |dtor| dtor(obj);
|
||||||
|
fill_with_poison(obj, self.obj_size, free_poison);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1354,6 +1368,8 @@ pub fn TypedZone(comptime T: type) type {
|
|||||||
pub const InitOptions = struct {
|
pub const InitOptions = struct {
|
||||||
ctor: ?*const fn (*T) void = null,
|
ctor: ?*const fn (*T) void = null,
|
||||||
dtor: ?*const fn (*T) void = null,
|
dtor: ?*const fn (*T) void = null,
|
||||||
|
smr: ?*ke.smr.Domain = null,
|
||||||
|
smr_reclaim: ?*const fn (*T) void = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(self: *@This(), name: []const u8, options: InitOptions) void {
|
pub fn init(self: *@This(), name: []const u8, options: InitOptions) void {
|
||||||
@@ -1361,6 +1377,8 @@ pub fn TypedZone(comptime T: type) type {
|
|||||||
.alignment = @alignOf(T),
|
.alignment = @alignOf(T),
|
||||||
.ctor = @ptrCast(options.ctor),
|
.ctor = @ptrCast(options.ctor),
|
||||||
.dtor = @ptrCast(options.dtor),
|
.dtor = @ptrCast(options.dtor),
|
||||||
|
.smr = options.smr,
|
||||||
|
.smr_reclaim = @ptrCast(options.smr_reclaim),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1369,6 +1387,11 @@ pub fn TypedZone(comptime T: type) type {
|
|||||||
return @ptrCast(@alignCast(ret));
|
return @ptrCast(@alignCast(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_opts(self: *Self, opts: AllocOpts) mm.Error!*T {
|
||||||
|
const ret = try self.zone.alloc(opts);
|
||||||
|
return @ptrCast(@alignCast(ret));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *Self, obj: *T) void {
|
pub fn destroy(self: *Self, obj: *T) void {
|
||||||
self.zone.free(obj);
|
self.zone.free(obj);
|
||||||
}
|
}
|
||||||
@@ -1422,6 +1445,9 @@ pub fn late_init() linksection(r.init) void {
|
|||||||
|
|
||||||
smr_zone.init("SMR", .{});
|
smr_zone.init("SMR", .{});
|
||||||
smr_cpu_zone.init("SMR CPU", @sizeOf(ke.smr.Cpu) * ke.ncpus, .{});
|
smr_cpu_zone.init("SMR CPU", @sizeOf(ke.smr.Cpu) * ke.ncpus, .{});
|
||||||
|
|
||||||
|
smr_sys_domain = smr_domain_create(false) catch @panic("Failed to create smr domain");
|
||||||
|
smr_sys_preempt_domain = smr_domain_create(true) catch @panic("Failed to create smr domain");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn smr_domain_create(preempt: bool) !*ke.smr.Domain {
|
pub fn smr_domain_create(preempt: bool) !*ke.smr.Domain {
|
||||||
|
|||||||
Reference in New Issue
Block a user