Skip to content

Commit

Permalink
Switch to Append style encoding
Browse files Browse the repository at this point in the history
Signed-off-by: Alun Evans <[email protected]>
  • Loading branch information
alxn committed Dec 1, 2023
1 parent feba017 commit 79a6817
Showing 1 changed file with 19 additions and 17 deletions.
36 changes: 19 additions & 17 deletions marshalers.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/cilium/ebpf/internal"
"github.com/cilium/ebpf/internal/sys"
"github.com/cilium/ebpf/internal/sysenc"
"golang.org/x/exp/slices"
)

// marshalMapSyscallInput converts an arbitrary value into a pointer suitable
Expand Down Expand Up @@ -43,33 +44,36 @@ func makeMapSyscallOutput(dst any, length int) sysenc.Buffer {
return sysenc.SyscallOutput(dst, length)
}

// marshalSlice encodes a slice containing one value per
// appendPerCPUSlice encodes a slice containing one value per
// possible CPU into a buffer of bytes.
//
// Values are initialized to zero if the slice has less elements than CPUs.
func marshalSlice(slice any, elemLength, possibleCPUs, alignedElemLength int, buf []byte) error {
func appendPerCPUSlice(buf []byte, slice any, possibleCPUs, elemLength, alignedElemLength int) ([]byte, error) {
sliceType := reflect.TypeOf(slice)
if sliceType.Kind() != reflect.Slice {
return errors.New("per-CPU value requires slice")
return nil, errors.New("per-CPU value requires slice")
}

sliceValue := reflect.ValueOf(slice)
sliceLen := sliceValue.Len()
if sliceLen > possibleCPUs {
return fmt.Errorf("per-CPU value exceeds number of CPUs")
return nil, fmt.Errorf("per-CPU value exceeds number of CPUs")
}

// Grow increases the slice's capacity, _if_necessary_
buf = slices.Grow(buf, alignedElemLength*possibleCPUs)
for i := 0; i < sliceLen; i++ {
elem := sliceValue.Index(i).Interface()
elemBytes, err := sysenc.Marshal(elem, elemLength)
if err != nil {
return err
return nil, err
}

offset := i * alignedElemLength
elemBytes.CopyTo(buf[offset : offset+elemLength])
b := make([]byte, alignedElemLength)
elemBytes.CopyTo(b) // Only copies elemLength
buf = append(buf, b...)
}
return nil
return buf, nil
}

// marshalPerCPUValue encodes a slice containing one value per
Expand All @@ -83,8 +87,9 @@ func marshalPerCPUValue(slice any, elemLength int) (sys.Pointer, error) {
}

alignedElemLength := internal.Align(elemLength, 8)
buf := make([]byte, alignedElemLength*possibleCPUs)
if err := marshalSlice(slice, elemLength, possibleCPUs, alignedElemLength, buf); err != nil {
buf := make([]byte, 0, alignedElemLength*possibleCPUs)
buf, err = appendPerCPUSlice(buf, slice, possibleCPUs, elemLength, alignedElemLength)
if err != nil {
return sys.Pointer{}, err
}

Expand All @@ -108,18 +113,15 @@ func marshalBatchPerCPUValue(slice any, batchLen, elemLength int) (sys.Pointer,
}

alignedElemLength := internal.Align(elemLength, 8)
stride := alignedElemLength * possibleCPUs
result := make([]byte, batchLen*stride)
buf := result
buf := make([]byte, 0, batchLen*alignedElemLength*possibleCPUs)
for i := 0; i < batchLen; i++ {
batch := sliceValue.Slice(i*possibleCPUs, (i+1)*possibleCPUs).Interface()
if err := marshalSlice(batch, elemLength, possibleCPUs, alignedElemLength, buf[:stride]); err != nil {
buf, err = appendPerCPUSlice(buf, batch, possibleCPUs, elemLength, alignedElemLength)
if err != nil {
return sys.Pointer{}, fmt.Errorf("batch %d: %w", i, err)
}

buf = buf[stride:]
}
return sys.NewSlicePointer(result), nil
return sys.NewSlicePointer(buf), nil
}

// unmarshalPerCPUValue decodes a buffer into a slice containing one value per
Expand Down

0 comments on commit 79a6817

Please sign in to comment.