releaserMain implements the releaser goroutine.
()
| 1256 | |
| 1257 | // releaserMain implements the releaser goroutine. |
| 1258 | func (f *MemoryFile) releaserMain() { |
| 1259 | f.mu.Lock() |
| 1260 | MainLoop: |
| 1261 | for { |
| 1262 | for { |
| 1263 | if f.destroyed { |
| 1264 | f.releaserDestroyLocked() |
| 1265 | f.mu.Unlock() |
| 1266 | // This must be called without holding f.mu to avoid circular lock |
| 1267 | // ordering. |
| 1268 | if f.stopNotifyPressure != nil { |
| 1269 | f.stopNotifyPressure() |
| 1270 | } |
| 1271 | return |
| 1272 | } |
| 1273 | if f.haveWaste { |
| 1274 | break |
| 1275 | } |
| 1276 | if f.opts.DelayedEviction == DelayedEvictionEnabled && !f.opts.UseHostMemcgPressure { |
| 1277 | // No work to do. Evict any pending evictable allocations to |
| 1278 | // get more waste pages before going to sleep. |
| 1279 | f.startEvictionsLocked() |
| 1280 | } |
| 1281 | f.releaseCond.Wait() // releases f.mu while waiting |
| 1282 | } |
| 1283 | // Huge pages are relatively rare and expensive due to fragmentation |
| 1284 | // and the cost of compaction. Fragmentation is expected to increase |
| 1285 | // over time. Most allocations are done upwards, with the main |
| 1286 | // exception being thread stacks. So we expect lower offsets to weakly |
| 1287 | // correlate with older allocations, which are more likely to actually |
| 1288 | // be hugepage-backed. Thus, release from unwasteSmall before |
| 1289 | // unwasteHuge, and higher offsets before lower ones. |
| 1290 | for i, unwaste := range []*unwasteSet{&f.unwasteSmall, &f.unwasteHuge} { |
| 1291 | if uwgap := unwaste.LastLargeEnoughGap(1); uwgap.Ok() { |
| 1292 | fr := uwgap.Range() |
| 1293 | // Linux serializes fallocate()s on shmem files, so limit the amount we |
| 1294 | // release at once to avoid starving Decommit(). |
| 1295 | const maxReleasingBytes = 128 << 20 // 128 MB |
| 1296 | if fr.Length() > maxReleasingBytes { |
| 1297 | fr.Start = fr.End - maxReleasingBytes |
| 1298 | } |
| 1299 | unwaste.Insert(uwgap, fr, unwasteInfo{}) |
| 1300 | f.releaseLocked(fr, i == 1) |
| 1301 | continue MainLoop |
| 1302 | } |
| 1303 | } |
| 1304 | f.haveWaste = false |
| 1305 | } |
| 1306 | } |
| 1307 | |
| 1308 | // Preconditions: f.mu must be locked; it may be unlocked and reacquired. |
| 1309 | func (f *MemoryFile) releaseLocked(fr memmap.FileRange, huge bool) { |
no test coverage detected