Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / mojo / system / raw_shared_buffer_posix.cc
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/system/raw_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/types.h>  // For |off_t|.
11 #include <unistd.h>
12
13 #include <limits>
14
15 #include "base/file_util.h"
16 #include "base/files/file_path.h"
17 #include "base/files/scoped_file.h"
18 #include "base/logging.h"
19 #include "base/macros.h"
20 #include "base/posix/eintr_wrapper.h"
21 #include "base/sys_info.h"
22 #include "base/threading/thread_restrictions.h"
23 #include "mojo/embedder/platform_handle.h"
24
25 // We assume that |size_t| and |off_t| (type for |ftruncate()|) fits in a
26 // |uint64_t|.
27 COMPILE_ASSERT(sizeof(size_t) <= sizeof(uint64_t), size_t_too_big);
28 COMPILE_ASSERT(sizeof(off_t) <= sizeof(uint64_t), off_t_too_big);
29
30 namespace mojo {
31 namespace system {
32
33 // RawSharedBuffer -------------------------------------------------------------
34
35 bool RawSharedBuffer::InitNoLock() {
36   DCHECK(!handle_.is_valid());
37
38   base::ThreadRestrictions::ScopedAllowIO allow_io;
39
40   if (static_cast<uint64_t>(num_bytes_) >
41           static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
42     return false;
43   }
44
45   // TODO(vtl): This is stupid. The implementation of
46   // |CreateAndOpenTemporaryFileInDir()| starts with an FD, |fdopen()|s to get a
47   // |FILE*|, and then we have to |dup(fileno(fp))| to get back to an FD that we
48   // can own. (base/memory/shared_memory_posix.cc does this too, with more
49   // |fstat()|s thrown in for good measure.)
50   base::FilePath shared_buffer_dir;
51   if (!base::GetShmemTempDir(false, &shared_buffer_dir)) {
52     LOG(ERROR) << "Failed to get temporary directory for shared memory";
53     return false;
54   }
55   base::FilePath shared_buffer_file;
56   base::ScopedFILE fp(base::CreateAndOpenTemporaryFileInDir(
57       shared_buffer_dir, &shared_buffer_file));
58   if (!fp) {
59     LOG(ERROR) << "Failed to create/open temporary file for shared memory";
60     return false;
61   }
62   // Note: |unlink()| is not interruptible.
63   if (unlink(shared_buffer_file.value().c_str()) != 0) {
64     PLOG(WARNING) << "unlink";
65     // This isn't "fatal" (e.g., someone else may have unlinked the file first),
66     // so we may as well continue.
67   }
68
69   // Note: |dup()| is not interruptible (but |dup2()|/|dup3()| are).
70   base::ScopedFD fd(dup(fileno(fp.get())));
71   if (!fd.is_valid()) {
72     PLOG(ERROR) << "dup";
73     return false;
74   }
75
76   if (HANDLE_EINTR(ftruncate(fd.get(), static_cast<off_t>(num_bytes_))) != 0) {
77     PLOG(ERROR) << "ftruncate";
78     return false;
79   }
80
81   handle_.reset(embedder::PlatformHandle(fd.release()));
82   return true;
83 }
84
85 scoped_ptr<RawSharedBufferMapping> RawSharedBuffer::MapImplNoLock(
86     size_t offset,
87     size_t length) {
88   lock_.AssertAcquired();
89
90   size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity();
91   size_t real_offset = offset - offset_rounding;
92   size_t real_length = length + offset_rounding;
93
94   // This should hold (since we checked |num_bytes| versus the maximum value of
95   // |off_t| on creation, but it never hurts to be paranoid.
96   DCHECK_LE(static_cast<uint64_t>(real_offset),
97             static_cast<uint64_t>(std::numeric_limits<off_t>::max()));
98
99   void* real_base = mmap(NULL, real_length, PROT_READ | PROT_WRITE, MAP_SHARED,
100                          handle_.get().fd, static_cast<off_t>(real_offset));
101   // |mmap()| should return |MAP_FAILED| (a.k.a. -1) on error. But it shouldn't
102   // return null either.
103   if (real_base == MAP_FAILED || !real_base) {
104     PLOG(ERROR) << "mmap";
105     return scoped_ptr<RawSharedBufferMapping>();
106   }
107
108   void* base = static_cast<char*>(real_base) + offset_rounding;
109   return make_scoped_ptr(
110       new RawSharedBufferMapping(base, length, real_base, real_length));
111 }
112
113 // RawSharedBufferMapping ------------------------------------------------------
114
115 void RawSharedBufferMapping::Unmap() {
116   int result = munmap(real_base_, real_length_);
117   PLOG_IF(ERROR, result != 0) << "munmap";
118 }
119
120 }  // namespace system
121 }  // namespace mojo