mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 17:38:10 +00:00
feat(shm): arena allocator for unified region (§13.2)
- SuperBlock 新增 arenaOff/arenaCap/arenaUsed 字段 - arenaAlloc: append-only bump 分配,offset 0 保留给空语义 - arenaWrite: 写入并返回 SharedRef(含 generation) - arenaRead: 按 SharedRef 切片读取 - arenaReset: 压实后重置游标
This commit is contained in:
@ -62,8 +62,17 @@ const (
|
||||
sbOffCtxSize = 24
|
||||
sbOffEvtOff = 28
|
||||
sbOffEvtSize = 32
|
||||
sbOffArenaOff = 36 // 动态 arena 起始偏移
|
||||
sbOffArenaCap = 40 // 动态 arena 总容量
|
||||
sbOffArenaUsed = 44 // 动态 arena 已用字节(原子)
|
||||
sbOffReserved5 = 48
|
||||
sbOffReserved6 = 52
|
||||
sbOffReserved7 = 56
|
||||
sbOffReserved8 = 60
|
||||
)
|
||||
|
||||
const unifiedArenaSize = 256 * 1024 // 默认动态 arena 256KB
|
||||
|
||||
// SharedRef 是跨进程共享内存描述符,替代内联 JSON 数据。
|
||||
//
|
||||
// 所有数据交换(工具调用参数/结果、Cleaner、输入/输出通道消息)
|
||||
@ -99,6 +108,10 @@ type unifiedRegion struct {
|
||||
ctxSize uint32
|
||||
evtOff uint32
|
||||
evtSize uint32
|
||||
|
||||
arenaOff uint32 // 动态 arena 起始偏移(相对 data)
|
||||
arenaCap uint32 // 动态 arena 总容量
|
||||
arenaUsed *uint32 // 指向 SuperBlock 中的 arenaUsed 字段(原子 bump 游标)
|
||||
}
|
||||
|
||||
// initUnifiedRegion 在 mmap 区域上初始化 SuperBlock + 两个 segment。
|
||||
@ -111,6 +124,8 @@ func initUnifiedRegion(data []byte, ctxTotal, evtTotal int) (*unifiedRegion, err
|
||||
|
||||
ctxOff := uint32(superBlockSize)
|
||||
evtOff := ctxOff + uint32(ctxTotal)
|
||||
arenaOff := evtOff + uint32(evtTotal)
|
||||
arenaCap := cap - arenaOff
|
||||
|
||||
putU32(data[sbOffMagic:], unifiedMagic)
|
||||
putU32(data[sbOffVersion:], unifiedVersion)
|
||||
@ -120,13 +135,21 @@ func initUnifiedRegion(data []byte, ctxTotal, evtTotal int) (*unifiedRegion, err
|
||||
putU32(data[sbOffCtxSize:], uint32(ctxTotal))
|
||||
putU32(data[sbOffEvtOff:], evtOff)
|
||||
putU32(data[sbOffEvtSize:], uint32(evtTotal))
|
||||
putU32(data[sbOffArenaOff:], arenaOff)
|
||||
putU32(data[sbOffArenaCap:], arenaCap)
|
||||
putU32(data[sbOffArenaUsed:], 1)
|
||||
|
||||
return &unifiedRegion{
|
||||
data: data,
|
||||
ctxOff: ctxOff,
|
||||
ctxSize: uint32(ctxTotal),
|
||||
evtOff: evtOff,
|
||||
evtSize: uint32(evtTotal),
|
||||
data: data,
|
||||
ctxOff: ctxOff,
|
||||
ctxSize: uint32(ctxTotal),
|
||||
evtOff: evtOff,
|
||||
evtSize: uint32(evtTotal),
|
||||
arenaOff: arenaOff,
|
||||
arenaCap: arenaCap,
|
||||
arenaUsed: (*uint32)(unsafe.Pointer(
|
||||
uintptr(unsafe.Pointer(&data[0])) + uintptr(sbOffArenaUsed),
|
||||
)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -148,16 +171,24 @@ func attachUnifiedRegion(data []byte) (*unifiedRegion, error) {
|
||||
evtOff := getU32(data[sbOffEvtOff:])
|
||||
evtSize := getU32(data[sbOffEvtSize:])
|
||||
|
||||
arenaOff := getU32(data[sbOffArenaOff:])
|
||||
arenaCap := getU32(data[sbOffArenaCap:])
|
||||
|
||||
if int(evtOff)+int(evtSize) > len(data) {
|
||||
return nil, fmt.Errorf("unified: EvtRing 越界(off=%d size=%d total=%d)", evtOff, evtSize, len(data))
|
||||
}
|
||||
|
||||
return &unifiedRegion{
|
||||
data: data,
|
||||
ctxOff: ctxOff,
|
||||
ctxSize: ctxSize,
|
||||
evtOff: evtOff,
|
||||
evtSize: evtSize,
|
||||
data: data,
|
||||
ctxOff: ctxOff,
|
||||
ctxSize: ctxSize,
|
||||
evtOff: evtOff,
|
||||
evtSize: evtSize,
|
||||
arenaOff: arenaOff,
|
||||
arenaCap: arenaCap,
|
||||
arenaUsed: (*uint32)(unsafe.Pointer(
|
||||
uintptr(unsafe.Pointer(&data[0])) + uintptr(sbOffArenaUsed),
|
||||
)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -210,3 +241,46 @@ func getU64(b []byte) uint64 {
|
||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
||||
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
||||
}
|
||||
|
||||
// arenaAlloc 在动态 arena 中分配 n 字节,返回相对 arenaOff 的偏移。
|
||||
// append-only,offset 0 保留给“空”语义。
|
||||
func (r *unifiedRegion) arenaAlloc(n int) (uint32, error) {
|
||||
if n <= 0 {
|
||||
return 0, fmt.Errorf("arena: 非法分配长度 %d", n)
|
||||
}
|
||||
used := atomic.LoadUint32(r.arenaUsed)
|
||||
if used == 0 {
|
||||
used = 1
|
||||
}
|
||||
end := uint64(used) + uint64(n)
|
||||
if end > uint64(r.arenaCap) {
|
||||
return 0, fmt.Errorf("arena: 空间不足(需 %d,剩 %d)", n, uint64(r.arenaCap)-uint64(used))
|
||||
}
|
||||
atomic.StoreUint32(r.arenaUsed, uint32(end))
|
||||
return used, nil
|
||||
}
|
||||
|
||||
// arenaWrite 把 b 写入动态 arena 并返回 SharedRef。
|
||||
func (r *unifiedRegion) arenaWrite(b []byte) (SharedRef, error) {
|
||||
if len(b) == 0 {
|
||||
return SharedRef{}, nil
|
||||
}
|
||||
off, err := r.arenaAlloc(len(b))
|
||||
if err != nil {
|
||||
return SharedRef{}, err
|
||||
}
|
||||
base := r.arenaOff + off
|
||||
copy(r.data[base:base+uint32(len(b))], b)
|
||||
gen := uint32(r.generation())
|
||||
return SharedRef{Offset: base, Length: uint32(len(b)), Generation: gen}, nil
|
||||
}
|
||||
|
||||
// arenaRead 按 SharedRef 读取数据。
|
||||
func (r *unifiedRegion) arenaRead(ref SharedRef) []byte {
|
||||
return ref.Slice(r.data)
|
||||
}
|
||||
|
||||
// arenaReset 压实后重置游标(仅在无活跃 slot 时调用)。
|
||||
func (r *unifiedRegion) arenaReset() {
|
||||
atomic.StoreUint32(r.arenaUsed, 1)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user