summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/platform/filemem/filemem_state.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/platform/filemem/filemem_state.go')
-rw-r--r--pkg/sentry/platform/filemem/filemem_state.go24
1 files changed, 24 insertions, 0 deletions
diff --git a/pkg/sentry/platform/filemem/filemem_state.go b/pkg/sentry/platform/filemem/filemem_state.go
index 5dace8fec..e28e021c9 100644
--- a/pkg/sentry/platform/filemem/filemem_state.go
+++ b/pkg/sentry/platform/filemem/filemem_state.go
@@ -19,6 +19,7 @@ import (
"fmt"
"io"
"runtime"
+ "sync/atomic"
"syscall"
"gvisor.googlesource.com/gvisor/pkg/log"
@@ -127,6 +128,29 @@ func (f *FileMem) LoadFrom(r io.Reader) error {
return err
}
+ // Try to map committed chunks concurrently: For any given chunk, either
+ // this loop or the following one will mmap the chunk first and cache it in
+ // f.mappings for the other, but this loop is likely to run ahead of the
+ // other since it doesn't do any work between mmaps. The rest of this
+ // function doesn't mutate f.usage, so it's safe to iterate concurrently.
+ mapperDone := make(chan struct{})
+ mapperCanceled := int32(0)
+ go func() { // S/R-SAFE: see comment
+ defer func() { close(mapperDone) }()
+ for seg := f.usage.FirstSegment(); seg.Ok(); seg = seg.NextSegment() {
+ if atomic.LoadInt32(&mapperCanceled) != 0 {
+ return
+ }
+ if seg.Value().knownCommitted {
+ f.forEachMappingSlice(seg.Range(), func(s []byte) {})
+ }
+ }
+ }()
+ defer func() {
+ atomic.StoreInt32(&mapperCanceled, 1)
+ <-mapperDone
+ }()
+
// Load committed pages.
for seg := f.usage.FirstSegment(); seg.Ok(); seg = seg.NextSegment() {
if !seg.Value().knownCommitted {