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

Side by Side Diff: ppapi/proxy/file_mapping_resource.cc

Issue 69663002: PPAPI: Implement PPB_FileMapping on POSIX (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rough patch. Starting testing. Created 6 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 | Annotate | Revision Log
« no previous file with comments | « ppapi/proxy/file_mapping_resource.h ('k') | ppapi/proxy/interface_list.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 "ppapi/proxy/file_mapping_resource.h"
6
7 #if defined(OS_POSIX)
8 #include <sys/mman.h>
9 #include <unistd.h>
10 #endif
11
12 #include "base/bind.h"
13 #include "base/safe_numerics.h"
14 #include "base/task_runner_util.h"
15 #include "ppapi/shared_impl/tracked_callback.h"
16 #include "ppapi/shared_impl/var.h"
17 #include "ppapi/thunk/enter.h"
18 #include "ppapi/thunk/ppb_file_io_api.h"
19
20 namespace ppapi {
21 namespace proxy {
22
23 namespace {
24
25 int32_t ErrnoToPPError(int error_code) {
26 switch (error_code) {
27 case EACCES:
28 return PP_ERROR_NOACCESS;
29 case EAGAIN:
30 return PP_ERROR_NOMEMORY;
31 case EINVAL:
32 return PP_ERROR_BADARGUMENT;
33 case ENFILE:
34 case ENOMEM:
35 return PP_ERROR_NOSPACE;
36 default:
37 return PP_ERROR_FAILED;
38 }
39 }
40
41 }
42
43 FileMappingResource::FileMappingResource(Connection connection,
44 PP_Instance instance)
45 : PluginResource(connection, instance) {
46 }
47
48 FileMappingResource::~FileMappingResource() {
49 }
50
51 thunk::PPB_FileMapping_API* FileMappingResource::AsPPB_FileMapping_API() {
52 return this;
53 }
54
55 int32_t FileMappingResource::Map(PP_Instance /* instance */,
56 PP_Resource file_io,
57 int64_t length,
58 uint32_t map_protection,
59 uint32_t map_flags,
60 int64_t offset,
61 void** address,
62 scoped_refptr<TrackedCallback> callback) {
63 thunk::EnterResourceNoLock<thunk::PPB_FileIO_API> enter(file_io, true);
64 if (enter.failed())
65 return PP_ERROR_BADARGUMENT;
66 FileIOResource* file_io_resource =
67 static_cast<FileIOResource*>(enter.object());
68 scoped_refptr<FileIOResource::FileHandleHolder> file_handle =
69 file_io_resource->file_handle();
70 if (!FileIOResource::FileHandleHolder::IsValid(file_handle))
71 return PP_ERROR_BADARGUMENT;
72
73 if (length < 0 || offset < 0)
74 return PP_ERROR_BADARGUMENT;
75 // Ensure no bits that we don't recognize are set.
76 if (map_protection &
77 ~(PP_FILEMAPPROTECTION_READ | PP_FILEMAPPROTECTION_WRITE)) {
78 return PP_ERROR_BADARGUMENT;
79 }
80 if (map_flags &
81 ~(PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE |
82 PP_FILEMAPFLAG_FIXED)) {
83 return PP_ERROR_BADARGUMENT;
84 }
85 // Ensure at least one of SHARED and PRIVATE is set.
86 if (!(map_flags & (PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE)))
87 return PP_ERROR_BADARGUMENT;
88 // Ensure at most one of SHARED and PRIVATE is set.
89 if ((map_flags & PP_FILEMAPFLAG_SHARED) &&
90 (map_flags & PP_FILEMAPFLAG_PRIVATE)) {
91 return PP_ERROR_BADARGUMENT;
92 }
93 if (!address)
94 return PP_ERROR_BADARGUMENT;
95
96 base::Callback<MapResult()> map_op(
97 base::Bind(&FileMappingResource::DoMap, file_handle, *address, length,
98 map_protection, map_flags, offset));
99 if (callback->is_blocking()) {
100 // The plugin could release its reference to this instance when we release
101 // the proxy lock below.
102 scoped_refptr<FileMappingResource> protect(this);
103 MapResult map_result;
104 {
105 // Release the proxy lock while making a potentially slow file call.
106 ProxyAutoUnlock unlock;
107 map_result = map_op.Run();
108 }
109 OnMapCompleted(address, callback, map_result);
110 return map_result.result;
111 } else {
112 base::PostTaskAndReplyWithResult(
113 PpapiGlobals::Get()->GetFileTaskRunner(),
114 FROM_HERE,
115 map_op,
116 RunWhileLocked(Bind(&FileMappingResource::OnMapCompleted,
117 this,
118 base::Unretained(address),
119 callback)));
120 return PP_OK_COMPLETIONPENDING;
121 }
122 }
123
124 void FileMappingResource::Unmap(PP_Instance /* instance */,
125 void* address,
126 int64_t length) {
127 // TODO(dmichael): Is munmap slow enough that I should make this use a
128 // completion callback so it can run in the background? Noting that current
129 // known use-cases are all going to use it synchronously. Main reason for that
130 // would be so we can enforce that it's not done on the main thread.
131 // TODO(dmichael): Return something to indicate failure?
132 #if defined(OS_POSIX)
133 munmap(address, base::checked_numeric_cast<size_t>(length));
134 #else // defined(OS_POSIX)
135 NOTREACHED();
136 #endif
137 }
138
139 int64_t FileMappingResource::GetMapPageSize(PP_Instance /* instance */) {
140 // TODO(dmichael): It might be better to port sys_info_posix.cc to NaCl and
141 // call Sysinfo::VMAllocationGranularity.
142 #if defined(OS_POSIX)
143 return getpagesize();
144 #else // defined(OS_POSIX)
145 NOTREACHED();
146 return 0;
147 #endif
148 }
149
150 // static
151 FileMappingResource::MapResult FileMappingResource::DoMap(
152 scoped_refptr<FileIOResource::FileHandleHolder> handle,
153 void* address_hint,
154 int64_t length,
155 uint32_t map_protection,
156 uint32_t map_flags,
157 int64_t offset) {
158 #if defined(OS_POSIX)
159 int prot_for_mmap = 0;
160 if (map_protection & PP_FILEMAPPROTECTION_READ)
161 prot_for_mmap |= PROT_READ;
162 if (map_protection & PP_FILEMAPPROTECTION_WRITE)
163 prot_for_mmap |= PROT_WRITE;
164 if (prot_for_mmap == 0)
165 prot_for_mmap = PROT_NONE;
166
167 int flags_for_mmap = 0;
168 if (map_flags & PP_FILEMAPFLAG_SHARED)
169 flags_for_mmap |= MAP_SHARED;
170 if (map_flags & PP_FILEMAPFLAG_PRIVATE)
171 flags_for_mmap |= MAP_PRIVATE;
172 if (map_flags & PP_FILEMAPFLAG_FIXED)
173 flags_for_mmap |= MAP_FIXED;
174
175 MapResult map_result;
176 map_result.address =
177 mmap(address_hint,
178 base::checked_numeric_cast<size_t>(length),
179 prot_for_mmap,
180 flags_for_mmap,
181 handle->raw_handle(),
182 base::checked_numeric_cast<off_t>(offset));
183 if (map_result.address != MAP_FAILED)
184 map_result.result = PP_OK;
185 else
186 map_result.result = ErrnoToPPError(errno);
187 #else // defined(OS_POSIX)
188 // TODO(dmichael): Implement for Windows (crbug.com/83774).
189 NOTIMPLEMENTED();
190 #endif
191 return MapResult();
192 }
193
194 void FileMappingResource::OnMapCompleted(
195 void** mapped_address_out_param,
196 scoped_refptr<TrackedCallback> callback,
197 const MapResult& map_result) {
198 // TODO(dmichael): If the callback is aborted, should we unmap?
199 if (callback->aborted())
200 return;
201 if (map_result.result == 0)
202 *mapped_address_out_param = map_result.address;
203 if (!callback->is_blocking())
204 callback->Run(map_result.result);
205 }
206
207
208 } // namespace proxy
209 } // namespace ppapi
OLDNEW
« no previous file with comments | « ppapi/proxy/file_mapping_resource.h ('k') | ppapi/proxy/interface_list.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698