mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
Define memory Size and implement optimized memset
This commit is contained in:
parent
ca36793782
commit
61314a9c33
13
kernel/mem/constants_amd64.go
Normal file
13
kernel/mem/constants_amd64.go
Normal file
@ -0,0 +1,13 @@
|
||||
// +build amd64
|
||||
|
||||
package mem
|
||||
|
||||
const (
|
||||
// PageShift is equal to log2(PageSize). This constant is used when
|
||||
// we need to convert a physical address to a page number (shift right by PageShift)
|
||||
// and vice-versa.
|
||||
PageShift = 12
|
||||
|
||||
// PageSize defines the system's page size in bytes.
|
||||
PageSize = Size(1 << PageShift)
|
||||
)
|
29
kernel/mem/memset.go
Normal file
29
kernel/mem/memset.go
Normal file
@ -0,0 +1,29 @@
|
||||
package mem
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Memset sets size bytes at the given address to the supplied value. The implementation
|
||||
// is based on bytes.Repeat; instead of using a for loop, this function uses
|
||||
// log2(size) copy calls which should give us a speed boost as page addresses
|
||||
// are always aligned.
|
||||
func Memset(addr uintptr, value byte, size Size) {
|
||||
if size == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// overlay a slice on top of this address region
|
||||
target := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Len: int(size),
|
||||
Cap: int(size),
|
||||
Data: addr,
|
||||
}))
|
||||
|
||||
// Set first element and make log2(size) optimized copies
|
||||
target[0] = value
|
||||
for index := Size(1); index < size; index *= 2 {
|
||||
copy(target[index:], target[:index])
|
||||
}
|
||||
}
|
27
kernel/mem/memset_test.go
Normal file
27
kernel/mem/memset_test.go
Normal file
@ -0,0 +1,27 @@
|
||||
package mem
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func TestMemset(t *testing.T) {
|
||||
// memset with a 0 size should be a no-op
|
||||
Memset(uintptr(0), 0x00, 0)
|
||||
|
||||
for pageCount := uint32(1); pageCount <= 10; pageCount++ {
|
||||
buf := make([]byte, PageSize<<pageCount)
|
||||
for i := 0; i < len(buf); i++ {
|
||||
buf[i] = 0xFE
|
||||
}
|
||||
|
||||
addr := uintptr(unsafe.Pointer(&buf[0]))
|
||||
Memset(addr, 0x00, Size(len(buf)))
|
||||
|
||||
for i := 0; i < len(buf); i++ {
|
||||
if got := buf[i]; got != 0x00 {
|
||||
t.Errorf("[block with %d pages] expected byte: %d to be 0x00; got 0x%x", pageCount, i, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
kernel/mem/size.go
Normal file
12
kernel/mem/size.go
Normal file
@ -0,0 +1,12 @@
|
||||
package mem
|
||||
|
||||
// Size represents a memory block size in bytes.
|
||||
type Size uint64
|
||||
|
||||
// Common memory block sizes.
|
||||
const (
|
||||
Byte Size = 1
|
||||
Kb = 1024 * Byte
|
||||
Mb = 1024 * Kb
|
||||
Gb = 1024 * Mb
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user