Skip to content

Commit

Permalink
add syscall testing with sched tests
Browse files Browse the repository at this point in the history
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
  • Loading branch information
tonistiigi committed Dec 7, 2021
1 parent bc0b9d2 commit c0b3fbc
Show file tree
Hide file tree
Showing 6 changed files with 337 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ jobs:
uses: docker/setup-buildx-action@v1
with:
config: .github/buildkit.toml
buildkitd-flags: --allow-insecure-entitlement=security.insecure
-
name: Test buildkit
if: matrix.target == 'buildkit'
Expand Down Expand Up @@ -110,6 +111,11 @@ jobs:
docker run --rm --platform=linux/s390x s390x/ubuntu apt update
docker run --rm --platform=linux/ppc64le ppc64le/ubuntu apt update
docker run --rm --platform=linux/arm64 arm64v8/ubuntu apt update
- name: Test Syscalls
if: matrix.target == 'mainline'
run: |
set -x
docker buildx build --platform=linux/amd64,linux/arm64,linux/386,linux/arm,linux/ppc64le,linux/s390x --target=run --allow security.insecure --build-arg CONFIG_RT_GROUP_SCHED=false ./test
-
name: Login to DockerHub
if: startsWith(github.ref, 'refs/heads/')
Expand Down
30 changes: 30 additions & 0 deletions test/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#syntax=docker/dockerfile:1.3-labs

FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.1.0 AS xx

FROM scratch AS src
COPY *.go go.* /

FROM --platform=$BUILDPLATFORM golang:1.17-alpine AS build
COPY --from=xx / /
RUN apk add clang lld file
ARG TARGETPLATFORM
RUN xx-apk add musl-dev linux-headers gcc
WORKDIR /src
RUN XX_CC_PREFER_STATIC_LINKER=1 xx-clang --setup-target-triple
RUN --mount=from=src \
--mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg \
CGO_ENABLED=1 xx-go test -c -o /out/test -ldflags "-linkmode external -extldflags -static" . && \
xx-verify --static /out/test

FROM scratch AS binary
COPY --from=build /out/test .

FROM alpine AS run
RUN apk add libcap
COPY --from=binary / /usr/bin
ARG CONFIG_RT_GROUP_SCHED
RUN --security=insecure /usr/bin/test -test.v

FROM binary
14 changes: 14 additions & 0 deletions test/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module github.com/tonistiigi/binfmt/test

go 1.17

require (
github.com/stretchr/testify v1.7.0
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881
)

require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
13 changes: 13 additions & 0 deletions test/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
122 changes: 122 additions & 0 deletions test/sched.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package tests

import (
"syscall"
"unsafe"

"golang.org/x/sys/unix"
)

// #include <linux/sched.h>
// #include <linux/sched/types.h>
// typedef struct sched_param sched_param;
import "C"

type Policy uint32

const (
SCHED_NORMAL Policy = C.SCHED_NORMAL
SCHED_FIFO Policy = C.SCHED_FIFO
SCHED_RR Policy = C.SCHED_RR
SCHED_BATCH Policy = C.SCHED_BATCH
SCHED_IDLE Policy = C.SCHED_IDLE
SCHED_DEADLINE Policy = C.SCHED_DEADLINE
)

type SchedFlag int

const (
SCHED_FLAG_RESET_ON_FORK SchedFlag = C.SCHED_FLAG_RESET_ON_FORK
SCHED_FLAG_RECLAIM SchedFlag = C.SCHED_FLAG_RECLAIM
SCHED_FLAG_DL_OVERRUN SchedFlag = C.SCHED_FLAG_DL_OVERRUN
)

type SchedParam C.sched_param

func SchedGetScheduler(pid int) (Policy, error) {
r0, _, e1 := unix.Syscall(unix.SYS_SCHED_GETSCHEDULER, uintptr(pid), 0, 0)
if e1 != 0 {
return 0, syscall.Errno(e1)
}
return Policy(r0), nil
}

func SchedSetScheduler(pid int, p Policy, param SchedParam) error {
_, _, e1 := unix.Syscall(unix.SYS_SCHED_SETSCHEDULER, uintptr(pid), uintptr(p), uintptr(unsafe.Pointer(&param)))
if e1 != 0 {
return syscall.Errno(e1)
}
return nil
}

func SchedGetPriorityMin(p Policy) (int, error) {
r0, _, e1 := unix.Syscall(unix.SYS_SCHED_GET_PRIORITY_MIN, uintptr(p), 0, 0)
if e1 != 0 {
return 0, syscall.Errno(e1)
}
return int(r0), nil
}

func SchedGetPriorityMax(p Policy) (int, error) {
r0, _, e1 := unix.Syscall(unix.SYS_SCHED_GET_PRIORITY_MAX, uintptr(p), 0, 0)
if e1 != 0 {
return 0, syscall.Errno(e1)
}
return int(r0), nil
}

func SchedYield() error {
_, _, e1 := unix.Syscall(unix.SYS_SCHED_YIELD, 0, 0, 0)
if e1 != 0 {
return syscall.Errno(e1)
}
return nil
}

func SchedGetParam(pid int) (SchedParam, error) {
var param SchedParam
_, _, e1 := unix.Syscall(unix.SYS_SCHED_GETPARAM, uintptr(pid), uintptr(unsafe.Pointer(&param)), 0)
if e1 != 0 {
return param, syscall.Errno(e1)
}
return param, nil
}

func SchedSetParam(pid int, param SchedParam) error {
_, _, e1 := unix.Syscall(unix.SYS_SCHED_SETPARAM, uintptr(pid), uintptr(unsafe.Pointer(&param)), 0)
if e1 != 0 {
return syscall.Errno(e1)
}
return nil
}

type SchedAttr struct {
Size uint32
SchedPolicy Policy
SchedFlags uint64
SchedNice uint32
SchedPriority uint32
SchedRuntime uint64
SchedDeadline uint64
SchedPeriod uint64
SchedUtilMin uint32
SchedUtilMax uint32
}

func SchedGetAttr(pid int) (SchedAttr, error) {
var attr SchedAttr
_, _, e1 := unix.Syscall6(unix.SYS_SCHED_GETATTR, uintptr(pid), uintptr(unsafe.Pointer(&attr)), unsafe.Sizeof(SchedAttr{}), 0, 0, 0)
if e1 != 0 {
return attr, syscall.Errno(e1)
}
return attr, nil
}

func SchedSetAttr(pid int, attr SchedAttr, flags SchedFlag) error {
attr.Size = uint32(unsafe.Sizeof(attr))
_, _, e1 := unix.Syscall(unix.SYS_SCHED_SETATTR, uintptr(pid), uintptr(unsafe.Pointer(&attr)), uintptr(flags))
if e1 != 0 {
return syscall.Errno(e1)
}
return nil
}
152 changes: 152 additions & 0 deletions test/sched_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package tests

import (
"errors"
"os"
"runtime"
"strconv"
"syscall"
"testing"

"github.com/stretchr/testify/require"
)

var CONFIG_RT_GROUP_SCHED bool = true

func init() {
runtime.LockOSThread()

if v := os.Getenv("CONFIG_RT_GROUP_SCHED"); v != "" {
if vv, err := strconv.ParseBool(v); err == nil {
CONFIG_RT_GROUP_SCHED = vv
}
}
}

func TestGetSetScheduler(t *testing.T) {
_, err := SchedGetScheduler(1 << 30)
require.Error(t, err)

pid := os.Getpid()
s, err := SchedGetScheduler(pid)
require.NoError(t, err)
require.Equal(t, SCHED_NORMAL, s)

// priority
err = SchedSetScheduler(pid, SCHED_RR, SchedParam{
sched_priority: 100,
})
require.True(t, errors.Is(err, syscall.EINVAL))

err = SchedSetScheduler(pid, SCHED_RR, SchedParam{
sched_priority: 90,
})
require.True(t, !errors.Is(err, syscall.EINVAL))

if CONFIG_RT_GROUP_SCHED {
t.Logf("skipping scheduler set checks")
} else {
require.NoError(t, err)

s, err := SchedGetScheduler(pid)
require.NoError(t, err)
require.Equal(t, SCHED_RR, s)

p, err := SchedGetParam(pid)
require.NoError(t, err)
require.Equal(t, 90, int(p.sched_priority))
}

err = SchedSetScheduler(pid, SCHED_IDLE, SchedParam{})
require.NoError(t, err)

s, err = SchedGetScheduler(pid)
require.NoError(t, err)
require.Equal(t, SCHED_IDLE, s)

err = SchedSetScheduler(pid, SCHED_NORMAL, SchedParam{})
require.NoError(t, err)
}

func TestSchedMinMax(t *testing.T) {
p, err := SchedGetPriorityMin(SCHED_RR)
require.NoError(t, err)
require.Equal(t, 1, p)

p, err = SchedGetPriorityMax(SCHED_RR)
require.NoError(t, err)
require.Equal(t, 99, p)

p, err = SchedGetPriorityMax(SCHED_BATCH)
require.NoError(t, err)
require.Equal(t, 0, p)
}

func TestSchedYield(t *testing.T) {
err := SchedYield()
require.NoError(t, err)
}

func TestSchedGetSetParam(t *testing.T) {
pid := os.Getpid()

p, err := SchedGetParam(pid)
require.NoError(t, err)

require.Equal(t, 0, int(p.sched_priority))

err = SchedSetParam(pid, SchedParam{})
require.NoError(t, err)

if CONFIG_RT_GROUP_SCHED {
t.Logf("skipping setting sched_priority")
} else {
err = SchedSetScheduler(pid, SCHED_RR, SchedParam{sched_priority: 50})
require.NoError(t, err)

p, err := SchedGetParam(pid)
require.NoError(t, err)

require.Equal(t, 50, int(p.sched_priority))
}
}

func TestSchedAttr(t *testing.T) {
pid := os.Getpid()

if !CONFIG_RT_GROUP_SCHED {
err := SchedSetScheduler(pid, SCHED_RR, SchedParam{sched_priority: 50})
require.NoError(t, err)
}

attr, err := SchedGetAttr(pid)
require.NoError(t, err)

require.True(t, attr.Size >= 0x30)

if CONFIG_RT_GROUP_SCHED {
require.Equal(t, SCHED_NORMAL, attr.SchedPolicy)

attr := SchedAttr{SchedPolicy: SCHED_IDLE}
err := SchedSetAttr(pid, attr, 0)
require.NoError(t, err)

attr, err = SchedGetAttr(pid)
require.NoError(t, err)
require.Equal(t, SCHED_IDLE, attr.SchedPolicy)

t.Logf("skipping setting attr priority")
} else {
require.Equal(t, SCHED_RR, attr.SchedPolicy)
require.Equal(t, 50, int(attr.SchedPriority))

attr := SchedAttr{SchedPolicy: SCHED_RR, SchedPriority: 60}
err := SchedSetAttr(pid, attr, 0)
require.NoError(t, err)

attr, err = SchedGetAttr(pid)
require.NoError(t, err)
require.Equal(t, SCHED_RR, attr.SchedPolicy)
require.Equal(t, 60, int(attr.SchedPriority))
}
}

0 comments on commit c0b3fbc

Please sign in to comment.