summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/mm/io.go
diff options
context:
space:
mode:
authorFabricio Voznika <fvoznika@google.com>2019-03-05 23:39:14 -0800
committerShentubot <shentubot@google.com>2019-03-05 23:40:18 -0800
commit0b76887147820a809beaa497ede8dc4f7b7b120a (patch)
treea89be091add2e39163cefe84bf3614a6338f3cd9 /pkg/sentry/mm/io.go
parentfcba4e8f040ab4b40e04b9315d718d7e5aa44635 (diff)
Priority-inheritance futex implementation
It is Implemented without the priority inheritance part given that gVisor defers scheduling decisions to Go runtime and doesn't have control over it. PiperOrigin-RevId: 236989545 Change-Id: I714c8ca0798743ecf3167b14ffeb5cd834302560
Diffstat (limited to 'pkg/sentry/mm/io.go')
-rw-r--r--pkg/sentry/mm/io.go45
1 files changed, 45 insertions, 0 deletions
diff --git a/pkg/sentry/mm/io.go b/pkg/sentry/mm/io.go
index 6600ddd78..e0cebef84 100644
--- a/pkg/sentry/mm/io.go
+++ b/pkg/sentry/mm/io.go
@@ -346,6 +346,7 @@ func (mm *MemoryManager) SwapUint32(ctx context.Context, addr usermem.Addr, new
if err != nil {
return 0, translateIOError(ctx, err)
}
+ // Return the number of bytes read.
return 4, nil
})
return old, err
@@ -388,11 +389,55 @@ func (mm *MemoryManager) CompareAndSwapUint32(ctx context.Context, addr usermem.
if err != nil {
return 0, translateIOError(ctx, err)
}
+ // Return the number of bytes read.
return 4, nil
})
return prev, err
}
+// LoadUint32 implements usermem.IO.LoadUint32.
+func (mm *MemoryManager) LoadUint32(ctx context.Context, addr usermem.Addr, opts usermem.IOOpts) (uint32, error) {
+ ar, ok := mm.CheckIORange(addr, 4)
+ if !ok {
+ return 0, syserror.EFAULT
+ }
+
+ // Do AddressSpace IO if applicable.
+ if mm.haveASIO && opts.AddressSpaceActive && !opts.IgnorePermissions {
+ for {
+ val, err := mm.as.LoadUint32(addr)
+ if err == nil {
+ return val, nil
+ }
+ if f, ok := err.(platform.SegmentationFault); ok {
+ if err := mm.handleASIOFault(ctx, f.Addr, ar, usermem.Read); err != nil {
+ return 0, err
+ }
+ continue
+ }
+ return 0, translateIOError(ctx, err)
+ }
+ }
+
+ // Go through internal mappings.
+ var val uint32
+ _, err := mm.withInternalMappings(ctx, ar, usermem.Read, opts.IgnorePermissions, func(ims safemem.BlockSeq) (uint64, error) {
+ if ims.NumBlocks() != 1 || ims.NumBytes() != 4 {
+ // Atomicity is unachievable across mappings.
+ return 0, syserror.EFAULT
+ }
+ im := ims.Head()
+ var err error
+ val, err = safemem.LoadUint32(im)
+ if err != nil {
+ return 0, translateIOError(ctx, err)
+ }
+ // Return the number of bytes read.
+ return 4, nil
+ })
+ return val, err
+}
+
// handleASIOFault handles a page fault at address addr for an AddressSpaceIO
// operation spanning ioar.
//