diff options
author | Rutger Broekhoff | 2023-12-29 21:31:53 +0100 |
---|---|---|
committer | Rutger Broekhoff | 2023-12-29 21:31:53 +0100 |
commit | 404aeae4545d2426c089a5f8d5e82dae56f5212b (patch) | |
tree | 2d84e00af272b39fc04f3795ae06bc48970e57b5 /vendor/github.com/minio/md5-simd/md5-digest_amd64.go | |
parent | 209d8b0187ed025dec9ac149ebcced3462877bff (diff) | |
download | gitolfs3-404aeae4545d2426c089a5f8d5e82dae56f5212b.tar.gz gitolfs3-404aeae4545d2426c089a5f8d5e82dae56f5212b.zip |
Make Nix builds work
Diffstat (limited to 'vendor/github.com/minio/md5-simd/md5-digest_amd64.go')
-rw-r--r-- | vendor/github.com/minio/md5-simd/md5-digest_amd64.go | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/vendor/github.com/minio/md5-simd/md5-digest_amd64.go b/vendor/github.com/minio/md5-simd/md5-digest_amd64.go new file mode 100644 index 0000000..5ea23a4 --- /dev/null +++ b/vendor/github.com/minio/md5-simd/md5-digest_amd64.go | |||
@@ -0,0 +1,188 @@ | |||
1 | //+build !noasm,!appengine,gc | ||
2 | |||
3 | // Copyright (c) 2020 MinIO Inc. All rights reserved. | ||
4 | // Use of this source code is governed by a license that can be | ||
5 | // found in the LICENSE file. | ||
6 | |||
7 | package md5simd | ||
8 | |||
9 | import ( | ||
10 | "encoding/binary" | ||
11 | "errors" | ||
12 | "fmt" | ||
13 | "sync" | ||
14 | "sync/atomic" | ||
15 | ) | ||
16 | |||
17 | // md5Digest - Type for computing MD5 using either AVX2 or AVX512 | ||
18 | type md5Digest struct { | ||
19 | uid uint64 | ||
20 | blocksCh chan blockInput | ||
21 | cycleServer chan uint64 | ||
22 | x [BlockSize]byte | ||
23 | nx int | ||
24 | len uint64 | ||
25 | buffers <-chan []byte | ||
26 | } | ||
27 | |||
28 | // NewHash - initialize instance for Md5 implementation. | ||
29 | func (s *md5Server) NewHash() Hasher { | ||
30 | uid := atomic.AddUint64(&s.uidCounter, 1) | ||
31 | blockCh := make(chan blockInput, buffersPerLane) | ||
32 | s.newInput <- newClient{ | ||
33 | uid: uid, | ||
34 | input: blockCh, | ||
35 | } | ||
36 | return &md5Digest{ | ||
37 | uid: uid, | ||
38 | buffers: s.buffers, | ||
39 | blocksCh: blockCh, | ||
40 | cycleServer: s.cycle, | ||
41 | } | ||
42 | } | ||
43 | |||
44 | // Size - Return size of checksum | ||
45 | func (d *md5Digest) Size() int { return Size } | ||
46 | |||
47 | // BlockSize - Return blocksize of checksum | ||
48 | func (d md5Digest) BlockSize() int { return BlockSize } | ||
49 | |||
50 | func (d *md5Digest) Reset() { | ||
51 | if d.blocksCh == nil { | ||
52 | panic("reset after close") | ||
53 | } | ||
54 | d.nx = 0 | ||
55 | d.len = 0 | ||
56 | d.sendBlock(blockInput{uid: d.uid, reset: true}, false) | ||
57 | } | ||
58 | |||
59 | // write to digest | ||
60 | func (d *md5Digest) Write(p []byte) (nn int, err error) { | ||
61 | if d.blocksCh == nil { | ||
62 | return 0, errors.New("md5Digest closed") | ||
63 | } | ||
64 | |||
65 | // break input into chunks of maximum internalBlockSize size | ||
66 | for { | ||
67 | l := len(p) | ||
68 | if l > internalBlockSize { | ||
69 | l = internalBlockSize | ||
70 | } | ||
71 | nnn, err := d.write(p[:l]) | ||
72 | if err != nil { | ||
73 | return nn, err | ||
74 | } | ||
75 | nn += nnn | ||
76 | p = p[l:] | ||
77 | |||
78 | if len(p) == 0 { | ||
79 | break | ||
80 | } | ||
81 | |||
82 | } | ||
83 | return | ||
84 | } | ||
85 | |||
86 | func (d *md5Digest) write(p []byte) (nn int, err error) { | ||
87 | |||
88 | nn = len(p) | ||
89 | d.len += uint64(nn) | ||
90 | if d.nx > 0 { | ||
91 | n := copy(d.x[d.nx:], p) | ||
92 | d.nx += n | ||
93 | if d.nx == BlockSize { | ||
94 | // Create a copy of the overflow buffer in order to send it async over the channel | ||
95 | // (since we will modify the overflow buffer down below with any access beyond multiples of 64) | ||
96 | tmp := <-d.buffers | ||
97 | tmp = tmp[:BlockSize] | ||
98 | copy(tmp, d.x[:]) | ||
99 | d.sendBlock(blockInput{uid: d.uid, msg: tmp}, len(p)-n < BlockSize) | ||
100 | d.nx = 0 | ||
101 | } | ||
102 | p = p[n:] | ||
103 | } | ||
104 | if len(p) >= BlockSize { | ||
105 | n := len(p) &^ (BlockSize - 1) | ||
106 | buf := <-d.buffers | ||
107 | buf = buf[:n] | ||
108 | copy(buf, p) | ||
109 | d.sendBlock(blockInput{uid: d.uid, msg: buf}, len(p)-n < BlockSize) | ||
110 | p = p[n:] | ||
111 | } | ||
112 | if len(p) > 0 { | ||
113 | d.nx = copy(d.x[:], p) | ||
114 | } | ||
115 | return | ||
116 | } | ||
117 | |||
118 | func (d *md5Digest) Close() { | ||
119 | if d.blocksCh != nil { | ||
120 | close(d.blocksCh) | ||
121 | d.blocksCh = nil | ||
122 | } | ||
123 | } | ||
124 | |||
125 | var sumChPool sync.Pool | ||
126 | |||
127 | func init() { | ||
128 | sumChPool.New = func() interface{} { | ||
129 | return make(chan sumResult, 1) | ||
130 | } | ||
131 | } | ||
132 | |||
133 | // Sum - Return MD5 sum in bytes | ||
134 | func (d *md5Digest) Sum(in []byte) (result []byte) { | ||
135 | if d.blocksCh == nil { | ||
136 | panic("sum after close") | ||
137 | } | ||
138 | |||
139 | trail := <-d.buffers | ||
140 | trail = append(trail[:0], d.x[:d.nx]...) | ||
141 | |||
142 | length := d.len | ||
143 | // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. | ||
144 | var tmp [64]byte | ||
145 | tmp[0] = 0x80 | ||
146 | if length%64 < 56 { | ||
147 | trail = append(trail, tmp[0:56-length%64]...) | ||
148 | } else { | ||
149 | trail = append(trail, tmp[0:64+56-length%64]...) | ||
150 | } | ||
151 | |||
152 | // Length in bits. | ||
153 | length <<= 3 | ||
154 | binary.LittleEndian.PutUint64(tmp[:], length) // append length in bits | ||
155 | |||
156 | trail = append(trail, tmp[0:8]...) | ||
157 | if len(trail)%BlockSize != 0 { | ||
158 | panic(fmt.Errorf("internal error: sum block was not aligned. len=%d, nx=%d", len(trail), d.nx)) | ||
159 | } | ||
160 | sumCh := sumChPool.Get().(chan sumResult) | ||
161 | d.sendBlock(blockInput{uid: d.uid, msg: trail, sumCh: sumCh}, true) | ||
162 | |||
163 | sum := <-sumCh | ||
164 | sumChPool.Put(sumCh) | ||
165 | |||
166 | return append(in, sum.digest[:]...) | ||
167 | } | ||
168 | |||
169 | // sendBlock will send a block for processing. | ||
170 | // If cycle is true we will block on cycle, otherwise we will only block | ||
171 | // if the block channel is full. | ||
172 | func (d *md5Digest) sendBlock(bi blockInput, cycle bool) { | ||
173 | if cycle { | ||
174 | select { | ||
175 | case d.blocksCh <- bi: | ||
176 | d.cycleServer <- d.uid | ||
177 | } | ||
178 | return | ||
179 | } | ||
180 | // Only block on cycle if we filled the buffer | ||
181 | select { | ||
182 | case d.blocksCh <- bi: | ||
183 | return | ||
184 | default: | ||
185 | d.cycleServer <- d.uid | ||
186 | d.blocksCh <- bi | ||
187 | } | ||
188 | } | ||