upgrade deps to kcp-go@v5.5.16 and golang 1.14.9

This commit is contained in:
xtaci
2020-09-30 18:47:09 +08:00
parent e3c5c133a6
commit 335b2d35bb
142 changed files with 3308 additions and 1596 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
FROM golang:1.14.2-alpine3.11 as builder
FROM golang:1.14.9-alpine3.11 as builder
MAINTAINER xtaci <daniel820313@gmail.com>
ENV GO111MODULE=on
RUN apk update && \
+2 -9
View File
@@ -4,19 +4,12 @@ require (
github.com/coreos/go-iptables v0.4.2 // indirect
github.com/golang/snappy v0.0.1
github.com/google/gopacket v1.1.17 // indirect
github.com/klauspost/cpuid v1.2.3 // indirect
github.com/pkg/errors v0.9.1
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
github.com/tjfoc/gmsm v1.3.0 // indirect
github.com/urfave/cli v1.21.0
github.com/xtaci/kcp-go v5.4.20+incompatible // indirect
github.com/xtaci/kcp-go/v5 v5.5.14
github.com/xtaci/kcp-go/v5 v5.5.16
github.com/xtaci/smux v1.5.14
github.com/xtaci/tcpraw v1.2.25
golang.org/x/crypto v0.0.0-20200320181102-891825fb96df
golang.org/x/net v0.0.0-20200320220750-118fecf932d8 // indirect
golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae // indirect
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
)
go 1.14
+44 -36
View File
@@ -5,62 +5,70 @@ github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY=
github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
github.com/klauspost/cpuid v1.2.2 h1:1xAgYebNnsb9LKCdLOvFWtAxGU/33mjJtyOVbmUa0Us=
github.com/klauspost/cpuid v1.2.2/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs=
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/reedsolomon v1.9.3 h1:N/VzgeMfHmLc+KHMD1UL/tNkfXAt8FnUqlgXGIduwAY=
github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
github.com/klauspost/reedsolomon v1.9.9 h1:qCL7LZlv17xMixl55nq2/Oa1Y86nfO8EqDfv2GHND54=
github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo=
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 h1:ULR/QWMgcgRiZLUjSSJMU+fW+RDMstRdmnDWj9Q+AsA=
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/templexxx/cpu v0.0.1 h1:hY4WdLOgKdc8y13EYklu9OUTXik80BkxHoWvTO6MQQY=
github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI=
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/templexxx/cpu v0.0.7 h1:pUEZn8JBy/w5yzdYWgx+0m0xL9uk6j4K91C5kOViAzo=
github.com/templexxx/cpu v0.0.7/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
github.com/templexxx/xorsimd v0.4.1 h1:iUZcywbOYDRAZUasAs2eSCUW8eobuZDy0I9FJiORkVg=
github.com/templexxx/xorsimd v0.4.1/go.mod h1:W+ffZz8jJMH2SXwuKu9WhygqBMbFnp14G2fqEr8qaNo=
github.com/tjfoc/gmsm v1.0.1 h1:R11HlqhXkDospckjZEihx9SW/2VW0RgdwrykyWMFOQU=
github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
github.com/tjfoc/gmsm v1.3.0 h1:i7c6Za/IlgBvnGxYpfD7L3TGuaS+v6oGcgq+J9/ecEA=
github.com/tjfoc/gmsm v1.3.0/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/urfave/cli v1.21.0 h1:wYSSj06510qPIzGSua9ZqsncMmWE3Zr55KBERygyrxE=
github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ=
github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZWQ1bABv5xAg=
github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
github.com/xtaci/kcp-go/v5 v5.5.11 h1:wYvoREAp6bG3sYwtxhY1QelbB/1fNggCtkt2DwqFj2M=
github.com/xtaci/kcp-go/v5 v5.5.11/go.mod h1:Oyw+zrBrO58urX1AaWV+2RynthEKcs+qrRAh0Q8YpdU=
github.com/xtaci/kcp-go/v5 v5.5.14-0.20200701100455-43d2c47d8ac1 h1:bnQj12vKzlMDxNGzFTj7ZDgXXpUpEQsX9mF/s7hD68o=
github.com/xtaci/kcp-go/v5 v5.5.14-0.20200701100455-43d2c47d8ac1/go.mod h1:H0T/EJ+lPNytnFYsKLH0JHUtiwZjG3KXlTM6c+Q4YUo=
github.com/xtaci/kcp-go/v5 v5.5.14 h1:YODIwvTyZmOTj3SduJeIcQPxthDoHllMm8YIBlK44Ik=
github.com/xtaci/kcp-go/v5 v5.5.14/go.mod h1:H0T/EJ+lPNytnFYsKLH0JHUtiwZjG3KXlTM6c+Q4YUo=
github.com/xtaci/kcp-go/v5 v5.5.16 h1:doQfgOdghnuqnOxsr1fR5kWTxV/X15bUKQXMc11uiOU=
github.com/xtaci/kcp-go/v5 v5.5.16/go.mod h1:pVx3jb4LT5edTmPayc77tIU9nRsjGck8wep5ZV/RBO0=
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
github.com/xtaci/smux v1.5.14 h1:1j+zJYDZRv9FHaWqCJfH5RPizIm0fSzJIFbfVn8zsfg=
github.com/xtaci/smux v1.5.14/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY=
github.com/xtaci/tcpraw v1.2.25 h1:VDlqo0op17JeXBM6e2G9ocCNLOJcw9mZbobMbJjo0vk=
github.com/xtaci/tcpraw v1.2.25/go.mod h1:dKyZ2V75s0cZ7cbgJYdxPvms7af0joIeOyx1GgJQbLk=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200320181102-891825fb96df h1:lDWgvUvNnaTnNBc/dwOty86cFeKoKWbwy2wQj0gIxbU=
golang.org/x/crypto v0.0.0-20200320181102-891825fb96df/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200320220750-118fecf932d8 h1:1+zQlQqEEhUeStBTi653GZAnAuivZq/2hz+Iz+OP7rg=
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 h1:JA8d3MPx/IToSyXZG/RhwYEtfrKO1Fxrqe8KrkiLXKM=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae h1:3tcmuaB7wwSZtelmiv479UjUB+vviwABz7a133ZwOKQ=
golang.org/x/sys v0.0.0-20200321134203-328b4cd54aae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9 h1:yi1hN8dcqI9l8klZfy4B8mJvFmmAxJEePIQQFNSd7Cs=
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123 h1:4JSJPND/+4555t1HfXYF4UEqDqiSKCgeV0+hbA8hMs4=
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+33 -10
View File
@@ -1,23 +1,46 @@
language: go
sudo: false
os:
- linux
- osx
- osx
- windows
arch:
- amd64
- arm64
go:
- 1.11.x
- 1.12.x
- 1.13.x
- 1.14.x
- master
script:
- go vet ./...
- go test -v ./...
- go test -race ./...
- diff <(gofmt -d .) <("")
script:
- go vet ./...
- go test -race ./...
- go test -tags=noasm ./...
stages:
- gofmt
- test
matrix:
allow_failures:
- go: 'master'
fast_finish: true
fast_finish: true
include:
- stage: gofmt
go: 1.14.x
os: linux
arch: amd64
script:
- diff <(gofmt -d .) <(printf "")
- diff <(gofmt -d ./private) <(printf "")
- go install github.com/klauspost/asmfmt/cmd/asmfmt
- diff <(asmfmt -d .) <(printf "")
- stage: i386
go: 1.14.x
os: linux
arch: amd64
script:
- GOOS=linux GOARCH=386 go test .
+37 -3
View File
@@ -2,7 +2,7 @@
Package cpuid provides information about the CPU running the current program.
CPU features are detected on startup, and kept for fast access through the life of the application.
Currently x86 / x64 (AMD64) is supported, and no external C (cgo) code is used, which should make the library very easy to use.
Currently x86 / x64 (AMD64/i386) and ARM (ARM64) is supported, and no external C (cgo) code is used, which should make the library very easy to use.
You can access the CPU information by accessing the shared CPU variable of the cpuid library.
@@ -12,11 +12,12 @@ Package home: https://github.com/klauspost/cpuid
[1]: https://godoc.org/github.com/klauspost/cpuid?status.svg
[2]: https://godoc.org/github.com/klauspost/cpuid
[3]: https://travis-ci.org/klauspost/cpuid.svg
[3]: https://travis-ci.org/klauspost/cpuid.svg?branch=master
[4]: https://travis-ci.org/klauspost/cpuid
# features
## CPU Instructions
## x86 CPU Instructions
* **CMOV** (i686 CMOV)
* **NX** (NX (No-Execute) bit)
* **AMD3DNOW** (AMD 3DNOW)
@@ -83,6 +84,39 @@ Package home: https://github.com/klauspost/cpuid
* **Cache line** (Probable size of a cache line).
* **L1, L2, L3 Cache size** on newer Intel/AMD CPUs.
## ARM CPU features
# ARM FEATURE DETECTION DISABLED!
See [#52](https://github.com/klauspost/cpuid/issues/52).
Currently only `arm64` platforms are implemented.
* **FP** Single-precision and double-precision floating point
* **ASIMD** Advanced SIMD
* **EVTSTRM** Generic timer
* **AES** AES instructions
* **PMULL** Polynomial Multiply instructions (PMULL/PMULL2)
* **SHA1** SHA-1 instructions (SHA1C, etc)
* **SHA2** SHA-2 instructions (SHA256H, etc)
* **CRC32** CRC32/CRC32C instructions
* **ATOMICS** Large System Extensions (LSE)
* **FPHP** Half-precision floating point
* **ASIMDHP** Advanced SIMD half-precision floating point
* **ARMCPUID** Some CPU ID registers readable at user-level
* **ASIMDRDM** Rounding Double Multiply Accumulate/Subtract (SQRDMLAH/SQRDMLSH)
* **JSCVT** Javascript-style double->int convert (FJCVTZS)
* **FCMA** Floating point complex number addition and multiplication
* **LRCPC** Weaker release consistency (LDAPR, etc)
* **DCPOP** Data cache clean to Point of Persistence (DC CVAP)
* **SHA3** SHA-3 instructions (EOR3, RAXI, XAR, BCAX)
* **SM3** SM3 instructions
* **SM4** SM4 instructions
* **ASIMDDP** SIMD Dot Product
* **SHA512** SHA512 instructions
* **SVE** Scalable Vector Extension
* **GPA** Generic Pointer Authentication
## Cpu Vendor/VM
* **Intel**
* **AMD**
+363 -43
View File
@@ -3,14 +3,20 @@
// Package cpuid provides information about the CPU running the current program.
//
// CPU features are detected on startup, and kept for fast access through the life of the application.
// Currently x86 / x64 (AMD64) is supported.
// Currently x86 / x64 (AMD64) as well as arm64 is supported.
//
// You can access the CPU information by accessing the shared CPU variable of the cpuid library.
//
// Package home: https://github.com/klauspost/cpuid
package cpuid
import "strings"
import (
"math"
"strings"
)
// AMD refererence: https://www.amd.com/system/files/TechDocs/25481.pdf
// and Processor Programming Reference (PPR)
// Vendor is a representation of a CPU vendor.
type Vendor int
@@ -28,6 +34,8 @@ const (
XenHVM
Bhyve
Hygon
SiS
RDC
)
const (
@@ -167,22 +175,81 @@ var flagNames = map[Flags]string{
}
/* all special features for arm64 should be defined here */
const (
/* extension instructions */
FP ArmFlags = 1 << iota
ASIMD
EVTSTRM
AES
PMULL
SHA1
SHA2
CRC32
ATOMICS
FPHP
ASIMDHP
ARMCPUID
ASIMDRDM
JSCVT
FCMA
LRCPC
DCPOP
SHA3
SM3
SM4
ASIMDDP
SHA512
SVE
GPA
)
var flagNamesArm = map[ArmFlags]string{
FP: "FP", // Single-precision and double-precision floating point
ASIMD: "ASIMD", // Advanced SIMD
EVTSTRM: "EVTSTRM", // Generic timer
AES: "AES", // AES instructions
PMULL: "PMULL", // Polynomial Multiply instructions (PMULL/PMULL2)
SHA1: "SHA1", // SHA-1 instructions (SHA1C, etc)
SHA2: "SHA2", // SHA-2 instructions (SHA256H, etc)
CRC32: "CRC32", // CRC32/CRC32C instructions
ATOMICS: "ATOMICS", // Large System Extensions (LSE)
FPHP: "FPHP", // Half-precision floating point
ASIMDHP: "ASIMDHP", // Advanced SIMD half-precision floating point
ARMCPUID: "CPUID", // Some CPU ID registers readable at user-level
ASIMDRDM: "ASIMDRDM", // Rounding Double Multiply Accumulate/Subtract (SQRDMLAH/SQRDMLSH)
JSCVT: "JSCVT", // Javascript-style double->int convert (FJCVTZS)
FCMA: "FCMA", // Floatin point complex number addition and multiplication
LRCPC: "LRCPC", // Weaker release consistency (LDAPR, etc)
DCPOP: "DCPOP", // Data cache clean to Point of Persistence (DC CVAP)
SHA3: "SHA3", // SHA-3 instructions (EOR3, RAXI, XAR, BCAX)
SM3: "SM3", // SM3 instructions
SM4: "SM4", // SM4 instructions
ASIMDDP: "ASIMDDP", // SIMD Dot Product
SHA512: "SHA512", // SHA512 instructions
SVE: "SVE", // Scalable Vector Extension
GPA: "GPA", // Generic Pointer Authentication
}
// CPUInfo contains information about the detected system CPU.
type CPUInfo struct {
BrandName string // Brand name reported by the CPU
VendorID Vendor // Comparable CPU vendor ID
Features Flags // Features of the CPU
PhysicalCores int // Number of physical processor cores in your CPU. Will be 0 if undetectable.
ThreadsPerCore int // Number of threads per physical core. Will be 1 if undetectable.
LogicalCores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable.
Family int // CPU family number
Model int // CPU model number
CacheLine int // Cache line size in bytes. Will be 0 if undetectable.
BrandName string // Brand name reported by the CPU
VendorID Vendor // Comparable CPU vendor ID
VendorString string // Raw vendor string.
Features Flags // Features of the CPU (x64)
Arm ArmFlags // Features of the CPU (arm)
PhysicalCores int // Number of physical processor cores in your CPU. Will be 0 if undetectable.
ThreadsPerCore int // Number of threads per physical core. Will be 1 if undetectable.
LogicalCores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable.
Family int // CPU family number
Model int // CPU model number
CacheLine int // Cache line size in bytes. Will be 0 if undetectable.
Hz int64 // Clock speed, if known
Cache struct {
L1I int // L1 Instruction Cache (per core or shared). Will be -1 if undetected
L1D int // L1 Data Cache (per core or shared). Will be -1 if undetected
L2 int // L2 Cache (per core or shared). Will be -1 if undetected
L3 int // L3 Instruction Cache (per core or shared). Will be -1 if undetected
L3 int // L3 Cache (per core, per ccx or shared). Will be -1 if undetected
}
SGX SGXSupport
maxFunc uint32
@@ -197,8 +264,7 @@ var rdtscpAsm func() (eax, ebx, ecx, edx uint32)
// CPU contains information about the CPU as detected on startup,
// or when Detect last was called.
//
// Use this as the primary entry point to you data,
// this way queries are
// Use this as the primary entry point to you data.
var CPU CPUInfo
func init() {
@@ -214,18 +280,13 @@ func init() {
// If you call this, you must ensure that no other goroutine is accessing the
// exported CPU variable.
func Detect() {
CPU.maxFunc = maxFunctionID()
CPU.maxExFunc = maxExtendedFunction()
CPU.BrandName = brandName()
CPU.CacheLine = cacheLine()
CPU.Family, CPU.Model = familyModel()
CPU.Features = support()
CPU.SGX = hasSGX(CPU.Features&SGX != 0, CPU.Features&SGXLC != 0)
CPU.ThreadsPerCore = threadsPerCore()
CPU.LogicalCores = logicalCores()
CPU.PhysicalCores = physicalCores()
CPU.VendorID = vendorID()
CPU.cacheSize()
// Set defaults
CPU.ThreadsPerCore = 1
CPU.Cache.L1I = -1
CPU.Cache.L1D = -1
CPU.Cache.L2 = -1
CPU.Cache.L3 = -1
addInfo(&CPU)
}
// Generated here: http://play.golang.org/p/BxFH2Gdc0G
@@ -601,6 +662,65 @@ func (c CPUInfo) LogicalCPU() int {
return int(ebx >> 24)
}
// hertz tries to compute the clock speed of the CPU. If leaf 15 is
// supported, use it, otherwise parse the brand string. Yes, really.
func hertz(model string) int64 {
mfi := maxFunctionID()
if mfi >= 0x15 {
eax, ebx, ecx, _ := cpuid(0x15)
if eax != 0 && ebx != 0 && ecx != 0 {
return int64((int64(ecx) * int64(ebx)) / int64(eax))
}
}
// computeHz determines the official rated speed of a CPU from its brand
// string. This insanity is *actually the official documented way to do
// this according to Intel*, prior to leaf 0x15 existing. The official
// documentation only shows this working for exactly `x.xx` or `xxxx`
// cases, e.g., `2.50GHz` or `1300MHz`; this parser will accept other
// sizes.
hz := strings.LastIndex(model, "Hz")
if hz < 3 {
return -1
}
var multiplier int64
switch model[hz-1] {
case 'M':
multiplier = 1000 * 1000
case 'G':
multiplier = 1000 * 1000 * 1000
case 'T':
multiplier = 1000 * 1000 * 1000 * 1000
}
if multiplier == 0 {
return -1
}
freq := int64(0)
divisor := int64(0)
decimalShift := int64(1)
var i int
for i = hz - 2; i >= 0 && model[i] != ' '; i-- {
if model[i] >= '0' && model[i] <= '9' {
freq += int64(model[i]-'0') * decimalShift
decimalShift *= 10
} else if model[i] == '.' {
if divisor != 0 {
return -1
}
divisor = decimalShift
} else {
return -1
}
}
// we didn't find a space
if i < 0 {
return -1
}
if divisor != 0 {
return (freq * multiplier) / divisor
}
return freq * multiplier
}
// VM Will return true if the cpu id indicates we are in
// a virtual machine. This is only a hint, and will very likely
// have many false negatives.
@@ -612,29 +732,49 @@ func (c CPUInfo) VM() bool {
return false
}
// Flags contains detected cpu features and caracteristics
// Flags contains detected cpu features and characteristics
type Flags uint64
// ArmFlags contains detected ARM cpu features and characteristics
type ArmFlags uint64
// String returns a string representation of the detected
// CPU features.
func (f Flags) String() string {
return strings.Join(f.Strings(), ",")
}
// Strings returns and array of the detected features.
// Strings returns an array of the detected features.
func (f Flags) Strings() []string {
s := support()
r := make([]string, 0, 20)
for i := uint(0); i < 64; i++ {
key := Flags(1 << i)
val := flagNames[key]
if s&key != 0 {
if f&key != 0 {
r = append(r, val)
}
}
return r
}
// String returns a string representation of the detected
// CPU features.
func (f ArmFlags) String() string {
return strings.Join(f.Strings(), ",")
}
// Strings returns an array of the detected features.
func (f ArmFlags) Strings() []string {
r := make([]string, 0, 20)
for i := uint(0); i < 64; i++ {
key := ArmFlags(1 << i)
val := flagNamesArm[key]
if f&key != 0 {
r = append(r, val)
}
}
return r
}
func maxExtendedFunction() uint32 {
eax, _, _, _ := cpuid(0x80000000)
return eax
@@ -659,11 +799,16 @@ func brandName() string {
func threadsPerCore() int {
mfi := maxFunctionID()
if mfi < 0x4 || vendorID() != Intel {
vend, _ := vendorID()
if mfi < 0x4 || (vend != Intel && vend != AMD) {
return 1
}
if mfi < 0xb {
if vend != Intel {
return 1
}
_, b, _, d := cpuid(1)
if (d & (1 << 28)) != 0 {
// v will contain logical core count
@@ -688,7 +833,8 @@ func threadsPerCore() int {
func logicalCores() int {
mfi := maxFunctionID()
switch vendorID() {
v, _ := vendorID()
switch v {
case Intel:
// Use this on old Intel processors
if mfi < 0xb {
@@ -723,10 +869,18 @@ func familyModel() (int, int) {
}
func physicalCores() int {
switch vendorID() {
v, _ := vendorID()
switch v {
case Intel:
return logicalCores() / threadsPerCore()
case AMD, Hygon:
lc := logicalCores()
tpc := threadsPerCore()
if lc > 0 && tpc > 0 {
return lc / tpc
}
// The following is inaccurate on AMD EPYC 7742 64-Core Processor
if maxExtendedFunction() >= 0x80000008 {
_, _, c, _ := cpuid(0x80000008)
return int(c&0xff) + 1
@@ -751,16 +905,20 @@ var vendorMapping = map[string]Vendor{
"XenVMMXenVMM": XenHVM,
"bhyve bhyve ": Bhyve,
"HygonGenuine": Hygon,
"Vortex86 SoC": SiS,
"SiS SiS SiS ": SiS,
"RiseRiseRise": SiS,
"Genuine RDC": RDC,
}
func vendorID() Vendor {
func vendorID() (Vendor, string) {
_, b, c, d := cpuid(0)
v := valAsString(b, d, c)
vend, ok := vendorMapping[string(v)]
v := string(valAsString(b, d, c))
vend, ok := vendorMapping[v]
if !ok {
return Other
return Other, v
}
return vend
return vend, v
}
func cacheLine() int {
@@ -783,7 +941,7 @@ func (c *CPUInfo) cacheSize() {
c.Cache.L1I = -1
c.Cache.L2 = -1
c.Cache.L3 = -1
vendor := vendorID()
vendor, _ := vendorID()
switch vendor {
case Intel:
if maxFunctionID() < 4 {
@@ -837,6 +995,49 @@ func (c *CPUInfo) cacheSize() {
}
_, _, ecx, _ = cpuid(0x80000006)
c.Cache.L2 = int(((ecx >> 16) & 0xFFFF) * 1024)
// CPUID Fn8000_001D_EAX_x[N:0] Cache Properties
if maxExtendedFunction() < 0x8000001D {
return
}
for i := uint32(0); i < math.MaxUint32; i++ {
eax, ebx, ecx, _ := cpuidex(0x8000001D, i)
level := (eax >> 5) & 7
cacheNumSets := ecx + 1
cacheLineSize := 1 + (ebx & 2047)
cachePhysPartitions := 1 + ((ebx >> 12) & 511)
cacheNumWays := 1 + ((ebx >> 22) & 511)
typ := eax & 15
size := int(cacheNumSets * cacheLineSize * cachePhysPartitions * cacheNumWays)
if typ == 0 {
return
}
switch level {
case 1:
switch typ {
case 1:
// Data cache
c.Cache.L1D = size
case 2:
// Inst cache
c.Cache.L1I = size
default:
if c.Cache.L1D < 0 {
c.Cache.L1I = size
}
if c.Cache.L1I < 0 {
c.Cache.L1I = size
}
}
case 2:
c.Cache.L2 = size
case 3:
c.Cache.L3 = size
}
}
}
return
@@ -895,7 +1096,7 @@ func hasSGX(available, lc bool) (rval SGXSupport) {
func support() Flags {
mfi := maxFunctionID()
vend := vendorID()
vend, _ := vendorID()
if mfi < 0x1 {
return 0
}
@@ -954,7 +1155,11 @@ func support() Flags {
rval |= HTT
}
}
if vend == AMD && (d&(1<<28)) != 0 && mfi >= 4 {
if threadsPerCore() > 1 {
rval |= HTT
}
}
// Check XGETBV, OXSAVE and AVX bits
if c&(1<<26) != 0 && c&(1<<27) != 0 && c&(1<<28) != 0 {
// Check for OS support
@@ -1119,7 +1324,7 @@ func support() Flags {
AV_CPU_FLAG_SSE2 and AV_CPU_FLAG_SSE2SLOW are both set in this case
so that SSE2 is used unless explicitly disabled by checking
AV_CPU_FLAG_SSE2SLOW. */
if vendorID() != Intel &&
if vend != Intel &&
rval&SSE2 != 0 && (c&0x00000040) == 0 {
rval |= SSE2SLOW
}
@@ -1135,7 +1340,7 @@ func support() Flags {
}
}
if vendorID() == Intel {
if vend == Intel {
family, model := familyModel()
if family == 6 && (model == 9 || model == 13 || model == 14) {
/* 6/9 (pentium-m "banias"), 6/13 (pentium-m "dothan"), and
@@ -1182,3 +1387,118 @@ func valAsString(values ...uint32) []byte {
}
return r
}
// Single-precision and double-precision floating point
func (c CPUInfo) ArmFP() bool {
return c.Arm&FP != 0
}
// Advanced SIMD
func (c CPUInfo) ArmASIMD() bool {
return c.Arm&ASIMD != 0
}
// Generic timer
func (c CPUInfo) ArmEVTSTRM() bool {
return c.Arm&EVTSTRM != 0
}
// AES instructions
func (c CPUInfo) ArmAES() bool {
return c.Arm&AES != 0
}
// Polynomial Multiply instructions (PMULL/PMULL2)
func (c CPUInfo) ArmPMULL() bool {
return c.Arm&PMULL != 0
}
// SHA-1 instructions (SHA1C, etc)
func (c CPUInfo) ArmSHA1() bool {
return c.Arm&SHA1 != 0
}
// SHA-2 instructions (SHA256H, etc)
func (c CPUInfo) ArmSHA2() bool {
return c.Arm&SHA2 != 0
}
// CRC32/CRC32C instructions
func (c CPUInfo) ArmCRC32() bool {
return c.Arm&CRC32 != 0
}
// Large System Extensions (LSE)
func (c CPUInfo) ArmATOMICS() bool {
return c.Arm&ATOMICS != 0
}
// Half-precision floating point
func (c CPUInfo) ArmFPHP() bool {
return c.Arm&FPHP != 0
}
// Advanced SIMD half-precision floating point
func (c CPUInfo) ArmASIMDHP() bool {
return c.Arm&ASIMDHP != 0
}
// Rounding Double Multiply Accumulate/Subtract (SQRDMLAH/SQRDMLSH)
func (c CPUInfo) ArmASIMDRDM() bool {
return c.Arm&ASIMDRDM != 0
}
// Javascript-style double->int convert (FJCVTZS)
func (c CPUInfo) ArmJSCVT() bool {
return c.Arm&JSCVT != 0
}
// Floatin point complex number addition and multiplication
func (c CPUInfo) ArmFCMA() bool {
return c.Arm&FCMA != 0
}
// Weaker release consistency (LDAPR, etc)
func (c CPUInfo) ArmLRCPC() bool {
return c.Arm&LRCPC != 0
}
// Data cache clean to Point of Persistence (DC CVAP)
func (c CPUInfo) ArmDCPOP() bool {
return c.Arm&DCPOP != 0
}
// SHA-3 instructions (EOR3, RAXI, XAR, BCAX)
func (c CPUInfo) ArmSHA3() bool {
return c.Arm&SHA3 != 0
}
// SM3 instructions
func (c CPUInfo) ArmSM3() bool {
return c.Arm&SM3 != 0
}
// SM4 instructions
func (c CPUInfo) ArmSM4() bool {
return c.Arm&SM4 != 0
}
// SIMD Dot Product
func (c CPUInfo) ArmASIMDDP() bool {
return c.Arm&ASIMDDP != 0
}
// SHA512 instructions
func (c CPUInfo) ArmSHA512() bool {
return c.Arm&SHA512 != 0
}
// Scalable Vector Extension
func (c CPUInfo) ArmSVE() bool {
return c.Arm&SVE != 0
}
// Generic Pointer Authentication
func (c CPUInfo) ArmGPA() bool {
return c.Arm&GPA != 0
}
+1 -1
View File
@@ -1,6 +1,6 @@
// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file.
// +build 386,!gccgo
//+build 386,!gccgo,!noasm,!appengine
// func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32)
TEXT ·asmCpuid(SB), 7, $0
+1 -1
View File
@@ -1,6 +1,6 @@
// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file.
//+build amd64,!gccgo
//+build amd64,!gccgo,!noasm,!appengine
// func asmCpuid(op uint32) (eax, ebx, ecx, edx uint32)
TEXT ·asmCpuid(SB), 7, $0
+17 -1
View File
@@ -1,6 +1,6 @@
// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file.
// +build 386,!gccgo amd64,!gccgo
//+build 386,!gccgo,!noasm amd64,!gccgo,!noasm,!appengine
package cpuid
@@ -15,3 +15,19 @@ func initCPU() {
xgetbv = asmXgetbv
rdtscpAsm = asmRdtscpAsm
}
func addInfo(c *CPUInfo) {
c.maxFunc = maxFunctionID()
c.maxExFunc = maxExtendedFunction()
c.BrandName = brandName()
c.CacheLine = cacheLine()
c.Family, c.Model = familyModel()
c.Features = support()
c.SGX = hasSGX(c.Features&SGX != 0, c.Features&SGXLC != 0)
c.ThreadsPerCore = threadsPerCore()
c.LogicalCores = logicalCores()
c.PhysicalCores = physicalCores()
c.VendorID, c.VendorString = vendorID()
c.Hz = hertz(c.BrandName)
c.cacheSize()
}
+7 -16
View File
@@ -1,23 +1,14 @@
// Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file.
// +build !amd64,!386 gccgo
//+build !amd64,!386,!arm64 gccgo noasm appengine
package cpuid
func initCPU() {
cpuid = func(op uint32) (eax, ebx, ecx, edx uint32) {
return 0, 0, 0, 0
}
cpuidex = func(op, op2 uint32) (eax, ebx, ecx, edx uint32) {
return 0, 0, 0, 0
}
xgetbv = func(index uint32) (eax, edx uint32) {
return 0, 0
}
rdtscpAsm = func() (eax, ebx, ecx, edx uint32) {
return 0, 0, 0, 0
}
cpuid = func(uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 }
cpuidex = func(x, y uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 }
xgetbv = func(uint32) (a, b uint32) { return 0, 0 }
rdtscpAsm = func() (a, b, c, d uint32) { return 0, 0, 0, 0 }
}
func addInfo(info *CPUInfo) {}
-4
View File
@@ -1,4 +0,0 @@
package cpuid
//go:generate go run private-gen.go
//go:generate gofmt -w ./private
+55 -10
View File
@@ -1,32 +1,77 @@
language: go
sudo: false
os:
- linux
- osx
- osx
- windows
arch:
- amd64
- arm64
- ppc64le
- s390x
go:
- 1.11.x
- 1.12.x
- 1.13.x
- 1.14.x
- master
install:
- go get ./...
script:
script:
- go vet ./...
- go test -v -cpu=1,2,4 .
- go test -v -cpu=1,2,4 -short -race .
- go test -tags=noasm -v -cpu=1,2,4 -short -race .
- go test -cpu=1,2 .
- go test -tags=noasm -cpu=1,2 .
- go build examples/simple-decoder.go
- go build examples/simple-encoder.go
- go build examples/stream-decoder.go
- go build examples/stream-encoder.go
- diff <(gofmt -d .) <("")
matrix:
stages:
- gofmt
- test
- deploy
jobs:
allow_failures:
- go: 'master'
- arch: s390x
fast_finish: true
include:
- stage: gofmt
go: 1.14.x
os: linux
arch: amd64
script:
- diff <(gofmt -d .) <(printf "")
- diff <(gofmt -d ./examples) <(printf "")
- go install github.com/klauspost/asmfmt/cmd/asmfmt
- diff <(asmfmt -d .) <(printf "")
- stage: race
go: 1.14.x
os: linux
arch: amd64
script:
- go test -cpu=1 -short -race .
- go test -cpu=2 -short -race .
- go test -tags=noasm -cpu=1 -short -race .
- go test -tags=noasm -cpu=4 -short -race .
- go test -no-avx512 -short -race .
- go test -no-avx512 -no-avx2 -short -race .
- go test -no-avx512 -no-avx2 -no-ssse3 -short -race .
- stage: amd64-noasm
go: 1.14.x
os: linux
arch: amd64
script:
- go test -no-avx512
- go test -no-avx512 -no-avx2
- go test -no-avx512 -no-avx2 -no-ssse3
- stage: i386
go: 1.14.x
os: linux
arch: amd64
script:
- GOOS=linux GOARCH=386 go test -short .
+133 -59
View File
@@ -2,19 +2,20 @@
[![GoDoc][1]][2] [![Build Status][3]][4]
[1]: https://godoc.org/github.com/klauspost/reedsolomon?status.svg
[2]: https://godoc.org/github.com/klauspost/reedsolomon
[2]: https://pkg.go.dev/github.com/klauspost/reedsolomon?tab=doc
[3]: https://travis-ci.org/klauspost/reedsolomon.svg?branch=master
[4]: https://travis-ci.org/klauspost/reedsolomon
Reed-Solomon Erasure Coding in Go, with speeds exceeding 1GB/s/cpu core implemented in pure Go.
This is a Go port of the [JavaReedSolomon](https://github.com/Backblaze/JavaReedSolomon) library released by [Backblaze](http://backblaze.com), with some additional optimizations.
This is a Go port of the [JavaReedSolomon](https://github.com/Backblaze/JavaReedSolomon) library released by
[Backblaze](http://backblaze.com), with some additional optimizations.
For an introduction on erasure coding, see the post on the [Backblaze blog](https://www.backblaze.com/blog/reed-solomon/).
Package home: https://github.com/klauspost/reedsolomon
Godoc: https://godoc.org/github.com/klauspost/reedsolomon
Godoc: https://pkg.go.dev/github.com/klauspost/reedsolomon?tab=doc
# Installation
To get the package use the standard:
@@ -24,13 +25,23 @@ go get -u github.com/klauspost/reedsolomon
# Changes
## May 2020
* ARM64 optimizations, up to 2.5x faster.
* Added [WithFastOneParityMatrix](https://pkg.go.dev/github.com/klauspost/reedsolomon?tab=doc#WithFastOneParityMatrix) for faster operation with 1 parity shard.
* Much better performance when using a limited number of goroutines.
* AVX512 is now using multiple cores.
* Stream processing overhaul, big speedups in most cases.
* AVX512 optimizations
## March 6, 2019
The pure Go implementation is about 30% faster. Minor tweaks to assembler implementations.
## February 8, 2019
AVX512 accelerated version added for Intel Skylake CPUs. This can give up to a 4x speed improvement as compared to AVX2. See [here](https://github.com/klauspost/reedsolomon#performance-on-avx512) for more details.
AVX512 accelerated version added for Intel Skylake CPUs. This can give up to a 4x speed improvement as compared to AVX2.
See [here](https://github.com/klauspost/reedsolomon#performance-on-avx512) for more details.
## December 18, 2018
@@ -38,49 +49,78 @@ Assembly code for ppc64le has been contributed, this boosts performance by about
## November 18, 2017
Added [WithAutoGoroutines](https://godoc.org/github.com/klauspost/reedsolomon#WithAutoGoroutines) which will attempt to calculate the optimal number of goroutines to use based on your expected shard size and detected CPU.
Added [WithAutoGoroutines](https://godoc.org/github.com/klauspost/reedsolomon#WithAutoGoroutines) which will attempt
to calculate the optimal number of goroutines to use based on your expected shard size and detected CPU.
## October 1, 2017
* [Cauchy Matrix](https://godoc.org/github.com/klauspost/reedsolomon#WithCauchyMatrix) is now an option. Thanks to [templexxx](https://github.com/templexxx) for the basis of this.
* Default maximum number of [goroutines](https://godoc.org/github.com/klauspost/reedsolomon#WithMaxGoroutines) has been increased for better multi-core scaling.
* After several requests the Reconstruct and ReconstructData now slices of zero length but sufficient capacity to be used instead of allocating new memory.
* [Cauchy Matrix](https://godoc.org/github.com/klauspost/reedsolomon#WithCauchyMatrix) is now an option.
Thanks to [templexxx](https://github.com/templexxx) for the basis of this.
* Default maximum number of [goroutines](https://godoc.org/github.com/klauspost/reedsolomon#WithMaxGoroutines)
has been increased for better multi-core scaling.
* After several requests the Reconstruct and ReconstructData now slices of zero length but sufficient capacity to
be used instead of allocating new memory.
## August 26, 2017
* The [`Encoder()`](https://godoc.org/github.com/klauspost/reedsolomon#Encoder) now contains an `Update` function contributed by [chenzhongtao](https://github.com/chenzhongtao).
* [Frank Wessels](https://github.com/fwessels) kindly contributed ARM 64 bit assembly, which gives a huge performance boost on this platform.
* The [`Encoder()`](https://godoc.org/github.com/klauspost/reedsolomon#Encoder) now contains an `Update`
function contributed by [chenzhongtao](https://github.com/chenzhongtao).
* [Frank Wessels](https://github.com/fwessels) kindly contributed ARM 64 bit assembly,
which gives a huge performance boost on this platform.
## July 20, 2017
`ReconstructData` added to [`Encoder`](https://godoc.org/github.com/klauspost/reedsolomon#Encoder) interface. This can cause compatibility issues if you implement your own Encoder. A simple workaround can be added:
`ReconstructData` added to [`Encoder`](https://godoc.org/github.com/klauspost/reedsolomon#Encoder) interface.
This can cause compatibility issues if you implement your own Encoder. A simple workaround can be added:
```Go
func (e *YourEnc) ReconstructData(shards [][]byte) error {
return ReconstructData(shards)
}
```
You can of course also do your own implementation. The [`StreamEncoder`](https://godoc.org/github.com/klauspost/reedsolomon#StreamEncoder) handles this without modifying the interface. This is a good lesson on why returning interfaces is not a good design.
You can of course also do your own implementation.
The [`StreamEncoder`](https://godoc.org/github.com/klauspost/reedsolomon#StreamEncoder)
handles this without modifying the interface.
This is a good lesson on why returning interfaces is not a good design.
# Usage
This section assumes you know the basics of Reed-Solomon encoding. A good start is this [Backblaze blog post](https://www.backblaze.com/blog/reed-solomon/).
This section assumes you know the basics of Reed-Solomon encoding.
A good start is this [Backblaze blog post](https://www.backblaze.com/blog/reed-solomon/).
This package performs the calculation of the parity sets. The usage is therefore relatively simple.
First of all, you need to choose your distribution of data and parity shards. A 'good' distribution is very subjective, and will depend a lot on your usage scenario. A good starting point is above 5 and below 257 data shards (the maximum supported number), and the number of parity shards to be 2 or above, and below the number of data shards.
First of all, you need to choose your distribution of data and parity shards.
A 'good' distribution is very subjective, and will depend a lot on your usage scenario.
A good starting point is above 5 and below 257 data shards (the maximum supported number),
and the number of parity shards to be 2 or above, and below the number of data shards.
To create an encoder with 10 data shards (where your data goes) and 3 parity shards (calculated):
```Go
enc, err := reedsolomon.New(10, 3)
```
This encoder will work for all parity sets with this distribution of data and parity shards. The error will only be set if you specify 0 or negative values in any of the parameters, or if you specify more than 256 data shards.
This encoder will work for all parity sets with this distribution of data and parity shards.
The error will only be set if you specify 0 or negative values in any of the parameters,
or if you specify more than 256 data shards.
If you will primarily be using it with one shard size it is recommended to use
[`WithAutoGoroutines(shardSize)`](https://pkg.go.dev/github.com/klauspost/reedsolomon?tab=doc#WithAutoGoroutines)
as an additional parameter. This will attempt to calculate the optimal number of goroutines to use for the best speed.
It is not required that all shards are this size.
The you send and receive data is a simple slice of byte slices; `[][]byte`.
In the example above, the top slice must have a length of 13.
The you send and receive data is a simple slice of byte slices; `[][]byte`. In the example above, the top slice must have a length of 13.
```Go
data := make([][]byte, 13)
```
You should then fill the 10 first slices with *equally sized* data, and create parity shards that will be populated with parity data. In this case we create the data in memory, but you could for instance also use [mmap](https://github.com/edsrzf/mmap-go) to map files.
You should then fill the 10 first slices with *equally sized* data,
and create parity shards that will be populated with parity data. In this case we create the data in memory,
but you could for instance also use [mmap](https://github.com/edsrzf/mmap-go) to map files.
```Go
// Create all shards, size them at 50000 each
@@ -101,13 +141,19 @@ To populate the parity shards, you simply call `Encode()` with your data.
```Go
err = enc.Encode(data)
```
The only cases where you should get an error is, if the data shards aren't of equal size. The last 3 shards now contain parity data. You can verify this by calling `Verify()`:
The only cases where you should get an error is, if the data shards aren't of equal size.
The last 3 shards now contain parity data. You can verify this by calling `Verify()`:
```Go
ok, err = enc.Verify(data)
```
The final (and important) part is to be able to reconstruct missing shards. For this to work, you need to know which parts of your data is missing. The encoder *does not know which parts are invalid*, so if data corruption is a likely scenario, you need to implement a hash check for each shard. If a byte has changed in your set, and you don't know which it is, there is no way to reconstruct the data set.
The final (and important) part is to be able to reconstruct missing shards.
For this to work, you need to know which parts of your data is missing.
The encoder *does not know which parts are invalid*, so if data corruption is a likely scenario,
you need to implement a hash check for each shard.
If a byte has changed in your set, and you don't know which it is, there is no way to reconstruct the data set.
To indicate missing data, you set the shard to nil before calling `Reconstruct()`:
@@ -138,11 +184,13 @@ So to sum up reconstruction:
* You may only supply data you know is valid.
* Invalid shards should be set to nil.
For complete examples of an encoder and decoder see the [examples folder](https://github.com/klauspost/reedsolomon/tree/master/examples).
For complete examples of an encoder and decoder see the
[examples folder](https://github.com/klauspost/reedsolomon/tree/master/examples).
# Splitting/Joining Data
You might have a large slice of data. To help you split this, there are some helper functions that can split and join a single byte slice.
You might have a large slice of data.
To help you split this, there are some helper functions that can split and join a single byte slice.
```Go
bigfile, _ := ioutil.Readfile("myfile.data")
@@ -152,7 +200,8 @@ You might have a large slice of data. To help you split this, there are some hel
```
This will split the file into the number of data shards set when creating the encoder and create empty parity shards.
An important thing to note is that you have to *keep track of the exact input size*. If the size of the input isn't divisible by the number of data shards, extra zeros will be inserted in the last shard.
An important thing to note is that you have to *keep track of the exact input size*.
If the size of the input isn't divisible by the number of data shards, extra zeros will be inserted in the last shard.
To join a data set, use the `Join()` function, which will join the shards and write it to the `io.Writer` you supply:
```Go
@@ -162,7 +211,9 @@ To join a data set, use the `Join()` function, which will join the shards and wr
# Streaming/Merging
It might seem like a limitation that all data should be in memory, but an important property is that *as long as the number of data/parity shards are the same, you can merge/split data sets*, and they will remain valid as a separate set.
It might seem like a limitation that all data should be in memory,
but an important property is that *as long as the number of data/parity shards are the same,
you can merge/split data sets*, and they will remain valid as a separate set.
```Go
// Split the data set of 50000 elements into two of 25000
@@ -198,26 +249,44 @@ It might seem like a limitation that all data should be in memory, but an import
}
```
This means that if you have a data set that may not fit into memory, you can split processing into smaller blocks. For the best throughput, don't use too small blocks.
This means that if you have a data set that may not fit into memory, you can split processing into smaller blocks.
For the best throughput, don't use too small blocks.
This also means that you can divide big input up into smaller blocks, and do reconstruction on parts of your data. This doesn't give the same flexibility of a higher number of data shards, but it will be much more performant.
This also means that you can divide big input up into smaller blocks, and do reconstruction on parts of your data.
This doesn't give the same flexibility of a higher number of data shards, but it will be much more performant.
# Streaming API
There has been added support for a streaming API, to help perform fully streaming operations, which enables you to do the same operations, but on streams. To use the stream API, use [`NewStream`](https://godoc.org/github.com/klauspost/reedsolomon#NewStream) function to create the encoding/decoding interfaces. You can use [`NewStreamC`](https://godoc.org/github.com/klauspost/reedsolomon#NewStreamC) to ready an interface that reads/writes concurrently from the streams.
There has been added support for a streaming API, to help perform fully streaming operations,
which enables you to do the same operations, but on streams.
To use the stream API, use [`NewStream`](https://godoc.org/github.com/klauspost/reedsolomon#NewStream) function
to create the encoding/decoding interfaces.
Input is delivered as `[]io.Reader`, output as `[]io.Writer`, and functionality corresponds to the in-memory API. Each stream must supply the same amount of data, similar to how each slice must be similar size with the in-memory API.
If an error occurs in relation to a stream, a [`StreamReadError`](https://godoc.org/github.com/klauspost/reedsolomon#StreamReadError) or [`StreamWriteError`](https://godoc.org/github.com/klauspost/reedsolomon#StreamWriteError) will help you determine which stream was the offender.
You can use [`WithConcurrentStreams`](https://godoc.org/github.com/klauspost/reedsolomon#WithConcurrentStreams)
to ready an interface that reads/writes concurrently from the streams.
You can specify the size of each operation using
[`WithStreamBlockSize`](https://godoc.org/github.com/klauspost/reedsolomon#WithStreamBlockSize).
This will set the size of each read/write operation.
Input is delivered as `[]io.Reader`, output as `[]io.Writer`, and functionality corresponds to the in-memory API.
Each stream must supply the same amount of data, similar to how each slice must be similar size with the in-memory API.
If an error occurs in relation to a stream,
a [`StreamReadError`](https://godoc.org/github.com/klauspost/reedsolomon#StreamReadError)
or [`StreamWriteError`](https://godoc.org/github.com/klauspost/reedsolomon#StreamWriteError)
will help you determine which stream was the offender.
There is no buffering or timeouts/retry specified. If you want to add that, you need to add it to the Reader/Writer.
For complete examples of a streaming encoder and decoder see the [examples folder](https://github.com/klauspost/reedsolomon/tree/master/examples).
For complete examples of a streaming encoder and decoder see the
[examples folder](https://github.com/klauspost/reedsolomon/tree/master/examples).
# Advanced Options
You can modify internal options which affects how jobs are split between and processed by goroutines.
To create options, use the WithXXX functions. You can supply options to `New`, `NewStream` and `NewStreamC`. If no Options are supplied, default options are used.
To create options, use the WithXXX functions. You can supply options to `New`, `NewStream`.
If no Options are supplied, default options are used.
Example of how to supply options:
@@ -227,9 +296,11 @@ Example of how to supply options:
# Performance
Performance depends mainly on the number of parity shards. In rough terms, doubling the number of parity shards will double the encoding time.
Performance depends mainly on the number of parity shards.
In rough terms, doubling the number of parity shards will double the encoding time.
Here are the throughput numbers with some different selections of data and parity shards. For reference each shard is 1MB random data, and 2 CPU cores are used for encoding.
Here are the throughput numbers with some different selections of data and parity shards.
For reference each shard is 1MB random data, and 2 CPU cores are used for encoding.
| Data | Parity | Parity | MB/s | SSSE3 MB/s | SSSE3 Speed | Rel. Speed |
|------|--------|--------|--------|-------------|-------------|------------|
@@ -238,16 +309,20 @@ Here are the throughput numbers with some different selections of data and parit
| 10 | 4 | 40% | 298,38 | 2470,97 | 828% | 51,79% |
| 50 | 20 | 40% | 59,81 | 713,28 | 1193% | 10,38% |
If `runtime.GOMAXPROCS()` is set to a value higher than 1, the encoder will use multiple goroutines to perform the calculations in `Verify`, `Encode` and `Reconstruct`.
If `runtime.GOMAXPROCS()` is set to a value higher than 1,
the encoder will use multiple goroutines to perform the calculations in `Verify`, `Encode` and `Reconstruct`.
Example of performance scaling on Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz - 4 physical cores, 8 logical cores. The example uses 10 blocks with 16MB data each and 4 parity blocks.
Example of performance scaling on AMD Ryzen 3950X - 16 physical cores, 32 logical cores, AVX 2.
The example uses 10 blocks with 1MB data each and 4 parity blocks.
| Threads | Speed |
|---------|------------|
| 1 | 9979 MB/s |
| 2 | 18870 MB/s |
| 4 | 33697 MB/s |
| 8 | 51531 MB/s |
| 16 | 59204 MB/s |
| Threads | MB/s | Speed |
|---------|---------|-------|
| 1 | 1355,11 | 100% |
| 2 | 2339,78 | 172% |
| 4 | 3179,33 | 235% |
| 8 | 4346,18 | 321% |
Benchmarking `Reconstruct()` followed by a `Verify()` (=`all`) versus just calling `ReconstructData()` (=`data`) gives the following result:
```
@@ -263,36 +338,35 @@ BenchmarkReconstruct10x4x16M-8 1484.35 5779.53 3.89x
# Performance on AVX512
The performance on AVX512 has been accelerated for Intel CPUs. This gives speedups on a per-core basis of up to 4x compared to AVX2 as can be seen in the following table:
The performance on AVX512 has been accelerated for Intel CPUs.
This gives speedups on a per-core basis typically up to 2x compared to
AVX2 as can be seen in the following table:
```
$ benchcmp avx2.txt avx512.txt
benchmark AVX2 MB/s AVX512 MB/s speedup
BenchmarkEncode8x8x1M-72 1681.35 4125.64 2.45x
BenchmarkEncode8x4x8M-72 1529.36 5507.97 3.60x
BenchmarkEncode8x8x8M-72 791.16 2952.29 3.73x
BenchmarkEncode8x8x32M-72 573.26 2168.61 3.78x
BenchmarkEncode12x4x12M-72 1234.41 4912.37 3.98x
BenchmarkEncode16x4x16M-72 1189.59 5138.01 4.32x
BenchmarkEncode24x8x24M-72 690.68 2583.70 3.74x
BenchmarkEncode24x8x48M-72 674.20 2643.31 3.92x
[...]
```
This speedup has been achieved by computing multiple parity blocks in parallel as opposed to one after the other. In doing so it is possible to minimize the memory bandwidth required for loading all data shards. At the same time the calculations are performed in the 512-bit wide ZMM registers and the surplus of ZMM registers (32 in total) is used to keep more data around (most notably the matrix coefficients).
This speedup has been achieved by computing multiple parity blocks in parallel as opposed to one after the other.
In doing so it is possible to minimize the memory bandwidth required for loading all data shards.
At the same time the calculations are performed in the 512-bit wide ZMM registers and the surplus of ZMM
registers (32 in total) is used to keep more data around (most notably the matrix coefficients).
# Performance on ARM64 NEON
By exploiting NEON instructions the performance for ARM has been accelerated. Below are the performance numbers for a single core on an ARM Cortex-A53 CPU @ 1.2GHz (Debian 8.0 Jessie running Go: 1.7.4):
By exploiting NEON instructions the performance for ARM has been accelerated.
Below are the performance numbers for a single core on an EC2 m6g.16xlarge (Graviton2) instance (Amazon Linux 2):
| Data | Parity | Parity | ARM64 Go MB/s | ARM64 NEON MB/s | NEON Speed |
|------|--------|--------|--------------:|----------------:|-----------:|
| 5 | 2 | 40% | 189 | 1304 | 588% |
| 10 | 2 | 20% | 188 | 1738 | 925% |
| 10 | 4 | 40% | 96 | 839 | 877% |
```
BenchmarkGalois128K-64 119562 10028 ns/op 13070.78 MB/s
BenchmarkGalois1M-64 14380 83424 ns/op 12569.22 MB/s
BenchmarkGaloisXor128K-64 96508 12432 ns/op 10543.29 MB/s
BenchmarkGaloisXor1M-64 10000 100322 ns/op 10452.13 MB/s
```
# Performance on ppc64le
The performance for ppc64le has been accelerated. This gives roughly a 10x performance improvement on this architecture as can been seen below:
The performance for ppc64le has been accelerated.
This gives roughly a 10x performance improvement on this architecture as can been seen below:
```
benchmark old MB/s new MB/s speedup
+27 -3
View File
@@ -852,9 +852,6 @@ func galMultiply(a, b byte) byte {
return mulTable[a][b]
}
// amd64 indicates whether we are on an amd64 platform.
var amd64 bool
// Original function:
/*
// galMultiply multiplies to elements of the field.
@@ -903,3 +900,30 @@ func galExp(a byte, n int) byte {
}
return expTable[logResult]
}
func genAvx2Matrix(matrixRows [][]byte, inputs, outputs int, dst []byte) []byte {
if !avx2CodeGen {
panic("codegen not enabled")
}
total := inputs * outputs
// Duplicated in+out
wantBytes := total * 32 * 2
if cap(dst) < wantBytes {
dst = make([]byte, wantBytes)
} else {
dst = dst[:wantBytes]
}
for i, row := range matrixRows[:outputs] {
for j, idx := range row[:inputs] {
dstIdx := (j*outputs + i) * 64
lo := mulTableLow[idx][:]
hi := mulTableHigh[idx][:]
copy(dst[dstIdx:], lo)
copy(dst[dstIdx+16:], lo)
copy(dst[dstIdx+32:], hi)
copy(dst[dstIdx+48:], hi)
}
}
return dst
}
+216 -66
View File
@@ -7,25 +7,54 @@
package reedsolomon
import (
"sync"
)
//go:noescape
func _galMulAVX512Parallel81(in, out [][]byte, matrix *[matrixSize81]byte, addTo bool)
//go:noescape
func _galMulAVX512Parallel82(in, out [][]byte, matrix *[matrixSize82]byte, addTo bool)
//go:noescape
func _galMulAVX512Parallel84(in, out [][]byte, matrix *[matrixSize84]byte, addTo bool)
func init() {
amd64 = true
}
const (
dimIn = 8 // Number of input rows processed simultaneously
dimOut81 = 1 // Number of output rows processed simultaneously for x1 routine
dimOut82 = 2 // Number of output rows processed simultaneously for x2 routine
dimOut84 = 4 // Number of output rows processed simultaneously for x4 routine
matrixSize81 = (16 + 16) * dimIn * dimOut81 // Dimension of slice of matrix coefficient passed into x1 routine
matrixSize82 = (16 + 16) * dimIn * dimOut82 // Dimension of slice of matrix coefficient passed into x2 routine
matrixSize84 = (16 + 16) * dimIn * dimOut84 // Dimension of slice of matrix coefficient passed into x4 routine
)
// Construct block of matrix coefficients for 2 outputs rows in parallel
// Construct block of matrix coefficients for single output row in parallel
func setupMatrix81(matrixRows [][]byte, inputOffset, outputOffset int, matrix *[matrixSize81]byte) {
offset := 0
for c := inputOffset; c < inputOffset+dimIn; c++ {
for iRow := outputOffset; iRow < outputOffset+dimOut81; iRow++ {
if c < len(matrixRows[iRow]) {
coeff := matrixRows[iRow][c]
copy(matrix[offset*32:], mulTableLow[coeff][:])
copy(matrix[offset*32+16:], mulTableHigh[coeff][:])
} else {
// coefficients not used for this input shard (so null out)
v := matrix[offset*32 : offset*32+32]
for i := range v {
v[i] = 0
}
}
offset += dimIn
if offset >= dimIn*dimOut81 {
offset -= dimIn*dimOut81 - 1
}
}
}
}
// Construct block of matrix coefficients for 2 output rows in parallel
func setupMatrix82(matrixRows [][]byte, inputOffset, outputOffset int, matrix *[matrixSize82]byte) {
offset := 0
for c := inputOffset; c < inputOffset+dimIn; c++ {
@@ -49,7 +78,7 @@ func setupMatrix82(matrixRows [][]byte, inputOffset, outputOffset int, matrix *[
}
}
// Construct block of matrix coefficients for 4 outputs rows in parallel
// Construct block of matrix coefficients for 4 output rows in parallel
func setupMatrix84(matrixRows [][]byte, inputOffset, outputOffset int, matrix *[matrixSize84]byte) {
offset := 0
for c := inputOffset; c < inputOffset+dimIn; c++ {
@@ -73,10 +102,45 @@ func setupMatrix84(matrixRows [][]byte, inputOffset, outputOffset int, matrix *[
}
}
// Invoke AVX512 routine for single output row in parallel
func galMulAVX512Parallel81(in, out [][]byte, matrixRows [][]byte, inputOffset, outputOffset, start, stop int, matrix81 *[matrixSize81]byte) {
done := stop - start
if done <= 0 {
return
}
inputEnd := inputOffset + dimIn
if inputEnd > len(in) {
inputEnd = len(in)
}
outputEnd := outputOffset + dimOut81
if outputEnd > len(out) {
outputEnd = len(out)
}
// We know the max size, alloc temp array.
var inTmp [dimIn][]byte
for i, v := range in[inputOffset:inputEnd] {
inTmp[i] = v[start:stop]
}
var outTmp [dimOut81][]byte
for i, v := range out[outputOffset:outputEnd] {
outTmp[i] = v[start:stop]
}
addTo := inputOffset != 0 // Except for the first input column, add to previous results
_galMulAVX512Parallel81(inTmp[:inputEnd-inputOffset], outTmp[:outputEnd-outputOffset], matrix81, addTo)
done = start + ((done >> 6) << 6)
if done < stop {
galMulAVX512LastInput(inputOffset, inputEnd, outputOffset, outputEnd, matrixRows, done, stop, out, in)
}
}
// Invoke AVX512 routine for 2 output rows in parallel
func galMulAVX512Parallel82(in, out [][]byte, matrixRows [][]byte, inputOffset, outputOffset int) {
done := len(in[0])
if done == 0 {
func galMulAVX512Parallel82(in, out [][]byte, matrixRows [][]byte, inputOffset, outputOffset, start, stop int, matrix82 *[matrixSize82]byte) {
done := stop - start
if done <= 0 {
return
}
@@ -89,36 +153,29 @@ func galMulAVX512Parallel82(in, out [][]byte, matrixRows [][]byte, inputOffset,
outputEnd = len(out)
}
matrix82 := [matrixSize82]byte{}
setupMatrix82(matrixRows, inputOffset, outputOffset, &matrix82)
addTo := inputOffset != 0 // Except for the first input column, add to previous results
_galMulAVX512Parallel82(in[inputOffset:inputEnd], out[outputOffset:outputEnd], &matrix82, addTo)
done = (done >> 6) << 6
if len(in[0])-done == 0 {
return
// We know the max size, alloc temp array.
var inTmp [dimIn][]byte
for i, v := range in[inputOffset:inputEnd] {
inTmp[i] = v[start:stop]
}
var outTmp [dimOut82][]byte
for i, v := range out[outputOffset:outputEnd] {
outTmp[i] = v[start:stop]
}
for c := inputOffset; c < inputOffset+dimIn; c++ {
for iRow := outputOffset; iRow < outputOffset+dimOut82; iRow++ {
if c < len(matrixRows[iRow]) {
mt := mulTable[matrixRows[iRow][c]][:256]
for i := done; i < len(in[0]); i++ {
if c == 0 { // only set value for first input column
out[iRow][i] = mt[in[c][i]]
} else { // and add for all others
out[iRow][i] ^= mt[in[c][i]]
}
}
}
}
addTo := inputOffset != 0 // Except for the first input column, add to previous results
_galMulAVX512Parallel82(inTmp[:inputEnd-inputOffset], outTmp[:outputEnd-outputOffset], matrix82, addTo)
done = start + ((done >> 6) << 6)
if done < stop {
galMulAVX512LastInput(inputOffset, inputEnd, outputOffset, outputEnd, matrixRows, done, stop, out, in)
}
}
// Invoke AVX512 routine for 4 output rows in parallel
func galMulAVX512Parallel84(in, out [][]byte, matrixRows [][]byte, inputOffset, outputOffset int) {
done := len(in[0])
if done == 0 {
func galMulAVX512Parallel84(in, out [][]byte, matrixRows [][]byte, inputOffset, outputOffset, start, stop int, matrix84 *[matrixSize84]byte) {
done := stop - start
if done <= 0 {
return
}
@@ -131,21 +188,31 @@ func galMulAVX512Parallel84(in, out [][]byte, matrixRows [][]byte, inputOffset,
outputEnd = len(out)
}
matrix84 := [matrixSize84]byte{}
setupMatrix84(matrixRows, inputOffset, outputOffset, &matrix84)
addTo := inputOffset != 0 // Except for the first input column, add to previous results
_galMulAVX512Parallel84(in[inputOffset:inputEnd], out[outputOffset:outputEnd], &matrix84, addTo)
done = (done >> 6) << 6
if len(in[0])-done == 0 {
return
// We know the max size, alloc temp array.
var inTmp [dimIn][]byte
for i, v := range in[inputOffset:inputEnd] {
inTmp[i] = v[start:stop]
}
var outTmp [dimOut84][]byte
for i, v := range out[outputOffset:outputEnd] {
outTmp[i] = v[start:stop]
}
for c := inputOffset; c < inputOffset+dimIn; c++ {
for iRow := outputOffset; iRow < outputOffset+dimOut84; iRow++ {
addTo := inputOffset != 0 // Except for the first input column, add to previous results
_galMulAVX512Parallel84(inTmp[:inputEnd-inputOffset], outTmp[:outputEnd-outputOffset], matrix84, addTo)
done = start + ((done >> 6) << 6)
if done < stop {
galMulAVX512LastInput(inputOffset, inputEnd, outputOffset, outputEnd, matrixRows, done, stop, out, in)
}
}
func galMulAVX512LastInput(inputOffset int, inputEnd int, outputOffset int, outputEnd int, matrixRows [][]byte, done int, stop int, out [][]byte, in [][]byte) {
for c := inputOffset; c < inputEnd; c++ {
for iRow := outputOffset; iRow < outputEnd; iRow++ {
if c < len(matrixRows[iRow]) {
mt := mulTable[matrixRows[iRow][c]][:256]
for i := done; i < len(in[0]); i++ {
for i := done; i < stop; i++ {
if c == 0 { // only set value for first input column
out[iRow][i] = mt[in[c][i]]
} else { // and add for all others
@@ -159,30 +226,113 @@ func galMulAVX512Parallel84(in, out [][]byte, matrixRows [][]byte, inputOffset,
// Perform the same as codeSomeShards, but taking advantage of
// AVX512 parallelism for up to 4x faster execution as compared to AVX2
func (r reedSolomon) codeSomeShardsAvx512(matrixRows, inputs, outputs [][]byte, outputCount, byteCount int) {
outputRow := 0
// First process (multiple) batches of 4 output rows in parallel
for ; outputRow+dimOut84 <= len(outputs); outputRow += dimOut84 {
for inputRow := 0; inputRow < len(inputs); inputRow += dimIn {
galMulAVX512Parallel84(inputs, outputs, matrixRows, inputRow, outputRow)
}
func (r *reedSolomon) codeSomeShardsAvx512(matrixRows, inputs, outputs [][]byte, outputCount, byteCount int) {
// Process using no goroutines
start, end := 0, r.o.perRound
if end > byteCount {
end = byteCount
}
// Then process a (single) batch of 2 output rows in parallel
if outputRow+dimOut82 <= len(outputs) {
// fmt.Println(outputRow, len(outputs))
for inputRow := 0; inputRow < len(inputs); inputRow += dimIn {
galMulAVX512Parallel82(inputs, outputs, matrixRows, inputRow, outputRow)
}
outputRow += dimOut82
}
// Lastly, we may have a single output row left (for uneven parity)
if outputRow < len(outputs) {
for c := 0; c < r.DataShards; c++ {
if c == 0 {
galMulSlice(matrixRows[outputRow][c], inputs[c], outputs[outputRow], &r.o)
} else {
galMulSliceXor(matrixRows[outputRow][c], inputs[c], outputs[outputRow], &r.o)
for start < byteCount {
matrix84 := [matrixSize84]byte{}
matrix82 := [matrixSize82]byte{}
matrix81 := [matrixSize81]byte{}
outputRow := 0
// First process (multiple) batches of 4 output rows in parallel
if outputRow+dimOut84 <= outputCount {
for ; outputRow+dimOut84 <= outputCount; outputRow += dimOut84 {
for inputRow := 0; inputRow < len(inputs); inputRow += dimIn {
setupMatrix84(matrixRows, inputRow, outputRow, &matrix84)
galMulAVX512Parallel84(inputs, outputs, matrixRows, inputRow, outputRow, start, end, &matrix84)
}
}
}
// Then process a (single) batch of 2 output rows in parallel
if outputRow+dimOut82 <= outputCount {
for inputRow := 0; inputRow < len(inputs); inputRow += dimIn {
setupMatrix82(matrixRows, inputRow, outputRow, &matrix82)
galMulAVX512Parallel82(inputs, outputs, matrixRows, inputRow, outputRow, start, end, &matrix82)
}
outputRow += dimOut82
}
// Lastly, we may have a single output row left (for uneven parity)
if outputRow < outputCount {
for inputRow := 0; inputRow < len(inputs); inputRow += dimIn {
setupMatrix81(matrixRows, inputRow, outputRow, &matrix81)
galMulAVX512Parallel81(inputs, outputs, matrixRows, inputRow, outputRow, start, end, &matrix81)
}
}
start = end
end += r.o.perRound
if end > byteCount {
end = byteCount
}
}
}
// Perform the same as codeSomeShards, but taking advantage of
// AVX512 parallelism for up to 4x faster execution as compared to AVX2
func (r *reedSolomon) codeSomeShardsAvx512P(matrixRows, inputs, outputs [][]byte, outputCount, byteCount int) {
var wg sync.WaitGroup
do := byteCount / r.o.maxGoroutines
if do < r.o.minSplitSize {
do = r.o.minSplitSize
}
// Make sizes divisible by 64
do = (do + 63) & (^63)
start := 0
for start < byteCount {
if start+do > byteCount {
do = byteCount - start
}
wg.Add(1)
go func(grStart, grStop int) {
start, stop := grStart, grStart+r.o.perRound
if stop > grStop {
stop = grStop
}
// Loop for each round.
matrix84 := [matrixSize84]byte{}
matrix82 := [matrixSize82]byte{}
matrix81 := [matrixSize81]byte{}
for start < grStop {
outputRow := 0
// First process (multiple) batches of 4 output rows in parallel
if outputRow+dimOut84 <= outputCount {
// 1K matrix buffer
for ; outputRow+dimOut84 <= outputCount; outputRow += dimOut84 {
for inputRow := 0; inputRow < len(inputs); inputRow += dimIn {
setupMatrix84(matrixRows, inputRow, outputRow, &matrix84)
galMulAVX512Parallel84(inputs, outputs, matrixRows, inputRow, outputRow, start, stop, &matrix84)
}
}
}
// Then process a (single) batch of 2 output rows in parallel
if outputRow+dimOut82 <= outputCount {
// 512B matrix buffer
for inputRow := 0; inputRow < len(inputs); inputRow += dimIn {
setupMatrix82(matrixRows, inputRow, outputRow, &matrix82)
galMulAVX512Parallel82(inputs, outputs, matrixRows, inputRow, outputRow, start, stop, &matrix82)
}
outputRow += dimOut82
}
// Lastly, we may have a single output row left (for uneven parity)
if outputRow < outputCount {
for inputRow := 0; inputRow < len(inputs); inputRow += dimIn {
setupMatrix81(matrixRows, inputRow, outputRow, &matrix81)
galMulAVX512Parallel81(inputs, outputs, matrixRows, inputRow, outputRow, start, stop, &matrix81)
}
}
start = stop
stop += r.o.perRound
if stop > grStop {
stop = grStop
}
}
wg.Done()
}(start, start+do)
start += do
}
wg.Wait()
}
+303 -493
View File
@@ -3,227 +3,255 @@
// Copyright 2015, Klaus Post, see LICENSE for details.
// Copyright 2019, Minio, Inc.
#define LOAD(OFFSET) \
MOVQ OFFSET(SI), BX \
VMOVDQU64 (BX)(R11*1), Z0 \
VPSRLQ $4, Z0, Z1 \ // high input
VPANDQ Z2, Z0, Z0 \ // low input
VPANDQ Z2, Z1, Z1 // high input
#define GALOIS_MUL(MUL_LO, MUL_HI, LO, HI, OUT) \
VPSHUFB Z0, MUL_LO, LO \ // mul low part
VPSHUFB Z1, MUL_HI, HI \ // mul high part
VPTERNLOGD $0x96, LO, HI, OUT
#define GALOIS(C1, C2, IN, LO, HI, OUT) \
VSHUFI64X2 $C1, IN, IN, LO \
VSHUFI64X2 $C2, IN, IN, HI \
GALOIS_MUL(LO, HI, LO, HI, OUT)
//
// Process single output row from a total of 8 input rows
//
// func _galMulAVX512Parallel81(in, out [][]byte, matrix *[matrixSize81]byte, addTo bool)
TEXT ·_galMulAVX512Parallel81(SB), 7, $0
MOVQ in+0(FP), SI
MOVQ 8(SI), R9 // R9: len(in)
SHRQ $6, R9 // len(in) / 64
TESTQ R9, R9
JZ done_avx512_parallel81
MOVQ matrix+48(FP), SI
VMOVDQU64 0x000(SI), Z16
VMOVDQU64 0x040(SI), Z17
VMOVDQU64 0x080(SI), Z18
VMOVDQU64 0x0c0(SI), Z19
// Initialize multiplication constants
VSHUFI64X2 $0x55, Z16, Z16, Z20
VSHUFI64X2 $0xaa, Z16, Z16, Z24
VSHUFI64X2 $0xff, Z16, Z16, Z28
VSHUFI64X2 $0x00, Z16, Z16, Z16
VSHUFI64X2 $0x55, Z17, Z17, Z21
VSHUFI64X2 $0xaa, Z17, Z17, Z25
VSHUFI64X2 $0xff, Z17, Z17, Z29
VSHUFI64X2 $0x00, Z17, Z17, Z17
VSHUFI64X2 $0x55, Z18, Z18, Z22
VSHUFI64X2 $0xaa, Z18, Z18, Z26
VSHUFI64X2 $0xff, Z18, Z18, Z30
VSHUFI64X2 $0x00, Z18, Z18, Z18
VSHUFI64X2 $0x55, Z19, Z19, Z23
VSHUFI64X2 $0xaa, Z19, Z19, Z27
VSHUFI64X2 $0xff, Z19, Z19, Z31
VSHUFI64X2 $0x00, Z19, Z19, Z19
MOVQ $15, BX
VPBROADCASTB BX, Z2
MOVB addTo+56(FP), AX
IMULQ $-0x1, AX
KMOVQ AX, K1
MOVQ in+0(FP), SI // SI: &in
MOVQ in_len+8(FP), AX // number of inputs
XORQ R11, R11
MOVQ out+24(FP), DX
MOVQ (DX), DX // DX: &out[0][0]
loopback_avx512_parallel81:
VMOVDQU64.Z (DX), K1, Z4
LOAD(0x00) // &in[0][0]
GALOIS_MUL(Z16, Z20, Z14, Z15, Z4)
CMPQ AX, $1
JE skip_avx512_parallel81
LOAD(0x18) // &in[1][0]
GALOIS_MUL(Z24, Z28, Z14, Z15, Z4)
CMPQ AX, $2
JE skip_avx512_parallel81
LOAD(0x30) // &in[2][0]
GALOIS_MUL(Z17, Z21, Z14, Z15, Z4)
CMPQ AX, $3
JE skip_avx512_parallel81
LOAD(0x48) // &in[3][0]
GALOIS_MUL(Z25, Z29, Z14, Z15, Z4)
CMPQ AX, $4
JE skip_avx512_parallel81
LOAD(0x60) // &in[4][0]
GALOIS_MUL(Z18, Z22, Z14, Z15, Z4)
CMPQ AX, $5
JE skip_avx512_parallel81
LOAD(0x78) // &in[5][0]
GALOIS_MUL(Z26, Z30, Z14, Z15, Z4)
CMPQ AX, $6
JE skip_avx512_parallel81
LOAD(0x90) // &in[6][0]
GALOIS_MUL(Z19, Z23, Z14, Z15, Z4)
CMPQ AX, $7
JE skip_avx512_parallel81
LOAD(0xa8) // &in[7][0]
GALOIS_MUL(Z27, Z31, Z14, Z15, Z4)
skip_avx512_parallel81:
VMOVDQU64 Z4, (DX)
ADDQ $64, R11 // in4+=64
ADDQ $64, DX // out+=64
SUBQ $1, R9
JNZ loopback_avx512_parallel81
done_avx512_parallel81:
VZEROUPPER
RET
//
// Process 2 output rows in parallel from a total of 8 input rows
//
// func _galMulAVX512Parallel82(in, out [][]byte, matrix *[matrixSize82]byte, addTo bool)
TEXT ·_galMulAVX512Parallel82(SB), 7, $0
MOVQ in+0(FP), SI //
MOVQ 8(SI), R9 // R9: len(in)
SHRQ $6, R9 // len(in) / 64
MOVQ in+0(FP), SI
MOVQ 8(SI), R9 // R9: len(in)
SHRQ $6, R9 // len(in) / 64
TESTQ R9, R9
JZ done_avx512_parallel82
MOVQ matrix+48(FP), SI
LONG $0x48fee162; WORD $0x066f // VMOVDQU64 ZMM16, 0x000[rsi]
LONG $0x48fee162; WORD $0x4e6f; BYTE $0x01 // VMOVDQU64 ZMM17, 0x040[rsi]
LONG $0x48fee162; WORD $0x566f; BYTE $0x02 // VMOVDQU64 ZMM18, 0x080[rsi]
LONG $0x48fee162; WORD $0x5e6f; BYTE $0x03 // VMOVDQU64 ZMM19, 0x0c0[rsi]
LONG $0x48fee162; WORD $0x666f; BYTE $0x04 // VMOVDQU64 ZMM20, 0x100[rsi]
LONG $0x48fee162; WORD $0x6e6f; BYTE $0x05 // VMOVDQU64 ZMM21, 0x140[rsi]
LONG $0x48fee162; WORD $0x766f; BYTE $0x06 // VMOVDQU64 ZMM22, 0x180[rsi]
LONG $0x48fee162; WORD $0x7e6f; BYTE $0x07 // VMOVDQU64 ZMM23, 0x1c0[rsi]
MOVQ matrix+48(FP), SI
VMOVDQU64 0x000(SI), Z16
VMOVDQU64 0x040(SI), Z17
VMOVDQU64 0x080(SI), Z18
VMOVDQU64 0x0c0(SI), Z19
VMOVDQU64 0x100(SI), Z20
VMOVDQU64 0x140(SI), Z21
VMOVDQU64 0x180(SI), Z22
VMOVDQU64 0x1c0(SI), Z23
// Initialize multiplication constants
VSHUFI64X2 $0x55, Z16, Z16, Z24
VSHUFI64X2 $0xaa, Z16, Z16, Z25
VSHUFI64X2 $0xff, Z16, Z16, Z26
VSHUFI64X2 $0x00, Z16, Z16, Z16
VSHUFI64X2 $0x55, Z20, Z20, Z27
VSHUFI64X2 $0xaa, Z20, Z20, Z28
VSHUFI64X2 $0xff, Z20, Z20, Z29
VSHUFI64X2 $0x00, Z20, Z20, Z20
VSHUFI64X2 $0x55, Z17, Z17, Z30
VSHUFI64X2 $0xaa, Z17, Z17, Z31
VSHUFI64X2 $0xff, Z17, Z17, Z11
VSHUFI64X2 $0x00, Z17, Z17, Z17
VSHUFI64X2 $0x55, Z21, Z21, Z8
VSHUFI64X2 $0xaa, Z21, Z21, Z9
VSHUFI64X2 $0xff, Z21, Z21, Z10
VSHUFI64X2 $0x00, Z21, Z21, Z21
MOVQ $15, BX
MOVQ BX, X5
LONG $0x487df262; WORD $0xd578 // VPBROADCASTB ZMM2, XMM5
VPBROADCASTB BX, Z2
MOVB addTo+56(FP), AX
LONG $0xffc0c749; WORD $0xffff; BYTE $0xff // mov r8, -1
WORD $0xf749; BYTE $0xe0 // mul r8
LONG $0x92fbe1c4; BYTE $0xc8 // kmovq k1, rax
MOVQ in+0(FP), SI // SI: &in
MOVQ in_len+8(FP), AX // number of inputs
XORQ R11, R11
MOVQ out+24(FP), DX
MOVQ 24(DX), CX // CX: &out[1][0]
MOVQ (DX), DX // DX: &out[0][0]
MOVB addTo+56(FP), AX
IMULQ $-0x1, AX
KMOVQ AX, K1
MOVQ in+0(FP), SI // SI: &in
MOVQ in_len+8(FP), AX // number of inputs
XORQ R11, R11
MOVQ out+24(FP), DX
MOVQ 24(DX), CX // CX: &out[1][0]
MOVQ (DX), DX // DX: &out[0][0]
loopback_avx512_parallel82:
LONG $0xc9fef162; WORD $0x226f // VMOVDQU64 ZMM4{k1}{z}, [rdx]
LONG $0xc9fef162; WORD $0x296f // VMOVDQU64 ZMM5{k1}{z}, [rcx]
VMOVDQU64.Z (DX), K1, Z4
VMOVDQU64.Z (CX), K1, Z5
MOVQ (SI), BX // BX: &in[0][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40fd3362; WORD $0xf043; BYTE $0x00 // VSHUFI64x2 ZMM14, ZMM16, ZMM16, 0x00
LONG $0x40fd3362; WORD $0xf843; BYTE $0x55 // VSHUFI64x2 ZMM15, ZMM16, ZMM16, 0x55
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LOAD(0x00) // &in[0][0]
GALOIS_MUL(Z16, Z24, Z14, Z15, Z4)
GALOIS_MUL(Z20, Z27, Z12, Z13, Z5)
LONG $0x40dd3362; WORD $0xe443; BYTE $0x00 // VSHUFI64x2 ZMM12, ZMM20, ZMM20, 0x00
LONG $0x40dd3362; WORD $0xec43; BYTE $0x55 // VSHUFI64x2 ZMM13, ZMM20, ZMM20, 0x55
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
CMPQ AX, $1
JE skip_avx512_parallel82
CMPQ AX, $1
JE skip_avx512_parallel82
LOAD(0x18) // &in[1][0]
GALOIS_MUL(Z25, Z26, Z14, Z15, Z4)
GALOIS_MUL(Z28, Z29, Z12, Z13, Z5)
MOVQ 24(SI), BX // BX: &in[1][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40fd3362; WORD $0xf043; BYTE $0xaa // VSHUFI64x2 ZMM14, ZMM16, ZMM16, 0xaa
LONG $0x40fd3362; WORD $0xf843; BYTE $0xff // VSHUFI64x2 ZMM15, ZMM16, ZMM16, 0xff
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
CMPQ AX, $2
JE skip_avx512_parallel82
LONG $0x40dd3362; WORD $0xe443; BYTE $0xaa // VSHUFI64x2 ZMM12, ZMM20, ZMM20, 0xaa
LONG $0x40dd3362; WORD $0xec43; BYTE $0xff // VSHUFI64x2 ZMM13, ZMM20, ZMM20, 0xff
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LOAD(0x30) // &in[2][0]
GALOIS_MUL(Z17, Z30, Z14, Z15, Z4)
GALOIS_MUL(Z21, Z8, Z12, Z13, Z5)
CMPQ AX, $2
JE skip_avx512_parallel82
CMPQ AX, $3
JE skip_avx512_parallel82
MOVQ 48(SI), BX // BX: &in[2][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40f53362; WORD $0xf143; BYTE $0x00 // VSHUFI64x2 ZMM14, ZMM17, ZMM17, 0x00
LONG $0x40f53362; WORD $0xf943; BYTE $0x55 // VSHUFI64x2 ZMM15, ZMM17, ZMM17, 0x55
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LOAD(0x48) // &in[3][0]
GALOIS_MUL(Z31, Z11, Z14, Z15, Z4)
GALOIS_MUL(Z9, Z10, Z12, Z13, Z5)
LONG $0x40d53362; WORD $0xe543; BYTE $0x00 // VSHUFI64x2 ZMM12, ZMM21, ZMM21, 0x00
LONG $0x40d53362; WORD $0xed43; BYTE $0x55 // VSHUFI64x2 ZMM13, ZMM21, ZMM21, 0x55
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
CMPQ AX, $4
JE skip_avx512_parallel82
CMPQ AX, $3
JE skip_avx512_parallel82
LOAD(0x60) // &in[4][0]
GALOIS(0x00, 0x55, Z18, Z14, Z15, Z4)
GALOIS(0x00, 0x55, Z22, Z12, Z13, Z5)
MOVQ 72(SI), BX // BX: &in[3][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40f53362; WORD $0xf143; BYTE $0xaa // VSHUFI64x2 ZMM14, ZMM17, ZMM17, 0xaa
LONG $0x40f53362; WORD $0xf943; BYTE $0xff // VSHUFI64x2 ZMM15, ZMM17, ZMM17, 0xff
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
CMPQ AX, $5
JE skip_avx512_parallel82
LONG $0x40d53362; WORD $0xe543; BYTE $0xaa // VSHUFI64x2 ZMM12, ZMM21, ZMM21, 0xaa
LONG $0x40d53362; WORD $0xed43; BYTE $0xff // VSHUFI64x2 ZMM13, ZMM21, ZMM21, 0xff
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LOAD(0x78) // &in[5][0]
GALOIS(0xaa, 0xff, Z18, Z14, Z15, Z4)
GALOIS(0xaa, 0xff, Z22, Z12, Z13, Z5)
CMPQ AX, $4
JE skip_avx512_parallel82
CMPQ AX, $6
JE skip_avx512_parallel82
MOVQ 96(SI), BX // BX: &in[4][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40ed3362; WORD $0xf243; BYTE $0x00 // VSHUFI64x2 ZMM14, ZMM18, ZMM18, 0x00
LONG $0x40ed3362; WORD $0xfa43; BYTE $0x55 // VSHUFI64x2 ZMM15, ZMM18, ZMM18, 0x55
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LOAD(0x90) // &in[6][0]
GALOIS(0x00, 0x55, Z19, Z14, Z15, Z4)
GALOIS(0x00, 0x55, Z23, Z12, Z13, Z5)
LONG $0x40cd3362; WORD $0xe643; BYTE $0x00 // VSHUFI64x2 ZMM12, ZMM22, ZMM22, 0x00
LONG $0x40cd3362; WORD $0xee43; BYTE $0x55 // VSHUFI64x2 ZMM13, ZMM22, ZMM22, 0x55
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
CMPQ AX, $7
JE skip_avx512_parallel82
CMPQ AX, $5
JE skip_avx512_parallel82
MOVQ 120(SI), BX // BX: &in[5][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40ed3362; WORD $0xf243; BYTE $0xaa // VSHUFI64x2 ZMM14, ZMM18, ZMM18, 0xaa
LONG $0x40ed3362; WORD $0xfa43; BYTE $0xff // VSHUFI64x2 ZMM15, ZMM18, ZMM18, 0xff
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40cd3362; WORD $0xe643; BYTE $0xaa // VSHUFI64x2 ZMM12, ZMM22, ZMM22, 0xaa
LONG $0x40cd3362; WORD $0xee43; BYTE $0xff // VSHUFI64x2 ZMM13, ZMM22, ZMM22, 0xff
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
CMPQ AX, $6
JE skip_avx512_parallel82
MOVQ 144(SI), BX // BX: &in[6][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40e53362; WORD $0xf343; BYTE $0x00 // VSHUFI64x2 ZMM14, ZMM19, ZMM19, 0x00
LONG $0x40e53362; WORD $0xfb43; BYTE $0x55 // VSHUFI64x2 ZMM15, ZMM19, ZMM19, 0x55
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40c53362; WORD $0xe743; BYTE $0x00 // VSHUFI64x2 ZMM12, ZMM23, ZMM23, 0x00
LONG $0x40c53362; WORD $0xef43; BYTE $0x55 // VSHUFI64x2 ZMM13, ZMM23, ZMM23, 0x55
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
CMPQ AX, $7
JE skip_avx512_parallel82
MOVQ 168(SI), BX // BX: &in[7][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40e53362; WORD $0xf343; BYTE $0xaa // VSHUFI64x2 ZMM14, ZMM19, ZMM19, 0xaa
LONG $0x40e53362; WORD $0xfb43; BYTE $0xff // VSHUFI64x2 ZMM15, ZMM19, ZMM19, 0xff
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40c53362; WORD $0xe743; BYTE $0xaa // VSHUFI64x2 ZMM12, ZMM23, ZMM23, 0xaa
LONG $0x40c53362; WORD $0xef43; BYTE $0xff // VSHUFI64x2 ZMM13, ZMM23, ZMM23, 0xff
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LOAD(0xa8) // &in[7][0]
GALOIS(0xaa, 0xff, Z19, Z14, Z15, Z4)
GALOIS(0xaa, 0xff, Z23, Z12, Z13, Z5)
skip_avx512_parallel82:
LONG $0x48fef162; WORD $0x227f // VMOVDQU64 [rdx], ZMM4
LONG $0x48fef162; WORD $0x297f // VMOVDQU64 [rcx], ZMM5
VMOVDQU64 Z4, (DX)
VMOVDQU64 Z5, (CX)
ADDQ $64, R11 // in4+=64
ADDQ $64, DX // out+=64
ADDQ $64, CX // out2+=64
ADDQ $64, DX // out+=64
ADDQ $64, CX // out2+=64
SUBQ $1, R9
JNZ loopback_avx512_parallel82
@@ -237,343 +265,125 @@ done_avx512_parallel82:
//
// func _galMulAVX512Parallel84(in, out [][]byte, matrix *[matrixSize84]byte, addTo bool)
TEXT ·_galMulAVX512Parallel84(SB), 7, $0
MOVQ in+0(FP), SI //
MOVQ 8(SI), R9 // R9: len(in)
SHRQ $6, R9 // len(in) / 64
MOVQ in+0(FP), SI
MOVQ 8(SI), R9 // R9: len(in)
SHRQ $6, R9 // len(in) / 64
TESTQ R9, R9
JZ done_avx512_parallel84
MOVQ matrix+48(FP), SI
LONG $0x48fee162; WORD $0x066f // VMOVDQU64 ZMM16, 0x000[rsi]
LONG $0x48fee162; WORD $0x4e6f; BYTE $0x01 // VMOVDQU64 ZMM17, 0x040[rsi]
LONG $0x48fee162; WORD $0x566f; BYTE $0x02 // VMOVDQU64 ZMM18, 0x080[rsi]
LONG $0x48fee162; WORD $0x5e6f; BYTE $0x03 // VMOVDQU64 ZMM19, 0x0c0[rsi]
LONG $0x48fee162; WORD $0x666f; BYTE $0x04 // VMOVDQU64 ZMM20, 0x100[rsi]
LONG $0x48fee162; WORD $0x6e6f; BYTE $0x05 // VMOVDQU64 ZMM21, 0x140[rsi]
LONG $0x48fee162; WORD $0x766f; BYTE $0x06 // VMOVDQU64 ZMM22, 0x180[rsi]
LONG $0x48fee162; WORD $0x7e6f; BYTE $0x07 // VMOVDQU64 ZMM23, 0x1c0[rsi]
LONG $0x48fe6162; WORD $0x466f; BYTE $0x08 // VMOVDQU64 ZMM24, 0x200[rsi]
LONG $0x48fe6162; WORD $0x4e6f; BYTE $0x09 // VMOVDQU64 ZMM25, 0x240[rsi]
LONG $0x48fe6162; WORD $0x566f; BYTE $0x0a // VMOVDQU64 ZMM26, 0x280[rsi]
LONG $0x48fe6162; WORD $0x5e6f; BYTE $0x0b // VMOVDQU64 ZMM27, 0x2c0[rsi]
LONG $0x48fe6162; WORD $0x666f; BYTE $0x0c // VMOVDQU64 ZMM28, 0x300[rsi]
LONG $0x48fe6162; WORD $0x6e6f; BYTE $0x0d // VMOVDQU64 ZMM29, 0x340[rsi]
LONG $0x48fe6162; WORD $0x766f; BYTE $0x0e // VMOVDQU64 ZMM30, 0x380[rsi]
LONG $0x48fe6162; WORD $0x7e6f; BYTE $0x0f // VMOVDQU64 ZMM31, 0x3c0[rsi]
MOVQ matrix+48(FP), SI
VMOVDQU64 0x000(SI), Z16
VMOVDQU64 0x040(SI), Z17
VMOVDQU64 0x080(SI), Z18
VMOVDQU64 0x0c0(SI), Z19
VMOVDQU64 0x100(SI), Z20
VMOVDQU64 0x140(SI), Z21
VMOVDQU64 0x180(SI), Z22
VMOVDQU64 0x1c0(SI), Z23
VMOVDQU64 0x200(SI), Z24
VMOVDQU64 0x240(SI), Z25
VMOVDQU64 0x280(SI), Z26
VMOVDQU64 0x2c0(SI), Z27
VMOVDQU64 0x300(SI), Z28
VMOVDQU64 0x340(SI), Z29
VMOVDQU64 0x380(SI), Z30
VMOVDQU64 0x3c0(SI), Z31
MOVQ $15, BX
MOVQ BX, X5
LONG $0x487df262; WORD $0xd578 // VPBROADCASTB ZMM2, XMM5
VPBROADCASTB BX, Z2
MOVB addTo+56(FP), AX
LONG $0xffc0c749; WORD $0xffff; BYTE $0xff // mov r8, -1
WORD $0xf749; BYTE $0xe0 // mul r8
LONG $0x92fbe1c4; BYTE $0xc8 // kmovq k1, rax
MOVQ in+0(FP), SI // SI: &in
MOVQ in_len+8(FP), AX // number of inputs
XORQ R11, R11
MOVQ out+24(FP), DX
MOVQ 24(DX), CX // CX: &out[1][0]
MOVQ 48(DX), R10 // R10: &out[2][0]
MOVQ 72(DX), R12 // R12: &out[3][0]
MOVQ (DX), DX // DX: &out[0][0]
MOVB addTo+56(FP), AX
IMULQ $-0x1, AX
KMOVQ AX, K1
MOVQ in+0(FP), SI // SI: &in
MOVQ in_len+8(FP), AX // number of inputs
XORQ R11, R11
MOVQ out+24(FP), DX
MOVQ 24(DX), CX // CX: &out[1][0]
MOVQ 48(DX), R10 // R10: &out[2][0]
MOVQ 72(DX), R12 // R12: &out[3][0]
MOVQ (DX), DX // DX: &out[0][0]
loopback_avx512_parallel84:
LONG $0xc9fef162; WORD $0x226f // VMOVDQU64 ZMM4{k1}{z}, [rdx]
LONG $0xc9fef162; WORD $0x296f // VMOVDQU64 ZMM5{k1}{z}, [rcx]
LONG $0xc9fed162; WORD $0x326f // VMOVDQU64 ZMM6{k1}{z}, [r10]
LONG $0xc9fed162; WORD $0x3c6f; BYTE $0x24 // VMOVDQU64 ZMM7{k1}{z}, [r12]
VMOVDQU64.Z (DX), K1, Z4
VMOVDQU64.Z (CX), K1, Z5
VMOVDQU64.Z (R10), K1, Z6
VMOVDQU64.Z (R12), K1, Z7
MOVQ (SI), BX // BX: &in[0][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40fd3362; WORD $0xf043; BYTE $0x00 // VSHUFI64x2 ZMM14, ZMM16, ZMM16, 0x00
LONG $0x40fd3362; WORD $0xf843; BYTE $0x55 // VSHUFI64x2 ZMM15, ZMM16, ZMM16, 0x55
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40dd3362; WORD $0xe443; BYTE $0x00 // VSHUFI64x2 ZMM12, ZMM20, ZMM20, 0x00
LONG $0x40dd3362; WORD $0xec43; BYTE $0x55 // VSHUFI64x2 ZMM13, ZMM20, ZMM20, 0x55
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LONG $0x40bd1362; WORD $0xd043; BYTE $0x00 // VSHUFI64x2 ZMM10, ZMM24, ZMM24, 0x00
LONG $0x40bd1362; WORD $0xd843; BYTE $0x55 // VSHUFI64x2 ZMM11, ZMM24, ZMM24, 0x55
LONG $0x482d7262; WORD $0xd000 // VPSHUFB ZMM10, ZMM10, ZMM0 ; mul low part
LONG $0x48257262; WORD $0xd900 // VPSHUFB ZMM11, ZMM11, ZMM1 ; mul high part
LONG $0x48ad5162; WORD $0xd3ef // VPXORQ ZMM10, ZMM10, ZMM11 ; result
LONG $0x48cdd162; WORD $0xf2ef // VPXORQ ZMM6, ZMM6, ZMM10
LONG $0x409d1362; WORD $0xc443; BYTE $0x00 // VSHUFI64x2 ZMM8, ZMM28, ZMM28, 0x00
LONG $0x409d1362; WORD $0xcc43; BYTE $0x55 // VSHUFI64x2 ZMM9, ZMM28, ZMM28, 0x55
LONG $0x483d7262; WORD $0xc000 // VPSHUFB ZMM8, ZMM8, ZMM0 ; mul low part
LONG $0x48357262; WORD $0xc900 // VPSHUFB ZMM9, ZMM9, ZMM1 ; mul high part
LONG $0x48bd5162; WORD $0xc1ef // VPXORQ ZMM8, ZMM8, ZMM9 ; result
LONG $0x48c5d162; WORD $0xf8ef // VPXORQ ZMM7, ZMM7, ZMM8
LOAD(0x00) // &in[0][0]
GALOIS(0x00, 0x55, Z16, Z14, Z15, Z4)
GALOIS(0x00, 0x55, Z20, Z12, Z13, Z5)
GALOIS(0x00, 0x55, Z24, Z10, Z11, Z6)
GALOIS(0x00, 0x55, Z28, Z8, Z9, Z7)
CMPQ AX, $1
JE skip_avx512_parallel84
JE skip_avx512_parallel84
MOVQ 24(SI), BX // BX: &in[1][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40fd3362; WORD $0xf043; BYTE $0xaa // VSHUFI64x2 ZMM14, ZMM16, ZMM16, 0xaa
LONG $0x40fd3362; WORD $0xf843; BYTE $0xff // VSHUFI64x2 ZMM15, ZMM16, ZMM16, 0xff
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40dd3362; WORD $0xe443; BYTE $0xaa // VSHUFI64x2 ZMM12, ZMM20, ZMM20, 0xaa
LONG $0x40dd3362; WORD $0xec43; BYTE $0xff // VSHUFI64x2 ZMM13, ZMM20, ZMM20, 0xff
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LONG $0x40bd1362; WORD $0xd043; BYTE $0xaa // VSHUFI64x2 ZMM10, ZMM24, ZMM24, 0xaa
LONG $0x40bd1362; WORD $0xd843; BYTE $0xff // VSHUFI64x2 ZMM11, ZMM24, ZMM24, 0xff
LONG $0x482d7262; WORD $0xd000 // VPSHUFB ZMM10, ZMM10, ZMM0 ; mul low part
LONG $0x48257262; WORD $0xd900 // VPSHUFB ZMM11, ZMM11, ZMM1 ; mul high part
LONG $0x48ad5162; WORD $0xd3ef // VPXORQ ZMM10, ZMM10, ZMM11 ; result
LONG $0x48cdd162; WORD $0xf2ef // VPXORQ ZMM6, ZMM6, ZMM10
LONG $0x409d1362; WORD $0xc443; BYTE $0xaa // VSHUFI64x2 ZMM8, ZMM28, ZMM28, 0xaa
LONG $0x409d1362; WORD $0xcc43; BYTE $0xff // VSHUFI64x2 ZMM9, ZMM28, ZMM28, 0xff
LONG $0x483d7262; WORD $0xc000 // VPSHUFB ZMM8, ZMM8, ZMM0 ; mul low part
LONG $0x48357262; WORD $0xc900 // VPSHUFB ZMM9, ZMM9, ZMM1 ; mul high part
LONG $0x48bd5162; WORD $0xc1ef // VPXORQ ZMM8, ZMM8, ZMM9 ; result
LONG $0x48c5d162; WORD $0xf8ef // VPXORQ ZMM7, ZMM7, ZMM8
LOAD(0x18) // &in[1][0]
GALOIS(0xaa, 0xff, Z16, Z14, Z15, Z4)
GALOIS(0xaa, 0xff, Z20, Z12, Z13, Z5)
GALOIS(0xaa, 0xff, Z24, Z10, Z11, Z6)
GALOIS(0xaa, 0xff, Z28, Z8, Z9, Z7)
CMPQ AX, $2
JE skip_avx512_parallel84
JE skip_avx512_parallel84
MOVQ 48(SI), BX // BX: &in[2][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40f53362; WORD $0xf143; BYTE $0x00 // VSHUFI64x2 ZMM14, ZMM17, ZMM17, 0x00
LONG $0x40f53362; WORD $0xf943; BYTE $0x55 // VSHUFI64x2 ZMM15, ZMM17, ZMM17, 0x55
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40d53362; WORD $0xe543; BYTE $0x00 // VSHUFI64x2 ZMM12, ZMM21, ZMM21, 0x00
LONG $0x40d53362; WORD $0xed43; BYTE $0x55 // VSHUFI64x2 ZMM13, ZMM21, ZMM21, 0x55
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LONG $0x40b51362; WORD $0xd143; BYTE $0x00 // VSHUFI64x2 ZMM10, ZMM25, ZMM25, 0x00
LONG $0x40b51362; WORD $0xd943; BYTE $0x55 // VSHUFI64x2 ZMM11, ZMM25, ZMM25, 0x55
LONG $0x482d7262; WORD $0xd000 // VPSHUFB ZMM10, ZMM10, ZMM0 ; mul low part
LONG $0x48257262; WORD $0xd900 // VPSHUFB ZMM11, ZMM11, ZMM1 ; mul high part
LONG $0x48ad5162; WORD $0xd3ef // VPXORQ ZMM10, ZMM10, ZMM11 ; result
LONG $0x48cdd162; WORD $0xf2ef // VPXORQ ZMM6, ZMM6, ZMM10
LONG $0x40951362; WORD $0xc543; BYTE $0x00 // VSHUFI64x2 ZMM8, ZMM29, ZMM29, 0x00
LONG $0x40951362; WORD $0xcd43; BYTE $0x55 // VSHUFI64x2 ZMM9, ZMM29, ZMM29, 0x55
LONG $0x483d7262; WORD $0xc000 // VPSHUFB ZMM8, ZMM8, ZMM0 ; mul low part
LONG $0x48357262; WORD $0xc900 // VPSHUFB ZMM9, ZMM9, ZMM1 ; mul high part
LONG $0x48bd5162; WORD $0xc1ef // VPXORQ ZMM8, ZMM8, ZMM9 ; result
LONG $0x48c5d162; WORD $0xf8ef // VPXORQ ZMM7, ZMM7, ZMM8
LOAD(0x30) // &in[2][0]
GALOIS(0x00, 0x55, Z17, Z14, Z15, Z4)
GALOIS(0x00, 0x55, Z21, Z12, Z13, Z5)
GALOIS(0x00, 0x55, Z25, Z10, Z11, Z6)
GALOIS(0x00, 0x55, Z29, Z8, Z9, Z7)
CMPQ AX, $3
JE skip_avx512_parallel84
JE skip_avx512_parallel84
MOVQ 72(SI), BX // BX: &in[3][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40f53362; WORD $0xf143; BYTE $0xaa // VSHUFI64x2 ZMM14, ZMM17, ZMM17, 0xaa
LONG $0x40f53362; WORD $0xf943; BYTE $0xff // VSHUFI64x2 ZMM15, ZMM17, ZMM17, 0xff
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40d53362; WORD $0xe543; BYTE $0xaa // VSHUFI64x2 ZMM12, ZMM21, ZMM21, 0xaa
LONG $0x40d53362; WORD $0xed43; BYTE $0xff // VSHUFI64x2 ZMM13, ZMM21, ZMM21, 0xff
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LONG $0x40b51362; WORD $0xd143; BYTE $0xaa // VSHUFI64x2 ZMM10, ZMM25, ZMM25, 0xaa
LONG $0x40b51362; WORD $0xd943; BYTE $0xff // VSHUFI64x2 ZMM11, ZMM25, ZMM25, 0xff
LONG $0x482d7262; WORD $0xd000 // VPSHUFB ZMM10, ZMM10, ZMM0 ; mul low part
LONG $0x48257262; WORD $0xd900 // VPSHUFB ZMM11, ZMM11, ZMM1 ; mul high part
LONG $0x48ad5162; WORD $0xd3ef // VPXORQ ZMM10, ZMM10, ZMM11 ; result
LONG $0x48cdd162; WORD $0xf2ef // VPXORQ ZMM6, ZMM6, ZMM10
LONG $0x40951362; WORD $0xc543; BYTE $0xaa // VSHUFI64x2 ZMM8, ZMM29, ZMM29, 0xaa
LONG $0x40951362; WORD $0xcd43; BYTE $0xff // VSHUFI64x2 ZMM9, ZMM29, ZMM29, 0xff
LONG $0x483d7262; WORD $0xc000 // VPSHUFB ZMM8, ZMM8, ZMM0 ; mul low part
LONG $0x48357262; WORD $0xc900 // VPSHUFB ZMM9, ZMM9, ZMM1 ; mul high part
LONG $0x48bd5162; WORD $0xc1ef // VPXORQ ZMM8, ZMM8, ZMM9 ; result
LONG $0x48c5d162; WORD $0xf8ef // VPXORQ ZMM7, ZMM7, ZMM8
LOAD(0x48) // &in[3][0]
GALOIS(0xaa, 0xff, Z17, Z14, Z15, Z4)
GALOIS(0xaa, 0xff, Z21, Z12, Z13, Z5)
GALOIS(0xaa, 0xff, Z25, Z10, Z11, Z6)
GALOIS(0xaa, 0xff, Z29, Z8, Z9, Z7)
CMPQ AX, $4
JE skip_avx512_parallel84
JE skip_avx512_parallel84
MOVQ 96(SI), BX // BX: &in[4][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40ed3362; WORD $0xf243; BYTE $0x00 // VSHUFI64x2 ZMM14, ZMM18, ZMM18, 0x00
LONG $0x40ed3362; WORD $0xfa43; BYTE $0x55 // VSHUFI64x2 ZMM15, ZMM18, ZMM18, 0x55
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40cd3362; WORD $0xe643; BYTE $0x00 // VSHUFI64x2 ZMM12, ZMM22, ZMM22, 0x00
LONG $0x40cd3362; WORD $0xee43; BYTE $0x55 // VSHUFI64x2 ZMM13, ZMM22, ZMM22, 0x55
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LONG $0x40ad1362; WORD $0xd243; BYTE $0x00 // VSHUFI64x2 ZMM10, ZMM26, ZMM26, 0x00
LONG $0x40ad1362; WORD $0xda43; BYTE $0x55 // VSHUFI64x2 ZMM11, ZMM26, ZMM26, 0x55
LONG $0x482d7262; WORD $0xd000 // VPSHUFB ZMM10, ZMM10, ZMM0 ; mul low part
LONG $0x48257262; WORD $0xd900 // VPSHUFB ZMM11, ZMM11, ZMM1 ; mul high part
LONG $0x48ad5162; WORD $0xd3ef // VPXORQ ZMM10, ZMM10, ZMM11 ; result
LONG $0x48cdd162; WORD $0xf2ef // VPXORQ ZMM6, ZMM6, ZMM10
LONG $0x408d1362; WORD $0xc643; BYTE $0x00 // VSHUFI64x2 ZMM8, ZMM30, ZMM30, 0x00
LONG $0x408d1362; WORD $0xce43; BYTE $0x55 // VSHUFI64x2 ZMM9, ZMM30, ZMM30, 0x55
LONG $0x483d7262; WORD $0xc000 // VPSHUFB ZMM8, ZMM8, ZMM0 ; mul low part
LONG $0x48357262; WORD $0xc900 // VPSHUFB ZMM9, ZMM9, ZMM1 ; mul high part
LONG $0x48bd5162; WORD $0xc1ef // VPXORQ ZMM8, ZMM8, ZMM9 ; result
LONG $0x48c5d162; WORD $0xf8ef // VPXORQ ZMM7, ZMM7, ZMM8
LOAD(0x60) // &in[4][0]
GALOIS(0x00, 0x55, Z18, Z14, Z15, Z4)
GALOIS(0x00, 0x55, Z22, Z12, Z13, Z5)
GALOIS(0x00, 0x55, Z26, Z10, Z11, Z6)
GALOIS(0x00, 0x55, Z30, Z8, Z9, Z7)
CMPQ AX, $5
JE skip_avx512_parallel84
JE skip_avx512_parallel84
MOVQ 120(SI), BX // BX: &in[5][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40ed3362; WORD $0xf243; BYTE $0xaa // VSHUFI64x2 ZMM14, ZMM18, ZMM18, 0xaa
LONG $0x40ed3362; WORD $0xfa43; BYTE $0xff // VSHUFI64x2 ZMM15, ZMM18, ZMM18, 0xff
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40cd3362; WORD $0xe643; BYTE $0xaa // VSHUFI64x2 ZMM12, ZMM22, ZMM22, 0xaa
LONG $0x40cd3362; WORD $0xee43; BYTE $0xff // VSHUFI64x2 ZMM13, ZMM22, ZMM22, 0xff
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LONG $0x40ad1362; WORD $0xd243; BYTE $0xaa // VSHUFI64x2 ZMM10, ZMM26, ZMM26, 0xaa
LONG $0x40ad1362; WORD $0xda43; BYTE $0xff // VSHUFI64x2 ZMM11, ZMM26, ZMM26, 0xff
LONG $0x482d7262; WORD $0xd000 // VPSHUFB ZMM10, ZMM10, ZMM0 ; mul low part
LONG $0x48257262; WORD $0xd900 // VPSHUFB ZMM11, ZMM11, ZMM1 ; mul high part
LONG $0x48ad5162; WORD $0xd3ef // VPXORQ ZMM10, ZMM10, ZMM11 ; result
LONG $0x48cdd162; WORD $0xf2ef // VPXORQ ZMM6, ZMM6, ZMM10
LONG $0x408d1362; WORD $0xc643; BYTE $0xaa // VSHUFI64x2 ZMM8, ZMM30, ZMM30, 0xaa
LONG $0x408d1362; WORD $0xce43; BYTE $0xff // VSHUFI64x2 ZMM9, ZMM30, ZMM30, 0xff
LONG $0x483d7262; WORD $0xc000 // VPSHUFB ZMM8, ZMM8, ZMM0 ; mul low part
LONG $0x48357262; WORD $0xc900 // VPSHUFB ZMM9, ZMM9, ZMM1 ; mul high part
LONG $0x48bd5162; WORD $0xc1ef // VPXORQ ZMM8, ZMM8, ZMM9 ; result
LONG $0x48c5d162; WORD $0xf8ef // VPXORQ ZMM7, ZMM7, ZMM8
LOAD(0x78) // &in[5][0]
GALOIS(0xaa, 0xff, Z18, Z14, Z15, Z4)
GALOIS(0xaa, 0xff, Z22, Z12, Z13, Z5)
GALOIS(0xaa, 0xff, Z26, Z10, Z11, Z6)
GALOIS(0xaa, 0xff, Z30, Z8, Z9, Z7)
CMPQ AX, $6
JE skip_avx512_parallel84
JE skip_avx512_parallel84
MOVQ 144(SI), BX // BX: &in[6][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40e53362; WORD $0xf343; BYTE $0x00 // VSHUFI64x2 ZMM14, ZMM19, ZMM19, 0x00
LONG $0x40e53362; WORD $0xfb43; BYTE $0x55 // VSHUFI64x2 ZMM15, ZMM19, ZMM19, 0x55
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40c53362; WORD $0xe743; BYTE $0x00 // VSHUFI64x2 ZMM12, ZMM23, ZMM23, 0x00
LONG $0x40c53362; WORD $0xef43; BYTE $0x55 // VSHUFI64x2 ZMM13, ZMM23, ZMM23, 0x55
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LONG $0x40a51362; WORD $0xd343; BYTE $0x00 // VSHUFI64x2 ZMM10, ZMM27, ZMM27, 0x00
LONG $0x40a51362; WORD $0xdb43; BYTE $0x55 // VSHUFI64x2 ZMM11, ZMM27, ZMM27, 0x55
LONG $0x482d7262; WORD $0xd000 // VPSHUFB ZMM10, ZMM10, ZMM0 ; mul low part
LONG $0x48257262; WORD $0xd900 // VPSHUFB ZMM11, ZMM11, ZMM1 ; mul high part
LONG $0x48ad5162; WORD $0xd3ef // VPXORQ ZMM10, ZMM10, ZMM11 ; result
LONG $0x48cdd162; WORD $0xf2ef // VPXORQ ZMM6, ZMM6, ZMM10
LONG $0x40851362; WORD $0xc743; BYTE $0x00 // VSHUFI64x2 ZMM8, ZMM31, ZMM31, 0x00
LONG $0x40851362; WORD $0xcf43; BYTE $0x55 // VSHUFI64x2 ZMM9, ZMM31, ZMM31, 0x55
LONG $0x483d7262; WORD $0xc000 // VPSHUFB ZMM8, ZMM8, ZMM0 ; mul low part
LONG $0x48357262; WORD $0xc900 // VPSHUFB ZMM9, ZMM9, ZMM1 ; mul high part
LONG $0x48bd5162; WORD $0xc1ef // VPXORQ ZMM8, ZMM8, ZMM9 ; result
LONG $0x48c5d162; WORD $0xf8ef // VPXORQ ZMM7, ZMM7, ZMM8
LOAD(0x90) // &in[6][0]
GALOIS(0x00, 0x55, Z19, Z14, Z15, Z4)
GALOIS(0x00, 0x55, Z23, Z12, Z13, Z5)
GALOIS(0x00, 0x55, Z27, Z10, Z11, Z6)
GALOIS(0x00, 0x55, Z31, Z8, Z9, Z7)
CMPQ AX, $7
JE skip_avx512_parallel84
JE skip_avx512_parallel84
MOVQ 168(SI), BX // BX: &in[7][0]
LONG $0x48feb162; WORD $0x046f; BYTE $0x1b // VMOVDQU64 ZMM0, [rbx+r11]
LONG $0x40e53362; WORD $0xf343; BYTE $0xaa // VSHUFI64x2 ZMM14, ZMM19, ZMM19, 0xaa
LONG $0x40e53362; WORD $0xfb43; BYTE $0xff // VSHUFI64x2 ZMM15, ZMM19, ZMM19, 0xff
LONG $0x48f5f162; WORD $0xd073; BYTE $0x04 // VPSRLQ ZMM1, ZMM0, 4 ; high input
LONG $0x48fdf162; WORD $0xc2db // VPANDQ ZMM0, ZMM0, ZMM2 ; low input
LONG $0x48f5f162; WORD $0xcadb // VPANDQ ZMM1, ZMM1, ZMM2 ; high input
LONG $0x480d7262; WORD $0xf000 // VPSHUFB ZMM14, ZMM14, ZMM0 ; mul low part
LONG $0x48057262; WORD $0xf900 // VPSHUFB ZMM15, ZMM15, ZMM1 ; mul high part
LONG $0x488d5162; WORD $0xf7ef // VPXORQ ZMM14, ZMM14, ZMM15 ; result
LONG $0x48ddd162; WORD $0xe6ef // VPXORQ ZMM4, ZMM4, ZMM14
LONG $0x40c53362; WORD $0xe743; BYTE $0xaa // VSHUFI64x2 ZMM12, ZMM23, ZMM23, 0xaa
LONG $0x40c53362; WORD $0xef43; BYTE $0xff // VSHUFI64x2 ZMM13, ZMM23, ZMM23, 0xff
LONG $0x481d7262; WORD $0xe000 // VPSHUFB ZMM12, ZMM12, ZMM0 ; mul low part
LONG $0x48157262; WORD $0xe900 // VPSHUFB ZMM13, ZMM13, ZMM1 ; mul high part
LONG $0x489d5162; WORD $0xe5ef // VPXORQ ZMM12, ZMM12, ZMM13 ; result
LONG $0x48d5d162; WORD $0xecef // VPXORQ ZMM5, ZMM5, ZMM12
LONG $0x40a51362; WORD $0xd343; BYTE $0xaa // VSHUFI64x2 ZMM10, ZMM27, ZMM27, 0xaa
LONG $0x40a51362; WORD $0xdb43; BYTE $0xff // VSHUFI64x2 ZMM11, ZMM27, ZMM27, 0xff
LONG $0x482d7262; WORD $0xd000 // VPSHUFB ZMM10, ZMM10, ZMM0 ; mul low part
LONG $0x48257262; WORD $0xd900 // VPSHUFB ZMM11, ZMM11, ZMM1 ; mul high part
LONG $0x48ad5162; WORD $0xd3ef // VPXORQ ZMM10, ZMM10, ZMM11 ; result
LONG $0x48cdd162; WORD $0xf2ef // VPXORQ ZMM6, ZMM6, ZMM10
LONG $0x40851362; WORD $0xc743; BYTE $0xaa // VSHUFI64x2 ZMM8, ZMM31, ZMM31, 0xaa
LONG $0x40851362; WORD $0xcf43; BYTE $0xff // VSHUFI64x2 ZMM9, ZMM31, ZMM31, 0xff
LONG $0x483d7262; WORD $0xc000 // VPSHUFB ZMM8, ZMM8, ZMM0 ; mul low part
LONG $0x48357262; WORD $0xc900 // VPSHUFB ZMM9, ZMM9, ZMM1 ; mul high part
LONG $0x48bd5162; WORD $0xc1ef // VPXORQ ZMM8, ZMM8, ZMM9 ; result
LONG $0x48c5d162; WORD $0xf8ef // VPXORQ ZMM7, ZMM7, ZMM8
LOAD(0xa8) // &in[7][0]
GALOIS(0xaa, 0xff, Z19, Z14, Z15, Z4)
GALOIS(0xaa, 0xff, Z23, Z12, Z13, Z5)
GALOIS(0xaa, 0xff, Z27, Z10, Z11, Z6)
GALOIS(0xaa, 0xff, Z31, Z8, Z9, Z7)
skip_avx512_parallel84:
LONG $0x48fef162; WORD $0x227f // VMOVDQU64 [rdx], ZMM4
LONG $0x48fef162; WORD $0x297f // VMOVDQU64 [rcx], ZMM5
LONG $0x48fed162; WORD $0x327f // VMOVDQU64 [r10], ZMM6
LONG $0x48fed162; WORD $0x3c7f; BYTE $0x24 // VMOVDQU64 [r12], ZMM7
VMOVDQU64 Z4, (DX)
VMOVDQU64 Z5, (CX)
VMOVDQU64 Z6, (R10)
VMOVDQU64 Z7, (R12)
ADDQ $64, R11 // in4+=64
+76 -30
View File
@@ -21,6 +21,15 @@ func galMulAVX2(low, high, in, out []byte)
//go:noescape
func sSE2XorSlice(in, out []byte)
//go:noescape
func galMulAVX2Xor_64(low, high, in, out []byte)
//go:noescape
func galMulAVX2_64(low, high, in, out []byte)
//go:noescape
func sSE2XorSlice_64(in, out []byte)
// This is what the assembler routines do in blocks of 16 bytes:
/*
func galMulSSSE3(low, high, in, out []byte) {
@@ -40,53 +49,90 @@ func galMulSSSE3Xor(low, high, in, out []byte) {
}
*/
// bigSwitchover is the size where 64 bytes are processed per loop.
const bigSwitchover = 128
func galMulSlice(c byte, in, out []byte, o *options) {
var done int
if c == 1 {
copy(out, in)
return
}
if o.useAVX2 {
galMulAVX2(mulTableLow[c][:], mulTableHigh[c][:], in, out)
done = (len(in) >> 5) << 5
if len(in) >= bigSwitchover {
galMulAVX2_64(mulTableLow[c][:], mulTableHigh[c][:], in, out)
done := (len(in) >> 6) << 6
in = in[done:]
out = out[done:]
}
if len(in) > 32 {
galMulAVX2(mulTableLow[c][:], mulTableHigh[c][:], in, out)
done := (len(in) >> 5) << 5
in = in[done:]
out = out[done:]
}
} else if o.useSSSE3 {
galMulSSSE3(mulTableLow[c][:], mulTableHigh[c][:], in, out)
done = (len(in) >> 4) << 4
done := (len(in) >> 4) << 4
in = in[done:]
out = out[done:]
}
remain := len(in) - done
if remain > 0 {
mt := mulTable[c][:256]
for i := done; i < len(in); i++ {
out[i] = mt[in[i]]
}
out = out[:len(in)]
mt := mulTable[c][:256]
for i := range in {
out[i] = mt[in[i]]
}
}
func galMulSliceXor(c byte, in, out []byte, o *options) {
var done int
if c == 1 {
sliceXor(in, out, o)
return
}
if o.useAVX2 {
galMulAVX2Xor(mulTableLow[c][:], mulTableHigh[c][:], in, out)
done = (len(in) >> 5) << 5
if len(in) >= bigSwitchover {
galMulAVX2Xor_64(mulTableLow[c][:], mulTableHigh[c][:], in, out)
done := (len(in) >> 6) << 6
in = in[done:]
out = out[done:]
}
if len(in) >= 32 {
galMulAVX2Xor(mulTableLow[c][:], mulTableHigh[c][:], in, out)
done := (len(in) >> 5) << 5
in = in[done:]
out = out[done:]
}
} else if o.useSSSE3 {
galMulSSSE3Xor(mulTableLow[c][:], mulTableHigh[c][:], in, out)
done = (len(in) >> 4) << 4
done := (len(in) >> 4) << 4
in = in[done:]
out = out[done:]
}
remain := len(in) - done
if remain > 0 {
mt := mulTable[c][:256]
for i := done; i < len(in); i++ {
out[i] ^= mt[in[i]]
}
out = out[:len(in)]
mt := mulTable[c][:256]
for i := range in {
out[i] ^= mt[in[i]]
}
}
// slice galois add
func sliceXor(in, out []byte, sse2 bool) {
var done int
if sse2 {
sSE2XorSlice(in, out)
done = (len(in) >> 4) << 4
}
remain := len(in) - done
if remain > 0 {
for i := done; i < len(in); i++ {
out[i] ^= in[i]
func sliceXor(in, out []byte, o *options) {
if o.useSSE2 {
if len(in) >= bigSwitchover {
sSE2XorSlice_64(in, out)
done := (len(in) >> 6) << 6
in = in[done:]
out = out[done:]
}
if len(in) >= 16 {
sSE2XorSlice(in, out)
done := (len(in) >> 4) << 4
in = in[done:]
out = out[done:]
}
}
out = out[:len(in)]
for i := range in {
out[i] ^= in[i]
}
}
+132
View File
@@ -234,3 +234,135 @@ loopback_xor_sse2:
done_xor_sse2:
RET
// func galMulAVX2Xor_64(low, high, in, out []byte)
TEXT ·galMulAVX2Xor_64(SB), 7, $0
MOVQ low+0(FP), SI // SI: &low
MOVQ high+24(FP), DX // DX: &high
MOVQ $15, BX // BX: low mask
MOVQ BX, X5
MOVOU (SI), X6 // X6: low
MOVOU (DX), X7 // X7: high
MOVQ in_len+56(FP), R9 // R9: len(in)
VINSERTI128 $1, X6, Y6, Y6 // low
VINSERTI128 $1, X7, Y7, Y7 // high
VPBROADCASTB X5, Y8 // Y8: lomask (unpacked)
SHRQ $6, R9 // len(in) / 64
MOVQ out+72(FP), DX // DX: &out
MOVQ in+48(FP), SI // SI: &in
TESTQ R9, R9
JZ done_xor_avx2_64
loopback_xor_avx2_64:
VMOVDQU (SI), Y0
VMOVDQU 32(SI), Y10
VMOVDQU (DX), Y4
VMOVDQU 32(DX), Y14
VPSRLQ $4, Y0, Y1 // Y1: high input
VPSRLQ $4, Y10, Y11 // Y11: high input 2
VPAND Y8, Y0, Y0 // Y0: low input
VPAND Y8, Y10, Y10 // Y10: low input 2
VPAND Y8, Y1, Y1 // Y11: high input
VPAND Y8, Y11, Y11 // Y11: high input 2
VPSHUFB Y0, Y6, Y2 // Y2: mul low part
VPSHUFB Y10, Y6, Y12 // Y12: mul low part 2
VPSHUFB Y1, Y7, Y3 // Y3: mul high part
VPSHUFB Y11, Y7, Y13 // Y13: mul high part 2
VPXOR Y3, Y2, Y3 // Y3: Result
VPXOR Y13, Y12, Y13 // Y13: Result 2
VPXOR Y4, Y3, Y4 // Y4: Result
VPXOR Y14, Y13, Y14 // Y4: Result 2
VMOVDQU Y4, (DX)
VMOVDQU Y14, 32(DX)
ADDQ $64, SI // in+=64
ADDQ $64, DX // out+=64
SUBQ $1, R9
JNZ loopback_xor_avx2_64
done_xor_avx2_64:
VZEROUPPER
RET
// func galMulAVX2_64(low, high, in, out []byte)
TEXT ·galMulAVX2_64(SB), 7, $0
MOVQ low+0(FP), SI // SI: &low
MOVQ high+24(FP), DX // DX: &high
MOVQ $15, BX // BX: low mask
MOVQ BX, X5
MOVOU (SI), X6 // X6: low
MOVOU (DX), X7 // X7: high
MOVQ in_len+56(FP), R9 // R9: len(in)
VINSERTI128 $1, X6, Y6, Y6 // low
VINSERTI128 $1, X7, Y7, Y7 // high
VPBROADCASTB X5, Y8 // Y8: lomask (unpacked)
SHRQ $6, R9 // len(in) / 64
MOVQ out+72(FP), DX // DX: &out
MOVQ in+48(FP), SI // SI: &in
TESTQ R9, R9
JZ done_avx2_64
loopback_avx2_64:
VMOVDQU (SI), Y0
VMOVDQU 32(SI), Y10
VPSRLQ $4, Y0, Y1 // Y1: high input
VPSRLQ $4, Y10, Y11 // Y11: high input 2
VPAND Y8, Y0, Y0 // Y0: low input
VPAND Y8, Y10, Y10 // Y10: low input
VPAND Y8, Y1, Y1 // Y1: high input
VPAND Y8, Y11, Y11 // Y11: high input 2
VPSHUFB Y0, Y6, Y2 // Y2: mul low part
VPSHUFB Y10, Y6, Y12 // Y12: mul low part 2
VPSHUFB Y1, Y7, Y3 // Y3: mul high part
VPSHUFB Y11, Y7, Y13 // Y13: mul high part 2
VPXOR Y3, Y2, Y4 // Y4: Result
VPXOR Y13, Y12, Y14 // Y14: Result 2
VMOVDQU Y4, (DX)
VMOVDQU Y14, 32(DX)
ADDQ $64, SI // in+=64
ADDQ $64, DX // out+=64
SUBQ $1, R9
JNZ loopback_avx2_64
done_avx2_64:
VZEROUPPER
RET
// func sSE2XorSlice_64(in, out []byte)
TEXT ·sSE2XorSlice_64(SB), 7, $0
MOVQ in+0(FP), SI // SI: &in
MOVQ in_len+8(FP), R9 // R9: len(in)
MOVQ out+24(FP), DX // DX: &out
SHRQ $6, R9 // len(in) / 64
CMPQ R9, $0
JEQ done_xor_sse2_64
loopback_xor_sse2_64:
MOVOU (SI), X0 // in[x]
MOVOU 16(SI), X2 // in[x]
MOVOU 32(SI), X4 // in[x]
MOVOU 48(SI), X6 // in[x]
MOVOU (DX), X1 // out[x]
MOVOU 16(DX), X3 // out[x]
MOVOU 32(DX), X5 // out[x]
MOVOU 48(DX), X7 // out[x]
PXOR X0, X1
PXOR X2, X3
PXOR X4, X5
PXOR X6, X7
MOVOU X1, (DX)
MOVOU X3, 16(DX)
MOVOU X5, 32(DX)
MOVOU X7, 48(DX)
ADDQ $64, SI // in+=64
ADDQ $64, DX // out+=64
SUBQ $1, R9
JNZ loopback_xor_sse2_64
done_xor_sse2_64:
RET
+25 -10
View File
@@ -8,14 +8,21 @@
package reedsolomon
//go:noescape
func galMulNEON(c uint64, in, out []byte)
func galMulNEON(low, high, in, out []byte)
//go:noescape
func galMulXorNEON(c uint64, in, out []byte)
func galMulXorNEON(low, high, in, out []byte)
//go:noescape
func galXorNEON(in, out []byte)
func galMulSlice(c byte, in, out []byte, o *options) {
if c == 1 {
copy(out, in)
return
}
var done int
galMulNEON(uint64(c), in, out)
galMulNEON(mulTableLow[c][:], mulTableHigh[c][:], in, out)
done = (len(in) >> 5) << 5
remain := len(in) - done
@@ -28,8 +35,12 @@ func galMulSlice(c byte, in, out []byte, o *options) {
}
func galMulSliceXor(c byte, in, out []byte, o *options) {
if c == 1 {
sliceXor(in, out, o)
return
}
var done int
galMulXorNEON(uint64(c), in, out)
galMulXorNEON(mulTableLow[c][:], mulTableHigh[c][:], in, out)
done = (len(in) >> 5) << 5
remain := len(in) - done
@@ -42,11 +53,15 @@ func galMulSliceXor(c byte, in, out []byte, o *options) {
}
// slice galois add
func sliceXor(in, out []byte, sse2 bool) {
for n, input := range in {
out[n] ^= input
func sliceXor(in, out []byte, o *options) {
galXorNEON(in, out)
done := (len(in) >> 5) << 5
remain := len(in) - done
if remain > 0 {
for i := done; i < len(in); i++ {
out[i] ^= in[i]
}
}
}
func (r reedSolomon) codeSomeShardsAvx512(matrixRows, inputs, outputs [][]byte, outputCount, byteCount int) {
}
+82 -98
View File
@@ -3,83 +3,54 @@
// Copyright 2015, Klaus Post, see LICENSE for details.
// Copyright 2017, Minio, Inc.
// Use github.com/minio/asm2plan9s on this file to assemble ARM instructions to
// the opcodes of their Plan9 equivalents
#define LOAD(LO1, LO2, HI1, HI2) \
VLD1.P 32(R1), [LO1.B16, LO2.B16] \
\
\ // Get low input and high input
VUSHR $4, LO1.B16, HI1.B16 \
VUSHR $4, LO2.B16, HI2.B16 \
VAND V8.B16, LO1.B16, LO1.B16 \
VAND V8.B16, LO2.B16, LO2.B16
// polynomial multiplication
#define POLYNOMIAL_MULTIPLICATION \
WORD $0x0e3ce340 \ // pmull v0.8h,v26.8b,v28.8b
WORD $0x4e3ce346 \ // pmull2 v6.8h,v26.16b,v28.16b
WORD $0x0e3ce36c \ // pmull v12.8h,v27.8b,v28.8b
WORD $0x4e3ce372 // pmull2 v18.8h,v27.16b,v28.16b
#define GALOIS_MUL(MUL_LO, MUL_HI, OUT1, OUT2, TMP1, TMP2) \
\ // Mul low part and mul high part
VTBL V0.B16, [MUL_LO.B16], OUT1.B16 \
VTBL V10.B16, [MUL_HI.B16], OUT2.B16 \
VTBL V1.B16, [MUL_LO.B16], TMP1.B16 \
VTBL V11.B16, [MUL_HI.B16], TMP2.B16 \
\
\ // Combine results
VEOR OUT2.B16, OUT1.B16, OUT1.B16 \
VEOR TMP2.B16, TMP1.B16, OUT2.B16
// first reduction
#define FIRST_REDUCTION \
WORD $0x0f088402 \ // shrn v2.8b, v0.8h, #8
WORD $0x0f0884c8 \ // shrn v8.8b, v6.8h, #8
WORD $0x0f08858e \ // shrn v14.8b, v12.8h, #8
WORD $0x0f088654 \ // shrn v20.8b, v18.8h, #8
WORD $0x0e22e3c3 \ // pmull v3.8h,v30.8b,v2.8b
WORD $0x0e28e3c9 \ // pmull v9.8h,v30.8b,v8.8b
WORD $0x0e2ee3cf \ // pmull v15.8h,v30.8b,v14.8b
WORD $0x0e34e3d5 \ // pmull v21.8h,v30.8b,v20.8b
WORD $0x6e201c60 \ // eor v0.16b,v3.16b,v0.16b
WORD $0x6e261d26 \ // eor v6.16b,v9.16b,v6.16b
WORD $0x6e2c1dec \ // eor v12.16b,v15.16b,v12.16b
WORD $0x6e321eb2 // eor v18.16b,v21.16b,v18.16b
// second reduction
#define SECOND_REDUCTION \
WORD $0x0f088404 \ // shrn v4.8b, v0.8h, #8
WORD $0x0f0884ca \ // shrn v10.8b, v6.8h, #8
WORD $0x0f088590 \ // shrn v16.8b, v12.8h, #8
WORD $0x0f088656 \ // shrn v22.8b, v18.8h, #8
WORD $0x6e241c44 \ // eor v4.16b,v2.16b,v4.16b
WORD $0x6e2a1d0a \ // eor v10.16b,v8.16b,v10.16b
WORD $0x6e301dd0 \ // eor v16.16b,v14.16b,v16.16b
WORD $0x6e361e96 \ // eor v22.16b,v20.16b,v22.16b
WORD $0x0e24e3c5 \ // pmull v5.8h,v30.8b,v4.8b
WORD $0x0e2ae3cb \ // pmull v11.8h,v30.8b,v10.8b
WORD $0x0e30e3d1 \ // pmull v17.8h,v30.8b,v16.8b
WORD $0x0e36e3d7 \ // pmull v23.8h,v30.8b,v22.8b
WORD $0x6e201ca0 \ // eor v0.16b,v5.16b,v0.16b
WORD $0x6e261d61 \ // eor v1.16b,v11.16b,v6.16b
WORD $0x6e2c1e22 \ // eor v2.16b,v17.16b,v12.16b
WORD $0x6e321ee3 // eor v3.16b,v23.16b,v18.16b
// func galMulNEON(c uint64, in, out []byte)
// func galMulNEON(low, high, in, out []byte)
TEXT ·galMulNEON(SB), 7, $0
MOVD c+0(FP), R0
MOVD in_base+8(FP), R1
MOVD in_len+16(FP), R2 // length of message
MOVD out_base+32(FP), R5
MOVD in_base+48(FP), R1
MOVD in_len+56(FP), R2 // length of message
MOVD out_base+72(FP), R5
SUBS $32, R2
BMI complete
// Load constants table pointer
MOVD $·constants(SB), R3
MOVD low+0(FP), R10 // R10: &low
MOVD high+24(FP), R11 // R11: &high
VLD1 (R10), [V6.B16]
VLD1 (R11), [V7.B16]
// and load constants into v30 & v31
WORD $0x4c40a07e // ld1 {v30.16b-v31.16b}, [x3]
WORD $0x4e010c1c // dup v28.16b, w0
//
// Use an extra instruction below since `VDUP R3, V8.B16` generates assembler error
// WORD $0x4e010c68 // dup v8.16b, w3
//
MOVD $0x0f, R3
VMOV R3, V8.B[0]
VDUP V8.B[0], V8.B16
loop:
// Main loop
WORD $0x4cdfa83a // ld1 {v26.4s-v27.4s}, [x1], #32
POLYNOMIAL_MULTIPLICATION
FIRST_REDUCTION
SECOND_REDUCTION
// combine results
WORD $0x4e1f2000 // tbl v0.16b,{v0.16b,v1.16b},v31.16b
WORD $0x4e1f2041 // tbl v1.16b,{v2.16b,v3.16b},v31.16b
LOAD(V0, V1, V10, V11)
GALOIS_MUL(V6, V7, V4, V5, V14, V15)
// Store result
WORD $0x4c9faca0 // st1 {v0.2d-v1.2d}, [x5], #32
VST1.P [V4.D2, V5.D2], 32(R5)
SUBS $32, R2
BPL loop
@@ -87,42 +58,39 @@ loop:
complete:
RET
// func galMulXorNEON(c uint64, in, out []byte)
// func galMulXorNEON(low, high, in, out []byte)
TEXT ·galMulXorNEON(SB), 7, $0
MOVD c+0(FP), R0
MOVD in_base+8(FP), R1
MOVD in_len+16(FP), R2 // length of message
MOVD out_base+32(FP), R5
MOVD in_base+48(FP), R1
MOVD in_len+56(FP), R2 // length of message
MOVD out_base+72(FP), R5
SUBS $32, R2
BMI completeXor
// Load constants table pointer
MOVD $·constants(SB), R3
MOVD low+0(FP), R10 // R10: &low
MOVD high+24(FP), R11 // R11: &high
VLD1 (R10), [V6.B16]
VLD1 (R11), [V7.B16]
// and load constants into v30 & v31
WORD $0x4c40a07e // ld1 {v30.16b-v31.16b}, [x3]
WORD $0x4e010c1c // dup v28.16b, w0
//
// Use an extra instruction below since `VDUP R3, V8.B16` generates assembler error
// WORD $0x4e010c68 // dup v8.16b, w3
//
MOVD $0x0f, R3
VMOV R3, V8.B[0]
VDUP V8.B[0], V8.B16
loopXor:
// Main loop
WORD $0x4cdfa83a // ld1 {v26.4s-v27.4s}, [x1], #32
WORD $0x4c40a8b8 // ld1 {v24.4s-v25.4s}, [x5]
VLD1 (R5), [V20.B16, V21.B16]
POLYNOMIAL_MULTIPLICATION
LOAD(V0, V1, V10, V11)
GALOIS_MUL(V6, V7, V4, V5, V14, V15)
FIRST_REDUCTION
VEOR V20.B16, V4.B16, V4.B16
VEOR V21.B16, V5.B16, V5.B16
SECOND_REDUCTION
// combine results
WORD $0x4e1f2000 // tbl v0.16b,{v0.16b,v1.16b},v31.16b
WORD $0x4e1f2041 // tbl v1.16b,{v2.16b,v3.16b},v31.16b
// Xor result and store
WORD $0x6e381c00 // eor v0.16b,v0.16b,v24.16b
WORD $0x6e391c21 // eor v1.16b,v1.16b,v25.16b
WORD $0x4c9faca0 // st1 {v0.2d-v1.2d}, [x5], #32
// Store result
VST1.P [V4.D2, V5.D2], 32(R5)
SUBS $32, R2
BPL loopXor
@@ -130,12 +98,28 @@ loopXor:
completeXor:
RET
// Constants table
// generating polynomial is 29 (= 0x1d)
DATA ·constants+0x0(SB)/8, $0x1d1d1d1d1d1d1d1d
DATA ·constants+0x8(SB)/8, $0x1d1d1d1d1d1d1d1d
// constant for TBL instruction
DATA ·constants+0x10(SB)/8, $0x0e0c0a0806040200
DATA ·constants+0x18(SB)/8, $0x1e1c1a1816141210
// func galXorNEON(in, out []byte)
TEXT ·galXorNEON(SB), 7, $0
MOVD in_base+0(FP), R1
MOVD in_len+8(FP), R2 // length of message
MOVD out_base+24(FP), R5
SUBS $32, R2
BMI completeXor
loopXor:
// Main loop
VLD1.P 32(R1), [V0.B16, V1.B16]
VLD1 (R5), [V20.B16, V21.B16]
VEOR V20.B16, V0.B16, V4.B16
VEOR V21.B16, V1.B16, V5.B16
// Store result
VST1.P [V4.D2, V5.D2], 32(R5)
SUBS $32, R2
BPL loopXor
completeXor:
RET
GLOBL ·constants(SB), 8, $32
+15 -5
View File
@@ -7,28 +7,38 @@
package reedsolomon
func galMulSlice(c byte, in, out []byte, o *options) {
mt := mulTable[c][:256]
out = out[:len(in)]
if c == 1 {
copy(out, in)
return
}
mt := mulTable[c][:256]
for n, input := range in {
out[n] = mt[input]
}
}
func galMulSliceXor(c byte, in, out []byte, o *options) {
mt := mulTable[c][:256]
out = out[:len(in)]
if c == 1 {
for n, input := range in {
out[n] ^= input
}
return
}
mt := mulTable[c][:256]
for n, input := range in {
out[n] ^= mt[input]
}
}
// slice galois add
func sliceXor(in, out []byte, sse2 bool) {
func sliceXor(in, out []byte, o *options) {
for n, input := range in {
out[n] ^= input
}
}
func (r reedSolomon) codeSomeShardsAvx512(matrixRows, inputs, outputs [][]byte, outputCount, byteCount int) {
panic("unreachable")
func init() {
defaultOptions.useAVX512 = false
}
+9 -4
View File
@@ -32,6 +32,10 @@ func galMulPpcXor(low, high, in, out []byte) {
*/
func galMulSlice(c byte, in, out []byte, o *options) {
if c == 1 {
copy(out, in)
return
}
done := (len(in) >> 4) << 4
if done > 0 {
galMulPpc(mulTableLow[c][:], mulTableHigh[c][:], in[:done], out)
@@ -46,6 +50,10 @@ func galMulSlice(c byte, in, out []byte, o *options) {
}
func galMulSliceXor(c byte, in, out []byte, o *options) {
if c == 1 {
sliceXor(in, out, o)
return
}
done := (len(in) >> 4) << 4
if done > 0 {
galMulPpcXor(mulTableLow[c][:], mulTableHigh[c][:], in[:done], out)
@@ -60,11 +68,8 @@ func galMulSliceXor(c byte, in, out []byte, o *options) {
}
// slice galois add
func sliceXor(in, out []byte, sse2 bool) {
func sliceXor(in, out []byte, o *options) {
for n, input := range in {
out[n] ^= input
}
}
func (r reedSolomon) codeSomeShardsAvx512(matrixRows, inputs, outputs [][]byte, outputCount, byteCount int) {
}
+56 -58
View File
@@ -32,89 +32,87 @@
#define FLIP VS41
#define FLIP_ V9
// func galMulPpc(low, high, in, out []byte)
TEXT ·galMulPpc(SB), NOFRAME|NOSPLIT, $0-96
MOVD low+0(FP), LOW
MOVD high+24(FP), HIGH
MOVD in+48(FP), IN
MOVD in_len+56(FP), LEN
MOVD out+72(FP), OUT
MOVD low+0(FP), LOW
MOVD high+24(FP), HIGH
MOVD in+48(FP), IN
MOVD in_len+56(FP), LEN
MOVD out+72(FP), OUT
MOVD $16, OFFSET1
MOVD $32, OFFSET2
MOVD $16, OFFSET1
MOVD $32, OFFSET2
MOVD $·constants(SB), CONSTANTS
LXVD2X (CONSTANTS)(R0), ROTATE
LXVD2X (CONSTANTS)(OFFSET1), MASK
LXVD2X (CONSTANTS)(OFFSET2), FLIP
MOVD $·constants(SB), CONSTANTS
LXVD2X (CONSTANTS)(R0), ROTATE
LXVD2X (CONSTANTS)(OFFSET1), MASK
LXVD2X (CONSTANTS)(OFFSET2), FLIP
LXVD2X (LOW)(R0), X6
LXVD2X (HIGH)(R0), X7
VPERM X6_, V31, FLIP_, X6_
VPERM X7_, V31, FLIP_, X7_
LXVD2X (LOW)(R0), X6
LXVD2X (HIGH)(R0), X7
VPERM X6_, V31, FLIP_, X6_
VPERM X7_, V31, FLIP_, X7_
MOVD $0, OFFSET
MOVD $0, OFFSET
loop:
LXVD2X (IN)(OFFSET), MSG
LXVD2X (IN)(OFFSET), MSG
VSRB MSG_, ROTATE_, MSG_HI_
VAND MSG_, MASK_, MSG_
VPERM X6_, V31, MSG_, MSG_
VPERM X7_, V31, MSG_HI_, MSG_HI_
VSRB MSG_, ROTATE_, MSG_HI_
VAND MSG_, MASK_, MSG_
VPERM X6_, V31, MSG_, MSG_
VPERM X7_, V31, MSG_HI_, MSG_HI_
VXOR MSG_, MSG_HI_, MSG_
VXOR MSG_, MSG_HI_, MSG_
STXVD2X MSG, (OUT)(OFFSET)
ADD $16, OFFSET, OFFSET
CMP LEN, OFFSET
BGT loop
RET
STXVD2X MSG, (OUT)(OFFSET)
ADD $16, OFFSET, OFFSET
CMP LEN, OFFSET
BGT loop
RET
// func galMulPpcXorlow, high, in, out []byte)
TEXT ·galMulPpcXor(SB), NOFRAME|NOSPLIT, $0-96
MOVD low+0(FP), LOW
MOVD high+24(FP), HIGH
MOVD in+48(FP), IN
MOVD in_len+56(FP), LEN
MOVD out+72(FP), OUT
MOVD low+0(FP), LOW
MOVD high+24(FP), HIGH
MOVD in+48(FP), IN
MOVD in_len+56(FP), LEN
MOVD out+72(FP), OUT
MOVD $16, OFFSET1
MOVD $32, OFFSET2
MOVD $16, OFFSET1
MOVD $32, OFFSET2
MOVD $·constants(SB), CONSTANTS
LXVD2X (CONSTANTS)(R0), ROTATE
LXVD2X (CONSTANTS)(OFFSET1), MASK
LXVD2X (CONSTANTS)(OFFSET2), FLIP
MOVD $·constants(SB), CONSTANTS
LXVD2X (CONSTANTS)(R0), ROTATE
LXVD2X (CONSTANTS)(OFFSET1), MASK
LXVD2X (CONSTANTS)(OFFSET2), FLIP
LXVD2X (LOW)(R0), X6
LXVD2X (HIGH)(R0), X7
VPERM X6_, V31, FLIP_, X6_
VPERM X7_, V31, FLIP_, X7_
LXVD2X (LOW)(R0), X6
LXVD2X (HIGH)(R0), X7
VPERM X6_, V31, FLIP_, X6_
VPERM X7_, V31, FLIP_, X7_
MOVD $0, OFFSET
MOVD $0, OFFSET
loopXor:
LXVD2X (IN)(OFFSET), MSG
LXVD2X (OUT)(OFFSET), RESULT
LXVD2X (IN)(OFFSET), MSG
LXVD2X (OUT)(OFFSET), RESULT
VSRB MSG_, ROTATE_, MSG_HI_
VAND MSG_, MASK_, MSG_
VPERM X6_, V31, MSG_, MSG_
VPERM X7_, V31, MSG_HI_, MSG_HI_
VSRB MSG_, ROTATE_, MSG_HI_
VAND MSG_, MASK_, MSG_
VPERM X6_, V31, MSG_, MSG_
VPERM X7_, V31, MSG_HI_, MSG_HI_
VXOR MSG_, MSG_HI_, MSG_
VXOR MSG_, RESULT_, RESULT_
VXOR MSG_, MSG_HI_, MSG_
VXOR MSG_, RESULT_, RESULT_
STXVD2X RESULT, (OUT)(OFFSET)
STXVD2X RESULT, (OUT)(OFFSET)
ADD $16, OFFSET, OFFSET
CMP LEN, OFFSET
BGT loopXor
RET
ADD $16, OFFSET, OFFSET
CMP LEN, OFFSET
BGT loopXor
RET
DATA ·constants+0x0(SB)/8, $0x0404040404040404
DATA ·constants+0x8(SB)/8, $0x0404040404040404
+67 -10
View File
@@ -10,28 +10,38 @@ import (
type Option func(*options)
type options struct {
maxGoroutines int
minSplitSize int
maxGoroutines int
minSplitSize int
shardSize int
perRound int
useAVX512, useAVX2, useSSSE3, useSSE2 bool
usePAR1Matrix bool
useCauchy bool
shardSize int
fastOneParity bool
// stream options
concReads bool
concWrites bool
streamBS int
}
var defaultOptions = options{
maxGoroutines: 384,
minSplitSize: 1024,
minSplitSize: -1,
fastOneParity: false,
// Detect CPU capabilities.
useSSSE3: cpuid.CPU.SSSE3(),
useSSE2: cpuid.CPU.SSE2(),
useAVX2: cpuid.CPU.AVX2(),
useAVX512: cpuid.CPU.AVX512F() && cpuid.CPU.AVX512BW(),
}
func init() {
if runtime.GOMAXPROCS(0) <= 1 {
defaultOptions.maxGoroutines = 1
}
// Detect CPU capabilities.
defaultOptions.useSSSE3 = cpuid.CPU.SSSE3()
defaultOptions.useSSE2 = cpuid.CPU.SSE2()
defaultOptions.useAVX2 = cpuid.CPU.AVX2()
defaultOptions.useAVX512 = cpuid.CPU.AVX512F() && cpuid.CPU.AVX512BW() && amd64
}
// WithMaxGoroutines is the maximum number of goroutines number for encoding & decoding.
@@ -61,6 +71,7 @@ func WithAutoGoroutines(shardSize int) Option {
}
// WithMinSplitSize is the minimum encoding size in bytes per goroutine.
// By default this parameter is determined by CPU cache characteristics.
// See WithMaxGoroutines on how jobs are split.
// If n <= 0, it is ignored.
func WithMinSplitSize(n int) Option {
@@ -71,7 +82,44 @@ func WithMinSplitSize(n int) Option {
}
}
func withSSE3(enabled bool) Option {
// WithConcurrentStreams will enable concurrent reads and writes on the streams.
// Default: Disabled, meaning only one stream will be read/written at the time.
// Ignored if not used on a stream input.
func WithConcurrentStreams(enabled bool) Option {
return func(o *options) {
o.concReads, o.concWrites = enabled, enabled
}
}
// WithConcurrentStreamReads will enable concurrent reads from the input streams.
// Default: Disabled, meaning only one stream will be read at the time.
// Ignored if not used on a stream input.
func WithConcurrentStreamReads(enabled bool) Option {
return func(o *options) {
o.concReads = enabled
}
}
// WithConcurrentStreamWrites will enable concurrent writes to the the output streams.
// Default: Disabled, meaning only one stream will be written at the time.
// Ignored if not used on a stream input.
func WithConcurrentStreamWrites(enabled bool) Option {
return func(o *options) {
o.concWrites = enabled
}
}
// WithStreamBlockSize allows to set a custom block size per round of reads/writes.
// If not set, any shard size set with WithAutoGoroutines will be used.
// If WithAutoGoroutines is also unset, 4MB will be used.
// Ignored if not used on stream.
func WithStreamBlockSize(n int) Option {
return func(o *options) {
o.streamBS = n
}
}
func withSSSE3(enabled bool) Option {
return func(o *options) {
o.useSSSE3 = enabled
}
@@ -116,3 +164,12 @@ func WithCauchyMatrix() Option {
o.usePAR1Matrix = false
}
}
// WithFastOneParityMatrix will switch the matrix to a simple xor
// if there is only one parity shard.
// The PAR1 matrix already has this property so it has little effect there.
func WithFastOneParityMatrix() Option {
return func(o *options) {
o.fastOneParity = true
}
}
+169 -58
View File
@@ -113,6 +113,7 @@ type reedSolomon struct {
tree inversionTree
parity [][]byte
o options
mPool sync.Pool
}
// ErrInvShardNum will be returned by New, if you attempt to create
@@ -206,6 +207,32 @@ func buildMatrixCauchy(dataShards, totalShards int) (matrix, error) {
return result, nil
}
// buildXorMatrix can be used to build a matrix with pure XOR
// operations if there is only one parity shard.
func buildXorMatrix(dataShards, totalShards int) (matrix, error) {
if dataShards+1 != totalShards {
return nil, errors.New("internal error")
}
result, err := newMatrix(totalShards, dataShards)
if err != nil {
return nil, err
}
for r, row := range result {
// The top portion of the matrix is the identity
// matrix.
if r < dataShards {
result[r][r] = 1
} else {
// Set all values to 1 (XOR)
for c := range row {
result[r][c] = 1
}
}
}
return result, nil
}
// New creates a new encoder and initializes it to
// the number of data shards and parity shards that
// you want to use. You can reuse this encoder.
@@ -232,6 +259,8 @@ func New(dataShards, parityShards int, opts ...Option) (Encoder, error) {
var err error
switch {
case r.o.fastOneParity && parityShards == 1:
r.m, err = buildXorMatrix(dataShards, r.Shards)
case r.o.useCauchy:
r.m, err = buildMatrixCauchy(dataShards, r.Shards)
case r.o.usePAR1Matrix:
@@ -242,32 +271,61 @@ func New(dataShards, parityShards int, opts ...Option) (Encoder, error) {
if err != nil {
return nil, err
}
if r.o.shardSize > 0 {
cacheSize := cpuid.CPU.Cache.L2
// Calculate what we want per round
r.o.perRound = cpuid.CPU.Cache.L2
if r.o.perRound <= 0 {
// Set to 128K if undetectable.
r.o.perRound = 128 << 10
}
if cpuid.CPU.ThreadsPerCore > 1 && r.o.maxGoroutines > cpuid.CPU.PhysicalCores {
// If multiple threads per core, make sure they don't contend for cache.
r.o.perRound /= cpuid.CPU.ThreadsPerCore
}
// 1 input + parity must fit in cache, and we add one more to be safer.
r.o.perRound = r.o.perRound / (1 + parityShards)
// Align to 64 bytes.
r.o.perRound = ((r.o.perRound + 63) / 64) * 64
if r.o.minSplitSize <= 0 {
// Set minsplit as high as we can, but still have parity in L1.
cacheSize := cpuid.CPU.Cache.L1D
if cacheSize <= 0 {
// Set to 128K if undetectable.
cacheSize = 128 << 10
}
p := runtime.NumCPU()
// 1 input + parity must fit in cache, and we add one more to be safer.
shards := 1 + parityShards
g := (r.o.shardSize * shards) / (cacheSize - (cacheSize >> 4))
if cpuid.CPU.ThreadsPerCore > 1 {
// If multiple threads per core, make sure they don't contend for cache.
g *= cpuid.CPU.ThreadsPerCore
}
g *= 2
if g < p {
g = p
cacheSize = 32 << 10
}
// Have g be multiple of p
g += p - 1
g -= g % p
r.o.minSplitSize = cacheSize / (parityShards + 1)
// Min 1K
if r.o.minSplitSize < 1024 {
r.o.minSplitSize = 1024
}
}
r.o.maxGoroutines = g
if r.o.perRound < r.o.minSplitSize {
r.o.perRound = r.o.minSplitSize
}
if r.o.shardSize > 0 {
p := runtime.GOMAXPROCS(0)
if p == 1 || r.o.shardSize <= r.o.minSplitSize*2 {
// Not worth it.
r.o.maxGoroutines = 1
} else {
g := r.o.shardSize / r.o.perRound
// Overprovision by a factor of 2.
if g < p*2 && r.o.perRound > r.o.minSplitSize*2 {
g = p * 2
r.o.perRound /= 2
}
// Have g be multiple of p
g += p - 1
g -= g % p
r.o.maxGoroutines = g
}
}
// Inverted matrices are cached in a tree keyed by the indices
@@ -282,6 +340,11 @@ func New(dataShards, parityShards int, opts ...Option) (Encoder, error) {
r.parity[i] = r.m[dataShards+i]
}
if avx2CodeGen && r.o.useAVX2 {
r.mPool.New = func() interface{} {
return make([]byte, r.Shards*2*32)
}
}
return &r, err
}
@@ -296,7 +359,7 @@ var ErrTooFewShards = errors.New("too few shards given")
// Each shard is a byte array, and they must all be the same size.
// The parity shards will always be overwritten and the data shards
// will remain the same.
func (r reedSolomon) Encode(shards [][]byte) error {
func (r *reedSolomon) Encode(shards [][]byte) error {
if len(shards) != r.Shards {
return ErrTooFewShards
}
@@ -317,7 +380,7 @@ func (r reedSolomon) Encode(shards [][]byte) error {
// ErrInvalidInput is returned if invalid input parameter of Update.
var ErrInvalidInput = errors.New("invalid input")
func (r reedSolomon) Update(shards [][]byte, newDatashards [][]byte) error {
func (r *reedSolomon) Update(shards [][]byte, newDatashards [][]byte) error {
if len(shards) != r.Shards {
return ErrTooFewShards
}
@@ -357,7 +420,7 @@ func (r reedSolomon) Update(shards [][]byte, newDatashards [][]byte) error {
return nil
}
func (r reedSolomon) updateParityShards(matrixRows, oldinputs, newinputs, outputs [][]byte, outputCount, byteCount int) {
func (r *reedSolomon) updateParityShards(matrixRows, oldinputs, newinputs, outputs [][]byte, outputCount, byteCount int) {
if r.o.maxGoroutines > 1 && byteCount > r.o.minSplitSize {
r.updateParityShardsP(matrixRows, oldinputs, newinputs, outputs, outputCount, byteCount)
return
@@ -370,14 +433,14 @@ func (r reedSolomon) updateParityShards(matrixRows, oldinputs, newinputs, output
}
oldin := oldinputs[c]
// oldinputs data will be change
sliceXor(in, oldin, r.o.useSSE2)
sliceXor(in, oldin, &r.o)
for iRow := 0; iRow < outputCount; iRow++ {
galMulSliceXor(matrixRows[iRow][c], oldin, outputs[iRow], &r.o)
}
}
}
func (r reedSolomon) updateParityShardsP(matrixRows, oldinputs, newinputs, outputs [][]byte, outputCount, byteCount int) {
func (r *reedSolomon) updateParityShardsP(matrixRows, oldinputs, newinputs, outputs [][]byte, outputCount, byteCount int) {
var wg sync.WaitGroup
do := byteCount / r.o.maxGoroutines
if do < r.o.minSplitSize {
@@ -397,7 +460,7 @@ func (r reedSolomon) updateParityShardsP(matrixRows, oldinputs, newinputs, outpu
}
oldin := oldinputs[c]
// oldinputs data will be change
sliceXor(in[start:stop], oldin[start:stop], r.o.useSSE2)
sliceXor(in[start:stop], oldin[start:stop], &r.o)
for iRow := 0; iRow < outputCount; iRow++ {
galMulSliceXor(matrixRows[iRow][c], oldin[start:stop], outputs[iRow][start:stop], &r.o)
}
@@ -411,7 +474,7 @@ func (r reedSolomon) updateParityShardsP(matrixRows, oldinputs, newinputs, outpu
// Verify returns true if the parity shards contain the right data.
// The data is the same format as Encode. No data is modified.
func (r reedSolomon) Verify(shards [][]byte) (bool, error) {
func (r *reedSolomon) Verify(shards [][]byte) (bool, error) {
if len(shards) != r.Shards {
return false, ErrTooFewShards
}
@@ -436,52 +499,100 @@ func (r reedSolomon) Verify(shards [][]byte) (bool, error) {
// The number of outputs computed, and the
// number of matrix rows used, is determined by
// outputCount, which is the number of outputs to compute.
func (r reedSolomon) codeSomeShards(matrixRows, inputs, outputs [][]byte, outputCount, byteCount int) {
if r.o.useAVX512 && len(inputs) >= 4 && len(outputs) >= 2 {
func (r *reedSolomon) codeSomeShards(matrixRows, inputs, outputs [][]byte, outputCount, byteCount int) {
if len(outputs) == 0 {
return
}
switch {
case r.o.useAVX512 && r.o.maxGoroutines > 1 && byteCount > r.o.minSplitSize && len(inputs) >= 4 && len(outputs) >= 2:
r.codeSomeShardsAvx512P(matrixRows, inputs, outputs, outputCount, byteCount)
return
case r.o.useAVX512 && len(inputs) >= 4 && len(outputs) >= 2:
r.codeSomeShardsAvx512(matrixRows, inputs, outputs, outputCount, byteCount)
return
} else if r.o.maxGoroutines > 1 && byteCount > r.o.minSplitSize {
case r.o.maxGoroutines > 1 && byteCount > r.o.minSplitSize:
r.codeSomeShardsP(matrixRows, inputs, outputs, outputCount, byteCount)
return
}
for c := 0; c < r.DataShards; c++ {
in := inputs[c]
for iRow := 0; iRow < outputCount; iRow++ {
if c == 0 {
galMulSlice(matrixRows[iRow][c], in, outputs[iRow], &r.o)
} else {
galMulSliceXor(matrixRows[iRow][c], in, outputs[iRow], &r.o)
// Process using no goroutines
start, end := 0, r.o.perRound
if end > len(inputs[0]) {
end = len(inputs[0])
}
if avx2CodeGen && r.o.useAVX2 && byteCount >= 32 && len(inputs) > 1 && len(outputs) > 1 && len(inputs) <= maxAvx2Inputs && len(outputs) <= maxAvx2Outputs {
m := genAvx2Matrix(matrixRows, len(inputs), len(outputs), r.mPool.Get().([]byte))
start += galMulSlicesAvx2(m, inputs, outputs, 0, byteCount)
r.mPool.Put(m)
end = len(inputs[0])
}
for start < len(inputs[0]) {
for c := 0; c < r.DataShards; c++ {
in := inputs[c][start:end]
for iRow := 0; iRow < outputCount; iRow++ {
if c == 0 {
galMulSlice(matrixRows[iRow][c], in, outputs[iRow][start:end], &r.o)
} else {
galMulSliceXor(matrixRows[iRow][c], in, outputs[iRow][start:end], &r.o)
}
}
}
start = end
end += r.o.perRound
if end > len(inputs[0]) {
end = len(inputs[0])
}
}
}
// Perform the same as codeSomeShards, but split the workload into
// several goroutines.
func (r reedSolomon) codeSomeShardsP(matrixRows, inputs, outputs [][]byte, outputCount, byteCount int) {
func (r *reedSolomon) codeSomeShardsP(matrixRows, inputs, outputs [][]byte, outputCount, byteCount int) {
var wg sync.WaitGroup
do := byteCount / r.o.maxGoroutines
if do < r.o.minSplitSize {
do = r.o.minSplitSize
}
// Make sizes divisible by 32
do = (do + 31) & (^31)
// Make sizes divisible by 64
do = (do + 63) & (^63)
start := 0
var avx2Matrix []byte
if avx2CodeGen && r.o.useAVX2 && byteCount >= 32 && len(inputs) > 1 && len(outputs) > 1 && len(inputs) <= maxAvx2Inputs && len(outputs) <= maxAvx2Outputs {
avx2Matrix = genAvx2Matrix(matrixRows, len(inputs), len(outputs), r.mPool.Get().([]byte))
defer r.mPool.Put(avx2Matrix)
}
for start < byteCount {
if start+do > byteCount {
do = byteCount - start
}
wg.Add(1)
go func(start, stop int) {
for c := 0; c < r.DataShards; c++ {
in := inputs[c][start:stop]
for iRow := 0; iRow < outputCount; iRow++ {
if c == 0 {
galMulSlice(matrixRows[iRow][c], in, outputs[iRow][start:stop], &r.o)
} else {
galMulSliceXor(matrixRows[iRow][c], in, outputs[iRow][start:stop], &r.o)
if avx2CodeGen && r.o.useAVX2 && stop-start >= 32 && len(inputs) > 1 && len(outputs) > 1 && len(inputs) <= maxAvx2Inputs && len(outputs) <= maxAvx2Outputs {
start += galMulSlicesAvx2(avx2Matrix, inputs, outputs, start, stop)
}
lstart, lstop := start, start+r.o.perRound
if lstop > stop {
lstop = stop
}
for lstart < stop {
for c := 0; c < r.DataShards; c++ {
in := inputs[c][lstart:lstop]
for iRow := 0; iRow < outputCount; iRow++ {
if c == 0 {
galMulSlice(matrixRows[iRow][c], in, outputs[iRow][lstart:lstop], &r.o)
} else {
galMulSliceXor(matrixRows[iRow][c], in, outputs[iRow][lstart:lstop], &r.o)
}
}
}
lstart = lstop
lstop += r.o.perRound
if lstop > stop {
lstop = stop
}
}
wg.Done()
}(start, start+do)
@@ -493,7 +604,7 @@ func (r reedSolomon) codeSomeShardsP(matrixRows, inputs, outputs [][]byte, outpu
// checkSomeShards is mostly the same as codeSomeShards,
// except this will check values and return
// as soon as a difference is found.
func (r reedSolomon) checkSomeShards(matrixRows, inputs, toCheck [][]byte, outputCount, byteCount int) bool {
func (r *reedSolomon) checkSomeShards(matrixRows, inputs, toCheck [][]byte, outputCount, byteCount int) bool {
if r.o.maxGoroutines > 1 && byteCount > r.o.minSplitSize {
return r.checkSomeShardsP(matrixRows, inputs, toCheck, outputCount, byteCount)
}
@@ -516,7 +627,7 @@ func (r reedSolomon) checkSomeShards(matrixRows, inputs, toCheck [][]byte, outpu
return true
}
func (r reedSolomon) checkSomeShardsP(matrixRows, inputs, toCheck [][]byte, outputCount, byteCount int) bool {
func (r *reedSolomon) checkSomeShardsP(matrixRows, inputs, toCheck [][]byte, outputCount, byteCount int) bool {
same := true
var mu sync.RWMutex // For above
@@ -525,8 +636,8 @@ func (r reedSolomon) checkSomeShardsP(matrixRows, inputs, toCheck [][]byte, outp
if do < r.o.minSplitSize {
do = r.o.minSplitSize
}
// Make sizes divisible by 32
do = (do + 31) & (^31)
// Make sizes divisible by 64
do = (do + 63) & (^63)
start := 0
for start < byteCount {
if start+do > byteCount {
@@ -620,7 +731,7 @@ func shardSize(shards [][]byte) int {
//
// The reconstructed shard set is complete, but integrity is not verified.
// Use the Verify function to check if data set is ok.
func (r reedSolomon) Reconstruct(shards [][]byte) error {
func (r *reedSolomon) Reconstruct(shards [][]byte) error {
return r.reconstruct(shards, false)
}
@@ -639,7 +750,7 @@ func (r reedSolomon) Reconstruct(shards [][]byte) error {
//
// As the reconstructed shard set may contain missing parity shards,
// calling the Verify function is likely to fail.
func (r reedSolomon) ReconstructData(shards [][]byte) error {
func (r *reedSolomon) ReconstructData(shards [][]byte) error {
return r.reconstruct(shards, true)
}
@@ -651,7 +762,7 @@ func (r reedSolomon) ReconstructData(shards [][]byte) error {
//
// If there are too few shards to reconstruct the missing
// ones, ErrTooFewShards will be returned.
func (r reedSolomon) reconstruct(shards [][]byte, dataOnly bool) error {
func (r *reedSolomon) reconstruct(shards [][]byte, dataOnly bool) error {
if len(shards) != r.Shards {
return ErrTooFewShards
}
@@ -810,7 +921,7 @@ var ErrShortData = errors.New("not enough data to fill the number of requested s
//
// The data will not be copied, except for the last shard, so you
// should not modify the data of the input slice afterwards.
func (r reedSolomon) Split(data []byte) ([][]byte, error) {
func (r *reedSolomon) Split(data []byte) ([][]byte, error) {
if len(data) == 0 {
return nil, ErrShortData
}
@@ -859,7 +970,7 @@ var ErrReconstructRequired = errors.New("reconstruction required as one or more
// If there are to few shards given, ErrTooFewShards will be returned.
// If the total data size is less than outSize, ErrShortData will be returned.
// If one or more required data shards are nil, ErrReconstructRequired will be returned.
func (r reedSolomon) Join(dst io.Writer, shards [][]byte, outSize int) error {
func (r *reedSolomon) Join(dst io.Writer, shards [][]byte, outSize int) error {
// Do we have enough shards?
if len(shards) < r.DataShards {
return ErrTooFewShards
+55 -34
View File
@@ -131,12 +131,15 @@ func (s StreamWriteError) String() string {
// distribution of datashards and parity shards.
// Construct if using NewStream()
type rsStream struct {
r *reedSolomon
bs int // Block size
r *reedSolomon
o options
// Shard reader
readShards func(dst [][]byte, in []io.Reader) error
// Shard writer
writeShards func(out []io.Writer, in [][]byte) error
blockPool sync.Pool
}
// NewStream creates a new encoder and initializes it to
@@ -144,14 +147,43 @@ type rsStream struct {
// you want to use. You can reuse this encoder.
// Note that the maximum number of data shards is 256.
func NewStream(dataShards, parityShards int, o ...Option) (StreamEncoder, error) {
r := rsStream{o: defaultOptions}
for _, opt := range o {
opt(&r.o)
}
// Override block size if shard size is set.
if r.o.streamBS == 0 && r.o.shardSize > 0 {
r.o.streamBS = r.o.shardSize
}
if r.o.streamBS <= 0 {
r.o.streamBS = 4 << 20
}
if r.o.shardSize == 0 && r.o.maxGoroutines == defaultOptions.maxGoroutines {
o = append(o, WithAutoGoroutines(r.o.streamBS))
}
enc, err := New(dataShards, parityShards, o...)
if err != nil {
return nil, err
}
rs := enc.(*reedSolomon)
r := rsStream{r: rs, bs: 4 << 20}
r.r = enc.(*reedSolomon)
r.blockPool.New = func() interface{} {
out := make([][]byte, dataShards+parityShards)
for i := range out {
out[i] = make([]byte, r.o.streamBS)
}
return out
}
r.readShards = readShards
r.writeShards = writeShards
if r.o.concReads {
r.readShards = cReadShards
}
if r.o.concWrites {
r.writeShards = cWriteShards
}
return &r, err
}
@@ -160,27 +192,13 @@ func NewStream(dataShards, parityShards int, o ...Option) (StreamEncoder, error)
//
// This functions as 'NewStream', but allows you to enable CONCURRENT reads and writes.
func NewStreamC(dataShards, parityShards int, conReads, conWrites bool, o ...Option) (StreamEncoder, error) {
enc, err := New(dataShards, parityShards, o...)
if err != nil {
return nil, err
}
rs := enc.(*reedSolomon)
r := rsStream{r: rs, bs: 4 << 20}
r.readShards = readShards
r.writeShards = writeShards
if conReads {
r.readShards = cReadShards
}
if conWrites {
r.writeShards = cWriteShards
}
return &r, err
return NewStream(dataShards, parityShards, append(o, WithConcurrentStreamReads(conReads), WithConcurrentStreamWrites(conWrites))...)
}
func createSlice(n, length int) [][]byte {
out := make([][]byte, n)
func (r *rsStream) createSlice() [][]byte {
out := r.blockPool.Get().([][]byte)
for i := range out {
out[i] = make([]byte, length)
out[i] = out[i][:r.o.streamBS]
}
return out
}
@@ -200,7 +218,7 @@ func createSlice(n, length int) [][]byte {
// If a data stream returns an error, a StreamReadError type error
// will be returned. If a parity writer returns an error, a
// StreamWriteError will be returned.
func (r rsStream) Encode(data []io.Reader, parity []io.Writer) error {
func (r *rsStream) Encode(data []io.Reader, parity []io.Writer) error {
if len(data) != r.r.DataShards {
return ErrTooFewShards
}
@@ -209,7 +227,8 @@ func (r rsStream) Encode(data []io.Reader, parity []io.Writer) error {
return ErrTooFewShards
}
all := createSlice(r.r.Shards, r.bs)
all := r.createSlice()
defer r.blockPool.Put(all)
in := all[:r.r.DataShards]
out := all[r.r.DataShards:]
read := 0
@@ -242,11 +261,11 @@ func (r rsStream) Encode(data []io.Reader, parity []io.Writer) error {
// Trim the shards so they are all the same size
func trimShards(in [][]byte, size int) [][]byte {
for i := range in {
if in[i] != nil {
if len(in[i]) != 0 {
in[i] = in[i][0:size]
}
if len(in[i]) < size {
in[i] = nil
in[i] = in[i][:0]
}
}
return in
@@ -259,7 +278,7 @@ func readShards(dst [][]byte, in []io.Reader) error {
size := -1
for i := range in {
if in[i] == nil {
dst[i] = nil
dst[i] = dst[i][:0]
continue
}
n, err := io.ReadFull(in[i], dst[i])
@@ -323,7 +342,7 @@ func cReadShards(dst [][]byte, in []io.Reader) error {
res := make(chan readResult, len(in))
for i := range in {
if in[i] == nil {
dst[i] = nil
dst[i] = dst[i][:0]
wg.Done()
continue
}
@@ -405,13 +424,14 @@ func cWriteShards(out []io.Writer, in [][]byte) error {
// Each reader must supply the same number of bytes.
// If a shard stream returns an error, a StreamReadError type error
// will be returned.
func (r rsStream) Verify(shards []io.Reader) (bool, error) {
func (r *rsStream) Verify(shards []io.Reader) (bool, error) {
if len(shards) != r.r.Shards {
return false, ErrTooFewShards
}
read := 0
all := createSlice(r.r.Shards, r.bs)
all := r.createSlice()
defer r.blockPool.Put(all)
for {
err := r.readShards(all, shards)
if err == io.EOF {
@@ -451,7 +471,7 @@ var ErrReconstructMismatch = errors.New("valid shards and fill shards are mutual
// The reconstructed shard set is complete when explicitly asked for all missing shards.
// However its integrity is not automatically verified.
// Use the Verify function to check in case the data set is complete.
func (r rsStream) Reconstruct(valid []io.Reader, fill []io.Writer) error {
func (r *rsStream) Reconstruct(valid []io.Reader, fill []io.Writer) error {
if len(valid) != r.r.Shards {
return ErrTooFewShards
}
@@ -459,7 +479,8 @@ func (r rsStream) Reconstruct(valid []io.Reader, fill []io.Writer) error {
return ErrTooFewShards
}
all := createSlice(r.r.Shards, r.bs)
all := r.createSlice()
defer r.blockPool.Put(all)
reconDataOnly := true
for i := range valid {
if valid[i] != nil && fill[i] != nil {
@@ -507,7 +528,7 @@ func (r rsStream) Reconstruct(valid []io.Reader, fill []io.Writer) error {
// You must supply the exact output size you want.
// If there are to few shards given, ErrTooFewShards will be returned.
// If the total data size is less than outSize, ErrShortData will be returned.
func (r rsStream) Join(dst io.Writer, shards []io.Reader, outSize int64) error {
func (r *rsStream) Join(dst io.Writer, shards []io.Reader, outSize int64) error {
// Do we have enough shards?
if len(shards) < r.r.DataShards {
return ErrTooFewShards
@@ -546,7 +567,7 @@ func (r rsStream) Join(dst io.Writer, shards []io.Reader, outSize int64) error {
// You must supply the total size of your input.
// 'ErrShortData' will be returned if it is unable to retrieve the
// number of bytes indicated.
func (r rsStream) Split(data io.Reader, dst []io.Writer, size int64) error {
func (r *rsStream) Split(data io.Reader, dst []io.Writer, size int64) error {
if size == 0 {
return ErrShortData
}
+18 -1
View File
@@ -1,5 +1,22 @@
# cpu
internal/cpu(in Go standard lib) with AVX512 & Cache Size detection.
internal/cpu(in Go standard lib) with these detections:
>- AVX512
>
>- Cache Size
>
>- Invariant TSC
>
It also provides:
>- False sharing range, see `X86FalseSharingRange` for X86 platform.
>
>- TSC frequency
>
>- Name
>
>- Family & Model
# Acknowledgement
+29 -2
View File
@@ -12,12 +12,21 @@ var debugOptions bool
var X86 x86
// "Loads data or instructions from memory to the second-level cache.
// To use the streamer, organize the data or instructions in blocks of 128 bytes,
// aligned on 128 bytes."
// From <Intel® 64 and IA-32 architectures optimization reference manual>,
// in section 3.7.3 "Hardware Prefetching for Second-Level Cache"
//
// In practice, I have found use 128bytes can gain better performance than 64bytes (one cache line).
const X86FalseSharingRange = 128
// The booleans in x86 contain the correspondingly named cpuid feature bit.
// HasAVX and HasAVX2 are only set if the OS does support XMM and YMM registers
// in addition to the cpuid feature bit being set.
// The struct is padded to avoid false sharing.
type x86 struct {
_ [CacheLineSize]byte
_ [X86FalseSharingRange]byte
HasAES bool
HasADX bool
HasAVX bool
@@ -38,9 +47,27 @@ type x86 struct {
HasSSSE3 bool
HasSSE41 bool
HasSSE42 bool
// The invariant TSC will run at a constant rate in all ACPI P-, C-, and T-states.
// This is the architectural behavior moving forward. On processors with
// invariant TSC support, the OS may use the TSC for wall clock timer services (instead of ACPI or HPET timers).
HasInvariantTSC bool
Cache Cache
_ [CacheLineSize]byte
// TSCFrequency only meaningful when HasInvariantTSC == true.
// Unit: Hz.
//
// Warn:
// 1. If it's 0, means can't get it. Don't use it.
// 2. Don't use it if you want "100%" precise timestamp.
TSCFrequency uint64
Name string
Signature string // DisplayFamily_DisplayModel.
Family uint32 // CPU family number.
Model uint32 // CPU model number.
_ [X86FalseSharingRange]byte
}
// CPU Cache Size.
+154
View File
@@ -6,6 +6,11 @@
package cpu
import (
"fmt"
"strings"
)
const CacheLineSize = 64
// cpuid is implemented in cpu_x86.s.
@@ -40,6 +45,9 @@ const (
cpuid_AVX512DQ = 1 << 17
cpuid_AVX512BW = 1 << 30
cpuid_AVX512VL = 1 << 31
// edx bits
cpuid_Invariant_TSC = 1 << 8
)
func doinit() {
@@ -62,6 +70,7 @@ func doinit() {
{"avx512dq", &X86.HasAVX512DQ},
{"avx512bw", &X86.HasAVX512BW},
{"avx512vl", &X86.HasAVX512VL},
{"invariant_tsc", &X86.HasInvariantTSC},
// sse2 set as last element so it can easily be removed again. See code below.
{"sse2", &X86.HasSSE2},
@@ -120,12 +129,157 @@ func doinit() {
X86.HasADX = isSet(ebx7, cpuid_ADX)
X86.Cache = getCacheSize()
X86.HasInvariantTSC = hasInvariantTSC()
X86.Family, X86.Model = getFamilyModel()
X86.Signature = makeSignature(X86.Family, X86.Model)
X86.Name = getName()
X86.TSCFrequency = getNativeTSCFrequency(X86.Name, X86.Signature)
}
func isSet(hwc uint32, value uint32) bool {
return hwc&value != 0
}
func hasInvariantTSC() bool {
if maxExtendedFunction() < 0x80000007 {
return false
}
_, _, _, edx := cpuid(0x80000007, 0)
return isSet(edx, cpuid_Invariant_TSC)
}
func getName() string {
if maxExtendedFunction() >= 0x80000004 {
v := make([]uint32, 0, 48)
for i := uint32(0); i < 3; i++ {
a, b, c, d := cpuid(0x80000002+i, 0)
v = append(v, a, b, c, d)
}
return strings.Trim(string(valAsString(v...)), " ")
}
return "unknown"
}
// getNativeTSCFrequency gets TSC frequency from CPUID,
// only supports Intel (Skylake or later microarchitecture) & key information is from Intel manual & kernel codes
// (especially this commit: https://github.com/torvalds/linux/commit/604dc9170f2435d27da5039a3efd757dceadc684).
func getNativeTSCFrequency(name, sign string) uint64 {
if vendorID() != Intel {
return 0
}
if maxFunctionID() < 0x15 {
return 0
}
// ApolloLake, GeminiLake, CannonLake (and presumably all new chipsets
// from this point) report the crystal frequency directly via CPUID.0x15.
// That's definitive data that we can rely upon.
eax, ebx, ecx, _ := cpuid(0x15, 0)
// If ebx is 0, the TSC/”core crystal clock” ratio is not enumerated.
// We won't provide TSC frequency detection in this situation.
if eax == 0 || ebx == 0 {
return 0
}
// Skylake, Kabylake and all variants of those two chipsets report a
// crystal frequency of zero.
if ecx == 0 { // Crystal clock frequency is not enumerated.
ecx = getCrystalClockFrequency(sign)
}
// TSC frequency = “core crystal clock frequency” * EBX/EAX.
return uint64(ecx) * (uint64(ebx) / uint64(eax))
}
// Copied from: CPUID Signature values of DisplayFamily and DisplayModel,
// in Intel® 64 and IA-32 Architectures Software Developers Manual
// Volume 4: Model-Specific Registers
// & https://github.com/torvalds/linux/blob/master/arch/x86/include/asm/intel-family.h
const (
IntelFam6SkylakeL = "06_4EH"
IntelFam6Skylake = "06_5EH"
IntelFam6SkylakeX = "06_55H"
IntelFam6KabylakeL = "06_8EH"
IntelFam6Kabylake = "06_9EH"
)
// getCrystalClockFrequency gets crystal clock frequency
// for Intel processors in which CPUID.15H.EBX[31:0] ÷ CPUID.0x15.EAX[31:0] is enumerated
// but CPUID.15H.ECX is not enumerated using this function to get nominal core crystal clock frequency.
//
// Actually these crystal clock frequencies provided by Intel hardcoded tables are not so accurate in some cases,
// e.g. SkyLake server CPU may have issue (All SKX subject the crystal to an EMI reduction circuit that
//reduces its actual frequency by (approximately) -0.25%):
// see https://lore.kernel.org/lkml/ff6dcea166e8ff8f2f6a03c17beab2cb436aa779.1513920414.git.len.brown@intel.com/
// for more details.
// With this report, I set a coefficient (0.9975) for IntelFam6SkyLakeX.
//
// Unlike the kernel way (mentioned in https://github.com/torvalds/linux/commit/604dc9170f2435d27da5039a3efd757dceadc684),
// I prefer the Intel hardcoded tables,
// because after some testing (comparing with wall clock, see https://github.com/templexxx/tsc/tsc_test.go for more details),
// I found hardcoded tables are more accurate.
func getCrystalClockFrequency(sign string) uint32 {
if maxFunctionID() < 0x16 {
return 0
}
switch sign {
case IntelFam6SkylakeL:
return 24 * 1000 * 1000
case IntelFam6Skylake:
return 24 * 1000 * 1000
case IntelFam6SkylakeX:
return 25 * 1000 * 1000 * 0.9975
case IntelFam6KabylakeL:
return 24 * 1000 * 1000
case IntelFam6Kabylake:
return 24 * 1000 * 1000
}
return 0
}
func getFamilyModel() (uint32, uint32) {
if maxFunctionID() < 0x1 {
return 0, 0
}
eax, _, _, _ := cpuid(1, 0)
family := (eax >> 8) & 0xf
displayFamily := family
if family == 0xf {
displayFamily = ((eax >> 20) & 0xff) + family
}
model := (eax >> 4) & 0xf
displayModel := model
if family == 0x6 || family == 0xf {
displayModel = ((eax >> 12) & 0xf0) + model
}
return displayFamily, displayModel
}
// signature format: XX_XXH
func makeSignature(family, model uint32) string {
signature := strings.ToUpper(fmt.Sprintf("0%x_0%xH", family, model))
ss := strings.Split(signature, "_")
for i, s := range ss {
// Maybe insert too more `0`, drop it.
if len(s) > 2 {
s = s[1:]
ss[i] = s
}
}
return strings.Join(ss, "_")
}
// getCacheSize is from
// https://github.com/klauspost/cpuid/blob/5a626f7029c910cc8329dae5405ee4f65034bce5/cpuid.go#L723
func getCacheSize() Cache {
+3
View File
@@ -246,6 +246,9 @@ func DecryptBlock(key SM4Key, dst, src []byte) {
func ReadKeyFromMem(data []byte, pwd []byte) (SM4Key, error) {
block, _ := pem.Decode(data)
if block == nil {
return nil, errors.New("SM4: pem decode failed")
}
if x509.IsEncryptedPEMBlock(block) {
if block.Type != "SM4 ENCRYPTED KEY" {
return nil, errors.New("SM4: unknown type")
+1
View File
@@ -6,6 +6,7 @@
# Folders
_obj
_test
/vendor/
# Architecture specific extensions/prefixes
*.[568vq]
+11 -7
View File
@@ -1,15 +1,19 @@
module github.com/xtaci/kcp-go/v5
require (
github.com/klauspost/cpuid v1.2.2 // indirect
github.com/klauspost/reedsolomon v1.9.3
github.com/pkg/errors v0.8.1
github.com/klauspost/cpuid v1.3.1 // indirect
github.com/klauspost/reedsolomon v1.9.9
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 // indirect
github.com/pkg/errors v0.9.1
github.com/templexxx/cpu v0.0.7 // indirect
github.com/templexxx/xorsimd v0.4.1
github.com/tjfoc/gmsm v1.0.1
github.com/tjfoc/gmsm v1.3.2
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 // indirect
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
golang.org/x/net v0.0.0-20200707034311-ab3426394381
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9 // indirect
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)
go 1.13
+47 -14
View File
@@ -1,25 +1,58 @@
github.com/klauspost/cpuid v1.2.2 h1:1xAgYebNnsb9LKCdLOvFWtAxGU/33mjJtyOVbmUa0Us=
github.com/klauspost/cpuid v1.2.2/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/reedsolomon v1.9.3 h1:N/VzgeMfHmLc+KHMD1UL/tNkfXAt8FnUqlgXGIduwAY=
github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
github.com/klauspost/reedsolomon v1.9.9 h1:qCL7LZlv17xMixl55nq2/Oa1Y86nfO8EqDfv2GHND54=
github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo=
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 h1:ULR/QWMgcgRiZLUjSSJMU+fW+RDMstRdmnDWj9Q+AsA=
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/templexxx/cpu v0.0.1 h1:hY4WdLOgKdc8y13EYklu9OUTXik80BkxHoWvTO6MQQY=
github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
github.com/templexxx/cpu v0.0.7 h1:pUEZn8JBy/w5yzdYWgx+0m0xL9uk6j4K91C5kOViAzo=
github.com/templexxx/cpu v0.0.7/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
github.com/templexxx/xorsimd v0.4.1 h1:iUZcywbOYDRAZUasAs2eSCUW8eobuZDy0I9FJiORkVg=
github.com/templexxx/xorsimd v0.4.1/go.mod h1:W+ffZz8jJMH2SXwuKu9WhygqBMbFnp14G2fqEr8qaNo=
github.com/tjfoc/gmsm v1.0.1 h1:R11HlqhXkDospckjZEihx9SW/2VW0RgdwrykyWMFOQU=
github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 h1:JA8d3MPx/IToSyXZG/RhwYEtfrKO1Fxrqe8KrkiLXKM=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9 h1:yi1hN8dcqI9l8klZfy4B8mJvFmmAxJEePIQQFNSd7Cs=
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123 h1:4JSJPND/+4555t1HfXYF4UEqDqiSKCgeV0+hbA8hMs4=
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+1 -3
View File
@@ -656,9 +656,7 @@ func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int {
if windowSlides { // if window has slided, flush
kcp.flush(false)
}
if ackNoDelay && len(kcp.acklist) > 0 { // ack immediately
} else if ackNoDelay && len(kcp.acklist) > 0 { // ack immediately
kcp.flush(true)
}
return 0
+17 -3
View File
@@ -611,6 +611,20 @@ func (s *UDPSession) GetRTO() uint32 {
return s.kcp.rx_rto
}
// GetSRTT gets current srtt of the session
func (s *UDPSession) GetSRTT() int32 {
s.mu.Lock()
defer s.mu.Unlock()
return s.kcp.rx_srtt
}
// GetRTTVar gets current rtt variance of the session
func (s *UDPSession) GetSRTTVar() int32 {
s.mu.Lock()
defer s.mu.Unlock()
return s.kcp.rx_rttvar
}
func (s *UDPSession) notifyReadEvent() {
select {
case s.chReadEvent <- struct{}{}:
@@ -762,7 +776,7 @@ type (
ownConn bool // true if we created conn internally, false if provided by caller
sessions map[string]*UDPSession // all sessions accepted by this Listener
sessionLock sync.Mutex
sessionLock sync.RWMutex
chAccepts chan *UDPSession // Listen() backlog
chSessionClosed chan net.Addr // session close queue
headerSize int // the additional header to a KCP frame
@@ -797,9 +811,9 @@ func (l *Listener) packetInput(data []byte, addr net.Addr) {
}
if dataValid {
l.sessionLock.Lock()
l.sessionLock.RLock()
s, ok := l.sessions[addr.String()]
l.sessionLock.Unlock()
l.sessionLock.RUnlock()
var conv, sn uint32
convValid := false
+2 -3
View File
@@ -14,9 +14,8 @@ import (
)
const (
Version = 4 // protocol version
HeaderLen = 20 // header length without extension headers
maxHeaderLen = 60 // sensible default, revisit if later RFCs define new usage of version and header length fields
Version = 4 // protocol version
HeaderLen = 20 // header length without extension headers
)
type HeaderFlags int
+2 -2
View File
@@ -89,7 +89,7 @@ constants.
Adding new syscall numbers is mostly done by running the build on a sufficiently
new installation of the target OS (or updating the source checkouts for the
new build system). However, depending on the OS, you make need to update the
new build system). However, depending on the OS, you may need to update the
parsing in mksysnum.
### mksyscall.go
@@ -163,7 +163,7 @@ The merge is performed in the following steps:
## Generated files
### `zerror_${GOOS}_${GOARCH}.go`
### `zerrors_${GOOS}_${GOARCH}.go`
A file containing all of the system's generated error numbers, error strings,
signal numbers, and constants. Generated by `mkerrors.sh` (see above).
+11 -2
View File
@@ -107,6 +107,7 @@ includes_FreeBSD='
#include <sys/types.h>
#include <sys/disk.h>
#include <sys/event.h>
#include <sys/sched.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@@ -187,6 +188,7 @@ struct ltchars {
#include <sys/select.h>
#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/timerfd.h>
#include <sys/uio.h>
#include <sys/xattr.h>
#include <linux/bpf.h>
@@ -200,6 +202,7 @@ struct ltchars {
#include <linux/filter.h>
#include <linux/fs.h>
#include <linux/fscrypt.h>
#include <linux/fsverity.h>
#include <linux/genetlink.h>
#include <linux/hdreg.h>
#include <linux/icmpv6.h>
@@ -295,6 +298,7 @@ includes_NetBSD='
#include <sys/extattr.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/sched.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@@ -323,6 +327,7 @@ includes_OpenBSD='
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/select.h>
#include <sys/sched.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/stat.h>
@@ -479,12 +484,13 @@ ccflags="$@"
$2 ~ /^(MS|MNT|UMOUNT)_/ ||
$2 ~ /^NS_GET_/ ||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ ||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ ||
$2 ~ /^KEXEC_/ ||
$2 ~ /^LINUX_REBOOT_CMD_/ ||
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
$2 ~ /^MODULE_INIT_/ ||
$2 !~ "NLA_TYPE_MASK" &&
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
$2 ~ /^SIOC/ ||
$2 ~ /^TIOC/ ||
@@ -504,9 +510,12 @@ ccflags="$@"
$2 ~ /^(CLOCK|TIMER)_/ ||
$2 ~ /^CAN_/ ||
$2 ~ /^CAP_/ ||
$2 ~ /^CP_/ ||
$2 ~ /^CPUSTATES$/ ||
$2 ~ /^ALG_/ ||
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
$2 ~ /^FS_IOC_.*ENCRYPTION/ ||
$2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|[GS]ETFLAGS)/ ||
$2 ~ /^FS_VERITY_/ ||
$2 ~ /^FSCRYPT_/ ||
$2 ~ /^GRND_/ ||
$2 ~ /^RND/ ||
+17
View File
@@ -527,6 +527,23 @@ func SysctlClockinfo(name string) (*Clockinfo, error) {
return &ci, nil
}
func SysctlTimeval(name string) (*Timeval, error) {
mib, err := sysctlmib(name)
if err != nil {
return nil, err
}
var tv Timeval
n := uintptr(unsafe.Sizeof(tv))
if err := sysctl(mib, (*byte)(unsafe.Pointer(&tv)), &n, nil, 0); err != nil {
return nil, err
}
if n != unsafe.Sizeof(tv) {
return nil, EIO
}
return &tv, nil
}
//sys utimes(path string, timeval *[2]Timeval) (err error)
func Utimes(path string, tv []Timeval) error {
+14 -7
View File
@@ -6,7 +6,11 @@
package unix
import "unsafe"
import (
"unsafe"
"golang.org/x/sys/internal/unsafeheader"
)
//sys closedir(dir uintptr) (err error)
//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
@@ -71,6 +75,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
cnt++
continue
}
reclen := int(entry.Reclen)
if reclen > len(buf) {
// Not enough room. Return for now.
@@ -79,13 +84,15 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
// restarting is O(n^2) in the length of the directory. Oh well.
break
}
// Copy entry into return buffer.
s := struct {
ptr unsafe.Pointer
siz int
cap int
}{ptr: unsafe.Pointer(&entry), siz: reclen, cap: reclen}
copy(buf, *(*[]byte)(unsafe.Pointer(&s)))
var s []byte
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&s))
hdr.Data = unsafe.Pointer(&entry)
hdr.Cap = reclen
hdr.Len = reclen
copy(buf, s)
buf = buf[reclen:]
n += reclen
cnt++
+1
View File
@@ -423,6 +423,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sysnb Getrlimit(which int, lim *Rlimit) (err error)
//sysnb Getrusage(who int, rusage *Rusage) (err error)
//sysnb Getsid(pid int) (sid int, err error)
//sysnb Gettimeofday(tp *Timeval) (err error)
//sysnb Getuid() (uid int)
//sysnb Issetugid() (tainted bool)
//sys Kqueue() (fd int, err error)
-11
View File
@@ -20,17 +20,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)}
}
//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = int32(sec)
tv.Usec = int32(usec)
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd)
k.Filter = int16(mode)
-11
View File
@@ -20,17 +20,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: int32(usec)}
}
//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = sec
tv.Usec = usec
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd)
k.Filter = int16(mode)
-11
View File
@@ -20,17 +20,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)}
}
//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = int32(sec)
tv.Usec = int32(usec)
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd)
k.Filter = int16(mode)
-11
View File
@@ -22,17 +22,6 @@ func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: sec, Usec: int32(usec)}
}
//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) {
// The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back
// in the two registers.
sec, usec, err := gettimeofday(tv)
tv.Sec = sec
tv.Usec = usec
return err
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd)
k.Filter = int16(mode)
+60 -6
View File
@@ -97,6 +97,12 @@ func IoctlSetRTCTime(fd int, value *RTCTime) error {
return err
}
func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error {
err := ioctl(fd, RTC_WKALM_SET, uintptr(unsafe.Pointer(value)))
runtime.KeepAlive(value)
return err
}
func IoctlGetUint32(fd int, req uint) (uint32, error) {
var value uint32
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
@@ -109,6 +115,12 @@ func IoctlGetRTCTime(fd int) (*RTCTime, error) {
return &value, err
}
func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
var value RTCWkAlrm
err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value)))
return &value, err
}
//sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
func Link(oldpath string, newpath string) (err error) {
@@ -1633,6 +1645,15 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
//sys DeleteModule(name string, flags int) (err error)
//sys Dup(oldfd int) (fd int, err error)
func Dup2(oldfd, newfd int) error {
// Android O and newer blocks dup2; riscv and arm64 don't implement dup2.
if runtime.GOOS == "android" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "arm64" {
return Dup3(oldfd, newfd, 0)
}
return dup2(oldfd, newfd)
}
//sys Dup3(oldfd int, newfd int, flags int) (err error)
//sysnb EpollCreate1(flag int) (fd int, err error)
//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error)
@@ -1757,6 +1778,9 @@ func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) {
//sys Syncfs(fd int) (err error)
//sysnb Sysinfo(info *Sysinfo_t) (err error)
//sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error)
//sysnb TimerfdCreate(clockid int, flags int) (fd int, err error)
//sysnb TimerfdGettime(fd int, currValue *ItimerSpec) (err error)
//sysnb TimerfdSettime(fd int, flags int, newValue *ItimerSpec, oldValue *ItimerSpec) (err error)
//sysnb Tgkill(tgid int, tid int, sig syscall.Signal) (err error)
//sysnb Times(tms *Tms) (ticks uintptr, err error)
//sysnb Umask(mask int) (oldmask int)
@@ -1926,11 +1950,30 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
return int(n), nil
}
func isGroupMember(gid int) bool {
groups, err := Getgroups()
if err != nil {
return false
}
for _, g := range groups {
if g == gid {
return true
}
}
return false
}
//sys faccessat(dirfd int, path string, mode uint32) (err error)
//sys Faccessat2(dirfd int, path string, mode uint32, flags int) (err error)
func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
if flags & ^(AT_SYMLINK_NOFOLLOW|AT_EACCESS) != 0 {
return EINVAL
if flags == 0 {
return faccessat(dirfd, path, mode)
}
if err := Faccessat2(dirfd, path, mode, flags); err != ENOSYS && err != EPERM {
return err
}
// The Linux kernel faccessat system call does not take any flags.
@@ -1939,8 +1982,8 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
// Because people naturally expect syscall.Faccessat to act
// like C faccessat, we do the same.
if flags == 0 {
return faccessat(dirfd, path, mode)
if flags & ^(AT_SYMLINK_NOFOLLOW|AT_EACCESS) != 0 {
return EINVAL
}
var st Stat_t
@@ -1983,7 +2026,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
gid = Getgid()
}
if uint32(gid) == st.Gid {
if uint32(gid) == st.Gid || isGroupMember(gid) {
fmode = (st.Mode >> 3) & 7
} else {
fmode = st.Mode & 7
@@ -2084,6 +2127,18 @@ func Klogset(typ int, arg int) (err error) {
return nil
}
// RemoteIovec is Iovec with the pointer replaced with an integer.
// It is used for ProcessVMReadv and ProcessVMWritev, where the pointer
// refers to a location in a different process' address space, which
// would confuse the Go garbage collector.
type RemoteIovec struct {
Base uintptr
Len int
}
//sys ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV
//sys ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV
/*
* Unimplemented
*/
@@ -2178,7 +2233,6 @@ func Klogset(typ int, arg int) (err error) {
// TimerGetoverrun
// TimerGettime
// TimerSettime
// Timerfd
// Tkill (obsolete)
// Tuxcall
// Umount2
+1 -1
View File
@@ -49,7 +49,7 @@ func Pipe2(p []int, flags int) (err error) {
// 64-bit file system and 32-bit uid calls
// (386 default is 32-bit file system and 16-bit uid).
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
+1 -1
View File
@@ -6,7 +6,7 @@
package unix
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
+1 -1
View File
@@ -80,7 +80,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
// 64-bit file system and 32-bit uid calls
// (16-bit uid calls are not always supported in newer kernels)
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
+23 -5
View File
@@ -25,7 +25,7 @@ func EpollCreate(size int) (fd int, err error) {
//sysnb Getegid() (egid int)
//sysnb Geteuid() (euid int)
//sysnb Getgid() (gid int)
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
//sysnb getrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Getuid() (uid int)
//sys Listen(s int, n int) (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
@@ -47,7 +47,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sysnb setrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Setreuid(ruid int, euid int) (err error)
//sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
@@ -168,6 +168,24 @@ func Pipe2(p []int, flags int) (err error) {
return
}
// Getrlimit prefers the prlimit64 system call. See issue 38604.
func Getrlimit(resource int, rlim *Rlimit) error {
err := prlimit(0, resource, nil, rlim)
if err != ENOSYS {
return err
}
return getrlimit(resource, rlim)
}
// Setrlimit prefers the prlimit64 system call. See issue 38604.
func Setrlimit(resource int, rlim *Rlimit) error {
err := prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}
return setrlimit(resource, rlim)
}
func (r *PtraceRegs) PC() uint64 { return r.Pc }
func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc }
@@ -192,9 +210,9 @@ func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}
func Dup2(oldfd int, newfd int) (err error) {
return Dup3(oldfd, newfd, 0)
}
// dup2 exists because func Dup3 in syscall_linux.go references
// it in an unreachable path. dup2 isn't available on arm64.
func dup2(oldfd int, newfd int) error
func Pause() error {
_, err := ppoll(nil, 0, nil, nil)
+1 -1
View File
@@ -7,7 +7,7 @@
package unix
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
+1 -1
View File
@@ -14,7 +14,7 @@ import (
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
+1 -1
View File
@@ -7,7 +7,7 @@
package unix
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
+4 -4
View File
@@ -191,10 +191,6 @@ func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}
func Dup2(oldfd int, newfd int) (err error) {
return Dup3(oldfd, newfd, 0)
}
func Pause() error {
_, err := ppoll(nil, 0, nil, nil)
return err
@@ -228,3 +224,7 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
}
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
}
// dup2 exists because func Dup3 in syscall_linux.go references
// it in an unreachable path. dup2 isn't available on arm64.
func dup2(oldfd int, newfd int) error
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"unsafe"
)
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sysnb EpollCreate(size int) (fd int, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
+1 -1
View File
@@ -8,7 +8,7 @@ package unix
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Dup2(oldfd int, newfd int) (err error)
//sys dup2(oldfd int, newfd int) (err error)
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
+9 -10
View File
@@ -12,6 +12,8 @@ import (
"sync"
"syscall"
"unsafe"
"golang.org/x/sys/internal/unsafeheader"
)
var (
@@ -76,7 +78,7 @@ func SignalName(s syscall.Signal) string {
// The signal name should start with "SIG".
func SignalNum(s string) syscall.Signal {
signalNameMapOnce.Do(func() {
signalNameMap = make(map[string]syscall.Signal)
signalNameMap = make(map[string]syscall.Signal, len(signalList))
for _, signal := range signalList {
signalNameMap[signal.name] = signal.num
}
@@ -113,15 +115,12 @@ func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (d
return nil, errno
}
// Slice memory layout
var sl = struct {
addr uintptr
len int
cap int
}{addr, length, length}
// Use unsafe to turn sl into a []byte.
b := *(*[]byte)(unsafe.Pointer(&sl))
// Use unsafe to convert addr into a []byte.
var b []byte
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b))
hdr.Data = unsafe.Pointer(addr)
hdr.Cap = length
hdr.Len = length
// Register mapping in m and return it.
p := &b[cap(b)-1]
+6
View File
@@ -339,6 +339,12 @@ const (
CLOCK_UPTIME_FAST = 0x8
CLOCK_UPTIME_PRECISE = 0x7
CLOCK_VIRTUAL = 0x1
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x30000
CS5 = 0x0
+6
View File
@@ -339,6 +339,12 @@ const (
CLOCK_UPTIME_FAST = 0x8
CLOCK_UPTIME_PRECISE = 0x7
CLOCK_VIRTUAL = 0x1
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x30000
CS5 = 0x0
+6
View File
@@ -339,6 +339,12 @@ const (
CLOCK_UPTIME_FAST = 0x8
CLOCK_UPTIME_PRECISE = 0x7
CLOCK_VIRTUAL = 0x1
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x30000
CS5 = 0x0
+6
View File
@@ -339,6 +339,12 @@ const (
CLOCK_UPTIME_FAST = 0x8
CLOCK_UPTIME_PRECISE = 0x7
CLOCK_VIRTUAL = 0x1
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x30000
CS5 = 0x0
+45 -68
View File
@@ -160,77 +160,28 @@ const (
BPF_A = 0x10
BPF_ABS = 0x20
BPF_ADD = 0x0
BPF_ADJ_ROOM_ENCAP_L2_MASK = 0xff
BPF_ADJ_ROOM_ENCAP_L2_SHIFT = 0x38
BPF_ALU = 0x4
BPF_ALU64 = 0x7
BPF_AND = 0x50
BPF_ANY = 0x0
BPF_ARSH = 0xc0
BPF_B = 0x10
BPF_BUILD_ID_SIZE = 0x14
BPF_CALL = 0x80
BPF_DEVCG_ACC_MKNOD = 0x1
BPF_DEVCG_ACC_READ = 0x2
BPF_DEVCG_ACC_WRITE = 0x4
BPF_DEVCG_DEV_BLOCK = 0x1
BPF_DEVCG_DEV_CHAR = 0x2
BPF_DIV = 0x30
BPF_DW = 0x18
BPF_END = 0xd0
BPF_EXIST = 0x2
BPF_EXIT = 0x90
BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG = 0x1
BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP = 0x4
BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL = 0x2
BPF_FROM_BE = 0x8
BPF_FROM_LE = 0x0
BPF_FS_MAGIC = 0xcafe4a11
BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 = 0x2
BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 = 0x4
BPF_F_ADJ_ROOM_ENCAP_L4_GRE = 0x8
BPF_F_ADJ_ROOM_ENCAP_L4_UDP = 0x10
BPF_F_ADJ_ROOM_FIXED_GSO = 0x1
BPF_F_ALLOW_MULTI = 0x2
BPF_F_ALLOW_OVERRIDE = 0x1
BPF_F_ANY_ALIGNMENT = 0x2
BPF_F_CLONE = 0x200
BPF_F_CTXLEN_MASK = 0xfffff00000000
BPF_F_CURRENT_CPU = 0xffffffff
BPF_F_CURRENT_NETNS = -0x1
BPF_F_DONT_FRAGMENT = 0x4
BPF_F_FAST_STACK_CMP = 0x200
BPF_F_HDR_FIELD_MASK = 0xf
BPF_F_INDEX_MASK = 0xffffffff
BPF_F_INGRESS = 0x1
BPF_F_INVALIDATE_HASH = 0x2
BPF_F_LOCK = 0x4
BPF_F_MARK_ENFORCE = 0x40
BPF_F_MARK_MANGLED_0 = 0x20
BPF_F_MMAPABLE = 0x400
BPF_F_NO_COMMON_LRU = 0x2
BPF_F_NO_PREALLOC = 0x1
BPF_F_NUMA_NODE = 0x4
BPF_F_PSEUDO_HDR = 0x10
BPF_F_QUERY_EFFECTIVE = 0x1
BPF_F_RDONLY = 0x8
BPF_F_RDONLY_PROG = 0x80
BPF_F_RECOMPUTE_CSUM = 0x1
BPF_F_REUSE_STACKID = 0x400
BPF_F_SEQ_NUMBER = 0x8
BPF_F_SKIP_FIELD_MASK = 0xff
BPF_F_STACK_BUILD_ID = 0x20
BPF_F_REPLACE = 0x4
BPF_F_STRICT_ALIGNMENT = 0x1
BPF_F_SYSCTL_BASE_NAME = 0x1
BPF_F_TEST_RND_HI32 = 0x4
BPF_F_TEST_STATE_FREQ = 0x8
BPF_F_TUNINFO_IPV6 = 0x1
BPF_F_USER_BUILD_ID = 0x800
BPF_F_USER_STACK = 0x100
BPF_F_WRONLY = 0x10
BPF_F_WRONLY_PROG = 0x100
BPF_F_ZERO_CSUM_TX = 0x2
BPF_F_ZERO_SEED = 0x40
BPF_H = 0x8
BPF_IMM = 0x0
BPF_IND = 0x40
@@ -266,7 +217,6 @@ const (
BPF_MUL = 0x20
BPF_NEG = 0x80
BPF_NET_OFF = -0x100000
BPF_NOEXIST = 0x1
BPF_OBJ_NAME_LEN = 0x10
BPF_OR = 0x40
BPF_PSEUDO_CALL = 0x1
@@ -274,12 +224,6 @@ const (
BPF_PSEUDO_MAP_VALUE = 0x2
BPF_RET = 0x6
BPF_RSH = 0x70
BPF_SK_STORAGE_GET_F_CREATE = 0x1
BPF_SOCK_OPS_ALL_CB_FLAGS = 0xf
BPF_SOCK_OPS_RETRANS_CB_FLAG = 0x2
BPF_SOCK_OPS_RTO_CB_FLAG = 0x1
BPF_SOCK_OPS_RTT_CB_FLAG = 0x8
BPF_SOCK_OPS_STATE_CB_FLAG = 0x4
BPF_ST = 0x2
BPF_STX = 0x3
BPF_SUB = 0x10
@@ -321,6 +265,7 @@ const (
CAP_AUDIT_READ = 0x25
CAP_AUDIT_WRITE = 0x1d
CAP_BLOCK_SUSPEND = 0x24
CAP_BPF = 0x27
CAP_CHOWN = 0x0
CAP_DAC_OVERRIDE = 0x1
CAP_DAC_READ_SEARCH = 0x2
@@ -329,7 +274,7 @@ const (
CAP_IPC_LOCK = 0xe
CAP_IPC_OWNER = 0xf
CAP_KILL = 0x5
CAP_LAST_CAP = 0x25
CAP_LAST_CAP = 0x27
CAP_LEASE = 0x1c
CAP_LINUX_IMMUTABLE = 0x9
CAP_MAC_ADMIN = 0x21
@@ -339,6 +284,7 @@ const (
CAP_NET_BIND_SERVICE = 0xa
CAP_NET_BROADCAST = 0xb
CAP_NET_RAW = 0xd
CAP_PERFMON = 0x26
CAP_SETFCAP = 0x1f
CAP_SETGID = 0x6
CAP_SETPCAP = 0x8
@@ -377,18 +323,21 @@ const (
CLOCK_TXINT = 0x3
CLONE_ARGS_SIZE_VER0 = 0x40
CLONE_ARGS_SIZE_VER1 = 0x50
CLONE_ARGS_SIZE_VER2 = 0x58
CLONE_CHILD_CLEARTID = 0x200000
CLONE_CHILD_SETTID = 0x1000000
CLONE_CLEAR_SIGHAND = 0x100000000
CLONE_DETACHED = 0x400000
CLONE_FILES = 0x400
CLONE_FS = 0x200
CLONE_INTO_CGROUP = 0x200000000
CLONE_IO = 0x80000000
CLONE_NEWCGROUP = 0x2000000
CLONE_NEWIPC = 0x8000000
CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x20000
CLONE_NEWPID = 0x20000000
CLONE_NEWTIME = 0x80
CLONE_NEWUSER = 0x10000000
CLONE_NEWUTS = 0x4000000
CLONE_PARENT = 0x8000
@@ -425,6 +374,7 @@ const (
DEVLINK_GENL_NAME = "devlink"
DEVLINK_GENL_VERSION = 0x1
DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14
DEVMEM_MAGIC = 0x454d444d
DEVPTS_SUPER_MAGIC = 0x1cd1
DMA_BUF_MAGIC = 0x444d4142
DT_BLK = 0x6
@@ -528,6 +478,7 @@ const (
ETH_P_MOBITEX = 0x15
ETH_P_MPLS_MC = 0x8848
ETH_P_MPLS_UC = 0x8847
ETH_P_MRP = 0x88e3
ETH_P_MVRP = 0x88f5
ETH_P_NCSI = 0x88f8
ETH_P_NSH = 0x894f
@@ -596,7 +547,9 @@ const (
FAN_DELETE = 0x200
FAN_DELETE_SELF = 0x400
FAN_DENY = 0x2
FAN_DIR_MODIFY = 0x80000
FAN_ENABLE_AUDIT = 0x40
FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2
FAN_EVENT_INFO_TYPE_FID = 0x1
FAN_EVENT_METADATA_LEN = 0x18
FAN_EVENT_ON_CHILD = 0x8000000
@@ -653,8 +606,9 @@ const (
FSCRYPT_POLICY_FLAGS_PAD_4 = 0x0
FSCRYPT_POLICY_FLAGS_PAD_8 = 0x1
FSCRYPT_POLICY_FLAGS_PAD_MASK = 0x3
FSCRYPT_POLICY_FLAGS_VALID = 0xf
FSCRYPT_POLICY_FLAGS_VALID = 0x1f
FSCRYPT_POLICY_FLAG_DIRECT_KEY = 0x4
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32 = 0x10
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 = 0x8
FSCRYPT_POLICY_V1 = 0x0
FSCRYPT_POLICY_V2 = 0x2
@@ -671,6 +625,7 @@ const (
FS_IOC_ADD_ENCRYPTION_KEY = 0xc0506617
FS_IOC_GET_ENCRYPTION_KEY_STATUS = 0xc080661a
FS_IOC_GET_ENCRYPTION_POLICY_EX = 0xc0096616
FS_IOC_MEASURE_VERITY = 0xc0046686
FS_IOC_REMOVE_ENCRYPTION_KEY = 0xc0406618
FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS = 0xc0406619
FS_KEY_DESCRIPTOR_SIZE = 0x8
@@ -682,7 +637,10 @@ const (
FS_POLICY_FLAGS_PAD_4 = 0x0
FS_POLICY_FLAGS_PAD_8 = 0x1
FS_POLICY_FLAGS_PAD_MASK = 0x3
FS_POLICY_FLAGS_VALID = 0xf
FS_POLICY_FLAGS_VALID = 0x1f
FS_VERITY_FL = 0x100000
FS_VERITY_HASH_ALG_SHA256 = 0x1
FS_VERITY_HASH_ALG_SHA512 = 0x2
FUTEXFS_SUPER_MAGIC = 0xbad1dea
F_ADD_SEALS = 0x409
F_DUPFD = 0x0
@@ -733,6 +691,7 @@ const (
GENL_NAMSIZ = 0x10
GENL_START_ALLOC = 0x13
GENL_UNS_ADMIN_PERM = 0x10
GRND_INSECURE = 0x4
GRND_NONBLOCK = 0x1
GRND_RANDOM = 0x2
HDIO_DRIVE_CMD = 0x31f
@@ -880,6 +839,7 @@ const (
IPPROTO_EGP = 0x8
IPPROTO_ENCAP = 0x62
IPPROTO_ESP = 0x32
IPPROTO_ETHERNET = 0x8f
IPPROTO_FRAGMENT = 0x2c
IPPROTO_GRE = 0x2f
IPPROTO_HOPOPTS = 0x0
@@ -893,6 +853,7 @@ const (
IPPROTO_L2TP = 0x73
IPPROTO_MH = 0x87
IPPROTO_MPLS = 0x89
IPPROTO_MPTCP = 0x106
IPPROTO_MTP = 0x5c
IPPROTO_NONE = 0x3b
IPPROTO_PIM = 0x67
@@ -1062,6 +1023,7 @@ const (
KEYCTL_CAPS0_PERSISTENT_KEYRINGS = 0x2
KEYCTL_CAPS0_PUBLIC_KEY = 0x8
KEYCTL_CAPS0_RESTRICT_KEYRING = 0x40
KEYCTL_CAPS1_NOTIFICATIONS = 0x4
KEYCTL_CAPS1_NS_KEYRING_NAME = 0x1
KEYCTL_CAPS1_NS_KEY_TAG = 0x2
KEYCTL_CHOWN = 0x4
@@ -1099,6 +1061,7 @@ const (
KEYCTL_SUPPORTS_VERIFY = 0x8
KEYCTL_UNLINK = 0x9
KEYCTL_UPDATE = 0x2
KEYCTL_WATCH_KEY = 0x20
KEY_REQKEY_DEFL_DEFAULT = 0x0
KEY_REQKEY_DEFL_GROUP_KEYRING = 0x6
KEY_REQKEY_DEFL_NO_CHANGE = -0x1
@@ -1142,6 +1105,8 @@ const (
LOOP_SET_FD = 0x4c00
LOOP_SET_STATUS = 0x4c02
LOOP_SET_STATUS64 = 0x4c04
LOOP_SET_STATUS_CLEARABLE_FLAGS = 0x4
LOOP_SET_STATUS_SETTABLE_FLAGS = 0xc
LO_KEY_SIZE = 0x20
LO_NAME_SIZE = 0x40
MADV_COLD = 0x14
@@ -1483,6 +1448,7 @@ const (
PR_GET_FPEMU = 0x9
PR_GET_FPEXC = 0xb
PR_GET_FP_MODE = 0x2e
PR_GET_IO_FLUSHER = 0x3a
PR_GET_KEEPCAPS = 0x7
PR_GET_NAME = 0x10
PR_GET_NO_NEW_PRIVS = 0x27
@@ -1518,6 +1484,7 @@ const (
PR_SET_FPEMU = 0xa
PR_SET_FPEXC = 0xc
PR_SET_FP_MODE = 0x2d
PR_SET_IO_FLUSHER = 0x39
PR_SET_KEEPCAPS = 0x8
PR_SET_MM = 0x23
PR_SET_MM_ARG_END = 0x9
@@ -1746,12 +1713,15 @@ const (
RTM_DELRULE = 0x21
RTM_DELTCLASS = 0x29
RTM_DELTFILTER = 0x2d
RTM_DELVLAN = 0x71
RTM_F_CLONED = 0x200
RTM_F_EQUALIZE = 0x400
RTM_F_FIB_MATCH = 0x2000
RTM_F_LOOKUP_TABLE = 0x1000
RTM_F_NOTIFY = 0x100
RTM_F_OFFLOAD = 0x4000
RTM_F_PREFIX = 0x800
RTM_F_TRAP = 0x8000
RTM_GETACTION = 0x32
RTM_GETADDR = 0x16
RTM_GETADDRLABEL = 0x4a
@@ -1773,7 +1743,8 @@ const (
RTM_GETSTATS = 0x5e
RTM_GETTCLASS = 0x2a
RTM_GETTFILTER = 0x2e
RTM_MAX = 0x6f
RTM_GETVLAN = 0x72
RTM_MAX = 0x73
RTM_NEWACTION = 0x30
RTM_NEWADDR = 0x14
RTM_NEWADDRLABEL = 0x48
@@ -1788,6 +1759,7 @@ const (
RTM_NEWNETCONF = 0x50
RTM_NEWNEXTHOP = 0x68
RTM_NEWNSID = 0x58
RTM_NEWNVLAN = 0x70
RTM_NEWPREFIX = 0x34
RTM_NEWQDISC = 0x24
RTM_NEWROUTE = 0x18
@@ -1795,8 +1767,8 @@ const (
RTM_NEWSTATS = 0x5c
RTM_NEWTCLASS = 0x28
RTM_NEWTFILTER = 0x2c
RTM_NR_FAMILIES = 0x18
RTM_NR_MSGTYPES = 0x60
RTM_NR_FAMILIES = 0x19
RTM_NR_MSGTYPES = 0x64
RTM_SETDCB = 0x4f
RTM_SETLINK = 0x13
RTM_SETNEIGHTBL = 0x43
@@ -2031,8 +2003,10 @@ const (
STATX_ATTR_APPEND = 0x20
STATX_ATTR_AUTOMOUNT = 0x1000
STATX_ATTR_COMPRESSED = 0x4
STATX_ATTR_DAX = 0x2000
STATX_ATTR_ENCRYPTED = 0x800
STATX_ATTR_IMMUTABLE = 0x10
STATX_ATTR_MOUNT_ROOT = 0x2000
STATX_ATTR_NODUMP = 0x40
STATX_ATTR_VERITY = 0x100000
STATX_BASIC_STATS = 0x7ff
@@ -2041,6 +2015,7 @@ const (
STATX_CTIME = 0x80
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MNT_ID = 0x1000
STATX_MODE = 0x2
STATX_MTIME = 0x40
STATX_NLINK = 0x4
@@ -2086,7 +2061,7 @@ const (
TASKSTATS_GENL_NAME = "TASKSTATS"
TASKSTATS_GENL_VERSION = 0x1
TASKSTATS_TYPE_MAX = 0x6
TASKSTATS_VERSION = 0x9
TASKSTATS_VERSION = 0xa
TCIFLUSH = 0x0
TCIOFF = 0x2
TCIOFLUSH = 0x2
@@ -2094,8 +2069,6 @@ const (
TCOFLUSH = 0x1
TCOOFF = 0x0
TCOON = 0x1
TCP_BPF_IW = 0x3e9
TCP_BPF_SNDCWND_CLAMP = 0x3ea
TCP_CC_INFO = 0x1a
TCP_CM_INQ = 0x24
TCP_CONGESTION = 0xd
@@ -2151,6 +2124,8 @@ const (
TCP_USER_TIMEOUT = 0x12
TCP_WINDOW_CLAMP = 0xa
TCP_ZEROCOPY_RECEIVE = 0x23
TFD_TIMER_ABSTIME = 0x1
TFD_TIMER_CANCEL_ON_SET = 0x2
TIMER_ABSTIME = 0x1
TIOCM_DTR = 0x2
TIOCM_LE = 0x1
@@ -2267,7 +2242,7 @@ const (
VMADDR_CID_ANY = 0xffffffff
VMADDR_CID_HOST = 0x2
VMADDR_CID_HYPERVISOR = 0x0
VMADDR_CID_RESERVED = 0x1
VMADDR_CID_LOCAL = 0x1
VMADDR_PORT_ANY = 0xffffffff
VM_SOCKETS_INVALID_VERSION = 0xffffffff
VQUIT = 0x1
@@ -2368,8 +2343,9 @@ const (
XDP_COPY = 0x2
XDP_FLAGS_DRV_MODE = 0x4
XDP_FLAGS_HW_MODE = 0x8
XDP_FLAGS_MASK = 0xf
XDP_FLAGS_MASK = 0x1f
XDP_FLAGS_MODES = 0xe
XDP_FLAGS_REPLACE = 0x10
XDP_FLAGS_SKB_MODE = 0x2
XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1
XDP_MMAP_OFFSETS = 0x1
@@ -2394,6 +2370,7 @@ const (
XENFS_SUPER_MAGIC = 0xabba1974
XFS_SUPER_MAGIC = 0x58465342
Z3FOLD_MAGIC = 0x33
ZONEFS_MAGIC = 0x5a4f4653
ZSMALLOC_MAGIC = 0x58295829
)
+6
View File
@@ -73,8 +73,12 @@ const (
FFDLY = 0x8000
FLUSHO = 0x1000
FP_XSTATE_MAGIC2 = 0x46505845
FS_IOC_ENABLE_VERITY = 0x40806685
FS_IOC_GETFLAGS = 0x80046601
FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614
FS_IOC_SETFLAGS = 0x40046602
FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613
F_GETLK = 0xc
F_GETLK64 = 0xc
@@ -340,6 +344,8 @@ const (
TCSETXF = 0x5434
TCSETXW = 0x5435
TCXONC = 0x540a
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x800
TIOCCBRK = 0x5428
TIOCCONS = 0x541d
TIOCEXCL = 0x540c
+6
View File
@@ -73,8 +73,12 @@ const (
FFDLY = 0x8000
FLUSHO = 0x1000
FP_XSTATE_MAGIC2 = 0x46505845
FS_IOC_ENABLE_VERITY = 0x40806685
FS_IOC_GETFLAGS = 0x80086601
FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614
FS_IOC_SETFLAGS = 0x40086602
FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613
F_GETLK = 0x5
F_GETLK64 = 0x5
@@ -341,6 +345,8 @@ const (
TCSETXF = 0x5434
TCSETXW = 0x5435
TCXONC = 0x540a
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x800
TIOCCBRK = 0x5428
TIOCCONS = 0x541d
TIOCEXCL = 0x540c
+6
View File
@@ -72,8 +72,12 @@ const (
FF1 = 0x8000
FFDLY = 0x8000
FLUSHO = 0x1000
FS_IOC_ENABLE_VERITY = 0x40806685
FS_IOC_GETFLAGS = 0x80046601
FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614
FS_IOC_SETFLAGS = 0x40046602
FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613
F_GETLK = 0xc
F_GETLK64 = 0xc
@@ -347,6 +351,8 @@ const (
TCSETXF = 0x5434
TCSETXW = 0x5435
TCXONC = 0x540a
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x800
TIOCCBRK = 0x5428
TIOCCONS = 0x541d
TIOCEXCL = 0x540c
+7
View File
@@ -75,8 +75,12 @@ const (
FFDLY = 0x8000
FLUSHO = 0x1000
FPSIMD_MAGIC = 0x46508001
FS_IOC_ENABLE_VERITY = 0x40806685
FS_IOC_GETFLAGS = 0x80086601
FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614
FS_IOC_SETFLAGS = 0x40086602
FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613
F_GETLK = 0x5
F_GETLK64 = 0x5
@@ -188,6 +192,7 @@ const (
PPPIOCSRASYNCMAP = 0x40047454
PPPIOCSXASYNCMAP = 0x4020744f
PPPIOCXFERUNIT = 0x744e
PROT_BTI = 0x10
PR_SET_PTRACER_ANY = 0xffffffffffffffff
PTRACE_SYSEMU = 0x1f
PTRACE_SYSEMU_SINGLESTEP = 0x20
@@ -334,6 +339,8 @@ const (
TCSETXF = 0x5434
TCSETXW = 0x5435
TCXONC = 0x540a
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x800
TIOCCBRK = 0x5428
TIOCCONS = 0x541d
TIOCEXCL = 0x540c
+6
View File
@@ -72,8 +72,12 @@ const (
FF1 = 0x8000
FFDLY = 0x8000
FLUSHO = 0x2000
FS_IOC_ENABLE_VERITY = 0x80806685
FS_IOC_GETFLAGS = 0x40046601
FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614
FS_IOC_SETFLAGS = 0x80046602
FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613
F_GETLK = 0x21
F_GETLK64 = 0x21
@@ -337,6 +341,8 @@ const (
TCSETSW = 0x540f
TCSETSW2 = 0x8030542c
TCXONC = 0x5406
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x80
TIOCCBRK = 0x5428
TIOCCONS = 0x80047478
TIOCEXCL = 0x740d
+6
View File
@@ -72,8 +72,12 @@ const (
FF1 = 0x8000
FFDLY = 0x8000
FLUSHO = 0x2000
FS_IOC_ENABLE_VERITY = 0x80806685
FS_IOC_GETFLAGS = 0x40086601
FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614
FS_IOC_SETFLAGS = 0x80086602
FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613
F_GETLK = 0xe
F_GETLK64 = 0xe
@@ -337,6 +341,8 @@ const (
TCSETSW = 0x540f
TCSETSW2 = 0x8030542c
TCXONC = 0x5406
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x80
TIOCCBRK = 0x5428
TIOCCONS = 0x80047478
TIOCEXCL = 0x740d
+6
View File
@@ -72,8 +72,12 @@ const (
FF1 = 0x8000
FFDLY = 0x8000
FLUSHO = 0x2000
FS_IOC_ENABLE_VERITY = 0x80806685
FS_IOC_GETFLAGS = 0x40086601
FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614
FS_IOC_SETFLAGS = 0x80086602
FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613
F_GETLK = 0xe
F_GETLK64 = 0xe
@@ -337,6 +341,8 @@ const (
TCSETSW = 0x540f
TCSETSW2 = 0x8030542c
TCXONC = 0x5406
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x80
TIOCCBRK = 0x5428
TIOCCONS = 0x80047478
TIOCEXCL = 0x740d
+6
View File
@@ -72,8 +72,12 @@ const (
FF1 = 0x8000
FFDLY = 0x8000
FLUSHO = 0x2000
FS_IOC_ENABLE_VERITY = 0x80806685
FS_IOC_GETFLAGS = 0x40046601
FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614
FS_IOC_SETFLAGS = 0x80046602
FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613
F_GETLK = 0x21
F_GETLK64 = 0x21
@@ -337,6 +341,8 @@ const (
TCSETSW = 0x540f
TCSETSW2 = 0x8030542c
TCXONC = 0x5406
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x80
TIOCCBRK = 0x5428
TIOCCONS = 0x80047478
TIOCEXCL = 0x740d
+6
View File
@@ -72,8 +72,12 @@ const (
FF1 = 0x4000
FFDLY = 0x4000
FLUSHO = 0x800000
FS_IOC_ENABLE_VERITY = 0x80806685
FS_IOC_GETFLAGS = 0x40086601
FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614
FS_IOC_SETFLAGS = 0x80086602
FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613
F_GETLK = 0x5
F_GETLK64 = 0xc
@@ -391,6 +395,8 @@ const (
TCSETSF = 0x802c7416
TCSETSW = 0x802c7415
TCXONC = 0x2000741e
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x800
TIOCCBRK = 0x5428
TIOCCONS = 0x541d
TIOCEXCL = 0x540c
+6
View File
@@ -72,8 +72,12 @@ const (
FF1 = 0x4000
FFDLY = 0x4000
FLUSHO = 0x800000
FS_IOC_ENABLE_VERITY = 0x80806685
FS_IOC_GETFLAGS = 0x40086601
FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614
FS_IOC_SETFLAGS = 0x80086602
FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613
F_GETLK = 0x5
F_GETLK64 = 0xc
@@ -391,6 +395,8 @@ const (
TCSETSF = 0x802c7416
TCSETSW = 0x802c7415
TCXONC = 0x2000741e
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x800
TIOCCBRK = 0x5428
TIOCCONS = 0x541d
TIOCEXCL = 0x540c
+6
View File
@@ -72,8 +72,12 @@ const (
FF1 = 0x8000
FFDLY = 0x8000
FLUSHO = 0x1000
FS_IOC_ENABLE_VERITY = 0x40806685
FS_IOC_GETFLAGS = 0x80086601
FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614
FS_IOC_SETFLAGS = 0x40086602
FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613
F_GETLK = 0x5
F_GETLK64 = 0x5
@@ -328,6 +332,8 @@ const (
TCSETXF = 0x5434
TCSETXW = 0x5435
TCXONC = 0x540a
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x800
TIOCCBRK = 0x5428
TIOCCONS = 0x541d
TIOCEXCL = 0x540c
+6
View File
@@ -72,8 +72,12 @@ const (
FF1 = 0x8000
FFDLY = 0x8000
FLUSHO = 0x1000
FS_IOC_ENABLE_VERITY = 0x40806685
FS_IOC_GETFLAGS = 0x80086601
FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614
FS_IOC_SETFLAGS = 0x40086602
FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613
F_GETLK = 0x5
F_GETLK64 = 0x5
@@ -401,6 +405,8 @@ const (
TCSETXF = 0x5434
TCSETXW = 0x5435
TCXONC = 0x540a
TFD_CLOEXEC = 0x80000
TFD_NONBLOCK = 0x800
TIOCCBRK = 0x5428
TIOCCONS = 0x541d
TIOCEXCL = 0x540c
+6
View File
@@ -76,8 +76,12 @@ const (
FF1 = 0x8000
FFDLY = 0x8000
FLUSHO = 0x1000
FS_IOC_ENABLE_VERITY = 0x80806685
FS_IOC_GETFLAGS = 0x40086601
FS_IOC_GET_ENCRYPTION_NONCE = 0x4010661b
FS_IOC_GET_ENCRYPTION_POLICY = 0x800c6615
FS_IOC_GET_ENCRYPTION_PWSALT = 0x80106614
FS_IOC_SETFLAGS = 0x80086602
FS_IOC_SET_ENCRYPTION_POLICY = 0x400c6613
F_GETLK = 0x7
F_GETLK64 = 0x7
@@ -390,6 +394,8 @@ const (
TCSETSW = 0x8024540a
TCSETSW2 = 0x802c540e
TCXONC = 0x20005406
TFD_CLOEXEC = 0x400000
TFD_NONBLOCK = 0x4000
TIOCCBRK = 0x2000747a
TIOCCONS = 0x20007424
TIOCEXCL = 0x2000740d
+6
View File
@@ -158,6 +158,12 @@ const (
CLONE_SIGHAND = 0x800
CLONE_VFORK = 0x4000
CLONE_VM = 0x100
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x10000
CS5 = 0x0
+6
View File
@@ -158,6 +158,12 @@ const (
CLONE_SIGHAND = 0x800
CLONE_VFORK = 0x4000
CLONE_VM = 0x100
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x10000
CS5 = 0x0
+6
View File
@@ -150,6 +150,12 @@ const (
BRKINT = 0x2
CFLUSH = 0xf
CLOCAL = 0x8000
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x10000
CS5 = 0x0
+6
View File
@@ -158,6 +158,12 @@ const (
CLONE_SIGHAND = 0x800
CLONE_VFORK = 0x4000
CLONE_VM = 0x100
CPUSTATES = 0x5
CP_IDLE = 0x4
CP_INTR = 0x3
CP_NICE = 0x1
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x10000
CS5 = 0x0
+7
View File
@@ -146,6 +146,13 @@ const (
BRKINT = 0x2
CFLUSH = 0xf
CLOCAL = 0x8000
CPUSTATES = 0x6
CP_IDLE = 0x5
CP_INTR = 0x4
CP_NICE = 0x1
CP_SPIN = 0x3
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x10000
CS5 = 0x0
+7
View File
@@ -153,6 +153,13 @@ const (
CLOCK_REALTIME = 0x0
CLOCK_THREAD_CPUTIME_ID = 0x4
CLOCK_UPTIME = 0x5
CPUSTATES = 0x6
CP_IDLE = 0x5
CP_INTR = 0x4
CP_NICE = 0x1
CP_SPIN = 0x3
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x10000
CS5 = 0x0
+7
View File
@@ -146,6 +146,13 @@ const (
BRKINT = 0x2
CFLUSH = 0xf
CLOCAL = 0x8000
CPUSTATES = 0x6
CP_IDLE = 0x5
CP_INTR = 0x4
CP_NICE = 0x1
CP_SPIN = 0x3
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x10000
CS5 = 0x0
+7
View File
@@ -156,6 +156,13 @@ const (
CLOCK_REALTIME = 0x0
CLOCK_THREAD_CPUTIME_ID = 0x4
CLOCK_UPTIME = 0x5
CPUSTATES = 0x6
CP_IDLE = 0x5
CP_INTR = 0x4
CP_NICE = 0x1
CP_SPIN = 0x3
CP_SYS = 0x2
CP_USER = 0x0
CREAD = 0x800
CRTSCTS = 0x10000
CS5 = 0x0
+10 -12
View File
@@ -966,6 +966,16 @@ func Getsid(pid int) (sid int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Gettimeofday(tp *Timeval) (err error) {
_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getuid() (uid int) {
r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
uid = int(r0)
@@ -1709,18 +1719,6 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) {
r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
sec = int32(r0)
usec = int32(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, stat *Stat_t) (err error) {
_, _, e1 := Syscall(SYS_FSTAT64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
+15 -17
View File
@@ -1376,6 +1376,21 @@ func libc_getsid_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Gettimeofday(tp *Timeval) (err error) {
_, _, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func libc_gettimeofday_trampoline()
//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getuid() (uid int) {
r0, _, _ := syscall_rawSyscall(funcPC(libc_getuid_trampoline), 0, 0, 0)
uid = int(r0)
@@ -2357,23 +2372,6 @@ func libc_ptrace_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) {
r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
sec = int32(r0)
usec = int32(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func libc_gettimeofday_trampoline()
//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, stat *Stat_t) (err error) {
_, _, e1 := syscall_syscall(funcPC(libc_fstat64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
+10 -12
View File
@@ -966,6 +966,16 @@ func Getsid(pid int) (sid int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Gettimeofday(tp *Timeval) (err error) {
_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getuid() (uid int) {
r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
uid = int(r0)
@@ -1709,18 +1719,6 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) {
r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
sec = int64(r0)
usec = int32(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, stat *Stat_t) (err error) {
_, _, e1 := Syscall(SYS_FSTAT64, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
+15 -17
View File
@@ -1376,6 +1376,21 @@ func libc_getsid_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Gettimeofday(tp *Timeval) (err error) {
_, _, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func libc_gettimeofday_trampoline()
//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getuid() (uid int) {
r0, _, _ := syscall_rawSyscall(funcPC(libc_getuid_trampoline), 0, 0, 0)
uid = int(r0)
@@ -2357,23 +2372,6 @@ func libc_ptrace_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) {
r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
sec = int64(r0)
usec = int32(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func libc_gettimeofday_trampoline()
//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, stat *Stat_t) (err error) {
_, _, e1 := syscall_syscall(funcPC(libc_fstat64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
+10 -12
View File
@@ -966,6 +966,16 @@ func Getsid(pid int) (sid int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Gettimeofday(tp *Timeval) (err error) {
_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getuid() (uid int) {
r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
uid = int(r0)
@@ -1682,18 +1692,6 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) {
r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
sec = int32(r0)
usec = int32(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, stat *Stat_t) (err error) {
_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
+15 -17
View File
@@ -1376,6 +1376,21 @@ func libc_getsid_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Gettimeofday(tp *Timeval) (err error) {
_, _, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func libc_gettimeofday_trampoline()
//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getuid() (uid int) {
r0, _, _ := syscall_rawSyscall(funcPC(libc_getuid_trampoline), 0, 0, 0)
uid = int(r0)
@@ -2342,23 +2357,6 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) {
r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
sec = int32(r0)
usec = int32(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func libc_gettimeofday_trampoline()
//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, stat *Stat_t) (err error) {
_, _, e1 := syscall_syscall(funcPC(libc_fstat_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
+10 -12
View File
@@ -966,6 +966,16 @@ func Getsid(pid int) (sid int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Gettimeofday(tp *Timeval) (err error) {
_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getuid() (uid int) {
r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
uid = int(r0)
@@ -1682,18 +1692,6 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) {
r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
sec = int64(r0)
usec = int32(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, stat *Stat_t) (err error) {
_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
+15 -17
View File
@@ -1376,6 +1376,21 @@ func libc_getsid_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Gettimeofday(tp *Timeval) (err error) {
_, _, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func libc_gettimeofday_trampoline()
//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getuid() (uid int) {
r0, _, _ := syscall_rawSyscall(funcPC(libc_getuid_trampoline), 0, 0, 0)
uid = int(r0)
@@ -2342,23 +2357,6 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) {
r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
sec = int64(r0)
usec = int32(r1)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func libc_gettimeofday_trampoline()
//go:linkname libc_gettimeofday libc_gettimeofday
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fstat(fd int, stat *Stat_t) (err error) {
_, _, e1 := syscall_syscall(funcPC(libc_fstat_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
if e1 != 0 {
+92
View File
@@ -1450,6 +1450,37 @@ func Sysinfo(info *Sysinfo_t) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func TimerfdCreate(clockid int, flags int) (fd int, err error) {
r0, _, e1 := RawSyscall(SYS_TIMERFD_CREATE, uintptr(clockid), uintptr(flags), 0)
fd = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func TimerfdGettime(fd int, currValue *ItimerSpec) (err error) {
_, _, e1 := RawSyscall(SYS_TIMERFD_GETTIME, uintptr(fd), uintptr(unsafe.Pointer(currValue)), 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func TimerfdSettime(fd int, flags int, newValue *ItimerSpec, oldValue *ItimerSpec) (err error) {
_, _, e1 := RawSyscall6(SYS_TIMERFD_SETTIME, uintptr(fd), uintptr(flags), uintptr(unsafe.Pointer(newValue)), uintptr(unsafe.Pointer(oldValue)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Tgkill(tgid int, tid int, sig syscall.Signal) (err error) {
_, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
if e1 != 0 {
@@ -1790,6 +1821,21 @@ func faccessat(dirfd int, path string, mode uint32) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Faccessat2(dirfd int, path string, mode uint32, flags int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := Syscall6(SYS_FACCESSAT2, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func nameToHandleAt(dirFD int, pathname string, fh *fileHandle, mountID *_C_int, flags int) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(pathname)
@@ -1816,6 +1862,52 @@ func openByHandleAt(mountFD int, fh *fileHandle, flags int) (fd int, err error)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) {
var _p0 unsafe.Pointer
if len(localIov) > 0 {
_p0 = unsafe.Pointer(&localIov[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
var _p1 unsafe.Pointer
if len(remoteIov) > 0 {
_p1 = unsafe.Pointer(&remoteIov[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PROCESS_VM_READV, uintptr(pid), uintptr(_p0), uintptr(len(localIov)), uintptr(_p1), uintptr(len(remoteIov)), uintptr(flags))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) {
var _p0 unsafe.Pointer
if len(localIov) > 0 {
_p0 = unsafe.Pointer(&localIov[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
var _p1 unsafe.Pointer
if len(remoteIov) > 0 {
_p1 = unsafe.Pointer(&remoteIov[0])
} else {
_p1 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PROCESS_VM_WRITEV, uintptr(pid), uintptr(_p0), uintptr(len(localIov)), uintptr(_p1), uintptr(len(remoteIov)), uintptr(flags))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {
+1 -1
View File
@@ -55,7 +55,7 @@ func pipe(p *[2]_C_int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup2(oldfd int, newfd int) (err error) {
func dup2(oldfd int, newfd int) (err error) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
if e1 != 0 {
err = errnoErr(e1)
+1 -1
View File
@@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup2(oldfd int, newfd int) (err error) {
func dup2(oldfd int, newfd int) (err error) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
if e1 != 0 {
err = errnoErr(e1)
+1 -1
View File
@@ -234,7 +234,7 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup2(oldfd int, newfd int) (err error) {
func dup2(oldfd int, newfd int) (err error) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
if e1 != 0 {
err = errnoErr(e1)
+2 -2
View File
@@ -151,7 +151,7 @@ func Getgid() (gid int) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getrlimit(resource int, rlim *Rlimit) (err error) {
func getrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
@@ -307,7 +307,7 @@ func Setresuid(ruid int, euid int, suid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
func setrlimit(resource int, rlim *Rlimit) (err error) {
_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
if e1 != 0 {
err = errnoErr(e1)
+1 -1
View File
@@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup2(oldfd int, newfd int) (err error) {
func dup2(oldfd int, newfd int) (err error) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
if e1 != 0 {
err = errnoErr(e1)
+1 -1
View File
@@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup2(oldfd int, newfd int) (err error) {
func dup2(oldfd int, newfd int) (err error) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
if e1 != 0 {
err = errnoErr(e1)
+1 -1
View File
@@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup2(oldfd int, newfd int) (err error) {
func dup2(oldfd int, newfd int) (err error) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
if e1 != 0 {
err = errnoErr(e1)
+1 -1
View File
@@ -45,7 +45,7 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Dup2(oldfd int, newfd int) (err error) {
func dup2(oldfd int, newfd int) (err error) {
_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
if e1 != 0 {
err = errnoErr(e1)

Some files were not shown because too many files have changed in this diff Show More