From a29c39aa629b6118765e5075eb228752934d7081 Mon Sep 17 00:00:00 2001 From: Jamie Liu Date: Mon, 10 Sep 2018 15:22:44 -0700 Subject: Map committed chunks concurrently in FileMem.LoadFrom. PiperOrigin-RevId: 212345401 Change-Id: Iac626ee87ba312df88ab1019ade6ecd62c04c75c --- pkg/sentry/platform/filemem/filemem_state.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'pkg/sentry/platform/filemem') 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 { -- cgit v1.2.3