How do we feel about a PR for a virtual.recommit?

I’m trying to make a lean page allocator, and I found myself wanting essentially a virtual.resize. Linux has mremap, but Windows and Posix would need to do an allocate → copy → release operation to grow. I see that could cause problems if someone tried to “resize” an uncommited page. So maybe recommit would be a decent name for it. Is this a bad idea?

Something like:

recommit :: proc "contextless" (old_data: rawptr, old_size, new_size: uint, may_move: bool = true) -> (data: []byte, err: Allocator_Error) {
|       return _recommit(old_data, old_size, new_size, may_move)
}
2 Likes

Not necessarily a bad idea. I’ll have to think about it.

2 Likes

Maybe, on second thought, it might be more dubious than it is worth if the win is limited to Linux. I originally thought mremap was part of posix. Here is what I had in mind for the generic implementation:

_recommit :: proc "contextless" (old_data: rawptr, old_size, new_size: uint, may_move: bool) -> (data: []byte, err: Allocator_Error) {
        if new_size == old_size {
                return ([^]byte)(old_data)[:old_size], nil
        }
        if new_size < old_size {
                data = ([^]byte)(old_data)[:new_size]
                unused := uintptr(&data[0]) + uintptr(new_size)
                release(rawptr(unused), old_size - new_size)  // decommit?
                return
        }
        if !may_move {
                return ([^]byte)(old_data)[:old_size], .Out_Of_Memory
        }

        data, err = reserve_and_commit(new_size)
        if err != nil {
                return ([^]byte)(old_data)[:old_size], .Out_Of_Memory
        }
        mem.copy_non_overlapping(&data[0], old_data, int(old_size))
        release(old_data, old_size)
        return
}
1 Like

For what it’s worth this is possible to implement on Darwin as well.

2 Likes