Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: mojo/edk/embedder/simple_platform_shared_buffer_posix.cc

Issue 814543006: Move //mojo/{public, edk} underneath //third_party (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "mojo/edk/embedder/simple_platform_shared_buffer.h"
6
7 #include <stdint.h>
8 #include <stdio.h> // For |fileno()|.
9 #include <sys/mman.h> // For |mmap()|/|munmap()|.
10 #include <sys/stat.h>
11 #include <sys/types.h> // For |off_t|.
12 #include <unistd.h>
13
14 #include <limits>
15
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/files/scoped_file.h"
19 #include "base/logging.h"
20 #include "base/macros.h"
21 #include "base/posix/eintr_wrapper.h"
22 #include "base/sys_info.h"
23 #include "base/threading/thread_restrictions.h"
24 #include "mojo/edk/embedder/platform_handle.h"
25
26 // We assume that |size_t| and |off_t| (type for |ftruncate()|) fits in a
27 // |uint64_t|.
28 static_assert(sizeof(size_t) <= sizeof(uint64_t), "size_t too big");
29 static_assert(sizeof(off_t) <= sizeof(uint64_t), "off_t too big");
30
31 namespace mojo {
32 namespace embedder {
33
34 // SimplePlatformSharedBuffer --------------------------------------------------
35
36 // The implementation for android uses ashmem to generate the file descriptor
37 // for the shared memory. See simple_platform_shared_buffer_android.cc
38 #if !defined(OS_ANDROID)
39
40 bool SimplePlatformSharedBuffer::Init() {
41 DCHECK(!handle_.is_valid());
42
43 base::ThreadRestrictions::ScopedAllowIO allow_io;
44
45 if (static_cast<uint64_t>(num_bytes_) >
46 static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
47 return false;
48 }
49
50 // TODO(vtl): This is stupid. The implementation of
51 // |CreateAndOpenTemporaryFileInDir()| starts with an FD, |fdopen()|s to get a
52 // |FILE*|, and then we have to |dup(fileno(fp))| to get back to an FD that we
53 // can own. (base/memory/shared_memory_posix.cc does this too, with more
54 // |fstat()|s thrown in for good measure.)
55 base::FilePath shared_buffer_dir;
56 if (!base::GetShmemTempDir(false, &shared_buffer_dir)) {
57 LOG(ERROR) << "Failed to get temporary directory for shared memory";
58 return false;
59 }
60 base::FilePath shared_buffer_file;
61 base::ScopedFILE fp(base::CreateAndOpenTemporaryFileInDir(
62 shared_buffer_dir, &shared_buffer_file));
63 if (!fp) {
64 LOG(ERROR) << "Failed to create/open temporary file for shared memory";
65 return false;
66 }
67 // Note: |unlink()| is not interruptible.
68 if (unlink(shared_buffer_file.value().c_str()) != 0) {
69 PLOG(WARNING) << "unlink";
70 // This isn't "fatal" (e.g., someone else may have unlinked the file first),
71 // so we may as well continue.
72 }
73
74 // Note: |dup()| is not interruptible (but |dup2()|/|dup3()| are).
75 base::ScopedFD fd(dup(fileno(fp.get())));
76 if (!fd.is_valid()) {
77 PLOG(ERROR) << "dup";
78 return false;
79 }
80
81 if (HANDLE_EINTR(ftruncate(fd.get(), static_cast<off_t>(num_bytes_))) != 0) {
82 PLOG(ERROR) << "ftruncate";
83 return false;
84 }
85
86 handle_.reset(PlatformHandle(fd.release()));
87 return true;
88 }
89
90 bool SimplePlatformSharedBuffer::InitFromPlatformHandle(
91 ScopedPlatformHandle platform_handle) {
92 DCHECK(!handle_.is_valid());
93
94 if (static_cast<uint64_t>(num_bytes_) >
95 static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
96 return false;
97 }
98
99 struct stat sb = {};
100 // Note: |fstat()| isn't interruptible.
101 if (fstat(platform_handle.get().fd, &sb) != 0) {
102 PLOG(ERROR) << "fstat";
103 return false;
104 }
105
106 if (!S_ISREG(sb.st_mode)) {
107 LOG(ERROR) << "Platform handle not to a regular file";
108 return false;
109 }
110
111 if (sb.st_size != static_cast<off_t>(num_bytes_)) {
112 LOG(ERROR) << "Shared memory file has the wrong size";
113 return false;
114 }
115
116 // TODO(vtl): More checks?
117
118 handle_ = platform_handle.Pass();
119 return true;
120 }
121
122 #endif // !defined(OS_ANDROID)
123
124 scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapImpl(
125 size_t offset,
126 size_t length) {
127 size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity();
128 size_t real_offset = offset - offset_rounding;
129 size_t real_length = length + offset_rounding;
130
131 // This should hold (since we checked |num_bytes| versus the maximum value of
132 // |off_t| on creation, but it never hurts to be paranoid.
133 DCHECK_LE(static_cast<uint64_t>(real_offset),
134 static_cast<uint64_t>(std::numeric_limits<off_t>::max()));
135
136 void* real_base =
137 mmap(nullptr, real_length, PROT_READ | PROT_WRITE, MAP_SHARED,
138 handle_.get().fd, static_cast<off_t>(real_offset));
139 // |mmap()| should return |MAP_FAILED| (a.k.a. -1) on error. But it shouldn't
140 // return null either.
141 if (real_base == MAP_FAILED || !real_base) {
142 PLOG(ERROR) << "mmap";
143 return nullptr;
144 }
145
146 void* base = static_cast<char*>(real_base) + offset_rounding;
147 return make_scoped_ptr(new SimplePlatformSharedBufferMapping(
148 base, length, real_base, real_length));
149 }
150
151 // SimplePlatformSharedBufferMapping -------------------------------------------
152
153 void SimplePlatformSharedBufferMapping::Unmap() {
154 int result = munmap(real_base_, real_length_);
155 PLOG_IF(ERROR, result != 0) << "munmap";
156 }
157
158 } // namespace embedder
159 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698