Mojo: Add a platform interface for shared memory (embedder::PlatformSharedBuffer).

Make the existing RawSharedBuffer an implementation of that. Later,
we'll plumb in a "PlatformSupport" that'll produce these things, but for
now keep the (static) creation methods where they are.

R=darin@chromium.org

Review URL: https://codereview.chromium.org/471773002

Cr-Commit-Position: refs/heads/master@{#289667}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289667 0039d316-1c4b-4281-b951-d872f2087c98
parent 3d143b09
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_EMBEDDER_PLATFORM_SHARED_BUFFER_H_
#define MOJO_EMBEDDER_PLATFORM_SHARED_BUFFER_H_
#include <stddef.h>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "mojo/embedder/scoped_platform_handle.h"
#include "mojo/system/system_impl_export.h"
namespace mojo {
namespace embedder {
class PlatformSharedBufferMapping;
// |PlatformSharedBuffer| is an interface for a thread-safe, ref-counted wrapper
// around OS-specific shared memory. It has the following features:
// - A |PlatformSharedBuffer| simply represents a piece of shared memory that
// *may* be mapped and *may* be shared to another process.
// - A single |PlatformSharedBuffer| may be mapped multiple times. The
// lifetime of the mapping (owned by |PlatformSharedBufferMapping|) is
// separate from the lifetime of the |PlatformSharedBuffer|.
// - Sizes/offsets (of the shared memory and mappings) are arbitrary, and not
// restricted by page size. However, more memory may actually be mapped than
// requested.
//
// It currently does NOT support the following:
// - Sharing read-only. (This will probably eventually be supported.)
//
// TODO(vtl): Rectify this with |base::SharedMemory|.
class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer
: public base::RefCountedThreadSafe<PlatformSharedBuffer> {
public:
// Gets the size of shared buffer (in number of bytes).
virtual size_t GetNumBytes() const = 0;
// Maps (some) of the shared buffer into memory; [|offset|, |offset + length|]
// must be contained in [0, |num_bytes|], and |length| must be at least 1.
// Returns null on failure.
virtual scoped_ptr<PlatformSharedBufferMapping> Map(size_t offset,
size_t length) = 0;
// Checks if |offset| and |length| are valid arguments.
virtual bool IsValidMap(size_t offset, size_t length) = 0;
// Like |Map()|, but doesn't check its arguments (which should have been
// preflighted using |IsValidMap()|).
virtual scoped_ptr<PlatformSharedBufferMapping> MapNoCheck(size_t offset,
size_t length) = 0;
// Duplicates the underlying platform handle and passes it to the caller.
// TODO(vtl): On POSIX, we'll need two FDs to support sharing read-only.
virtual ScopedPlatformHandle DuplicatePlatformHandle() = 0;
// Passes the underlying platform handle to the caller. This should only be
// called if there's a unique reference to this object (owned by the caller).
// After calling this, this object should no longer be used, but should only
// be disposed of.
virtual ScopedPlatformHandle PassPlatformHandle() = 0;
protected:
friend class base::RefCountedThreadSafe<PlatformSharedBuffer>;
PlatformSharedBuffer() {}
virtual ~PlatformSharedBuffer() {}
private:
DISALLOW_COPY_AND_ASSIGN(PlatformSharedBuffer);
};
// An interface for a mapping of a |PlatformSharedBuffer| (compararable to a
// "file view" in Windows); see above. Created by (implementations of)
// |PlatformSharedBuffer::Map()|. Automatically unmaps memory on destruction.
//
// Mappings are NOT thread-safe.
//
// Note: This is an entirely separate class (instead of
// |PlatformSharedBuffer::Mapping|) so that it can be forward-declared.
class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBufferMapping {
public:
// IMPORTANT: Implementations must implement a destructor that unmaps memory.
virtual ~PlatformSharedBufferMapping() {}
virtual void* GetBase() const = 0;
virtual size_t GetLength() const = 0;
protected:
PlatformSharedBufferMapping() {}
private:
DISALLOW_COPY_AND_ASSIGN(PlatformSharedBufferMapping);
};
} // namespace embedder
} // namespace mojo
#endif // MOJO_EMBEDDER_PLATFORM_SHARED_BUFFER_H_
...@@ -108,6 +108,7 @@ ...@@ -108,6 +108,7 @@
'embedder/platform_handle_utils_posix.cc', 'embedder/platform_handle_utils_posix.cc',
'embedder/platform_handle_utils_win.cc', 'embedder/platform_handle_utils_win.cc',
'embedder/platform_handle_vector.h', 'embedder/platform_handle_vector.h',
'embedder/platform_shared_buffer.h',
'embedder/scoped_platform_handle.h', 'embedder/scoped_platform_handle.h',
'system/channel.cc', 'system/channel.cc',
'system/channel.h', 'system/channel.h',
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "mojo/embedder/platform_shared_buffer.h"
#include "mojo/public/c/system/macros.h" #include "mojo/public/c/system/macros.h"
#include "mojo/system/constants.h" #include "mojo/system/constants.h"
#include "mojo/system/data_pipe.h" #include "mojo/system/data_pipe.h"
...@@ -19,7 +20,6 @@ ...@@ -19,7 +20,6 @@
#include "mojo/system/memory.h" #include "mojo/system/memory.h"
#include "mojo/system/message_pipe.h" #include "mojo/system/message_pipe.h"
#include "mojo/system/message_pipe_dispatcher.h" #include "mojo/system/message_pipe_dispatcher.h"
#include "mojo/system/raw_shared_buffer.h"
#include "mojo/system/shared_buffer_dispatcher.h" #include "mojo/system/shared_buffer_dispatcher.h"
#include "mojo/system/waiter.h" #include "mojo/system/waiter.h"
...@@ -516,13 +516,13 @@ MojoResult Core::MapBuffer(MojoHandle buffer_handle, ...@@ -516,13 +516,13 @@ MojoResult Core::MapBuffer(MojoHandle buffer_handle,
if (!dispatcher) if (!dispatcher)
return MOJO_RESULT_INVALID_ARGUMENT; return MOJO_RESULT_INVALID_ARGUMENT;
scoped_ptr<RawSharedBufferMapping> mapping; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping);
if (result != MOJO_RESULT_OK) if (result != MOJO_RESULT_OK)
return result; return result;
DCHECK(mapping); DCHECK(mapping);
void* address = mapping->base(); void* address = mapping->GetBase();
{ {
base::AutoLock locker(mapping_table_lock_); base::AutoLock locker(mapping_table_lock_);
result = mapping_table_.AddMapping(mapping.Pass()); result = mapping_table_.AddMapping(mapping.Pass());
......
...@@ -199,10 +199,11 @@ MojoResult Dispatcher::DuplicateBufferHandle( ...@@ -199,10 +199,11 @@ MojoResult Dispatcher::DuplicateBufferHandle(
return DuplicateBufferHandleImplNoLock(options, new_dispatcher); return DuplicateBufferHandleImplNoLock(options, new_dispatcher);
} }
MojoResult Dispatcher::MapBuffer(uint64_t offset, MojoResult Dispatcher::MapBuffer(
uint64_t offset,
uint64_t num_bytes, uint64_t num_bytes,
MojoMapBufferFlags flags, MojoMapBufferFlags flags,
scoped_ptr<RawSharedBufferMapping>* mapping) { scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) {
base::AutoLock locker(lock_); base::AutoLock locker(lock_);
if (is_closed_) if (is_closed_)
return MOJO_RESULT_INVALID_ARGUMENT; return MOJO_RESULT_INVALID_ARGUMENT;
...@@ -353,7 +354,7 @@ MojoResult Dispatcher::MapBufferImplNoLock( ...@@ -353,7 +354,7 @@ MojoResult Dispatcher::MapBufferImplNoLock(
uint64_t /*offset*/, uint64_t /*offset*/,
uint64_t /*num_bytes*/, uint64_t /*num_bytes*/,
MojoMapBufferFlags /*flags*/, MojoMapBufferFlags /*flags*/,
scoped_ptr<RawSharedBufferMapping>* /*mapping*/) { scoped_ptr<embedder::PlatformSharedBufferMapping>* /*mapping*/) {
lock_.AssertAcquired(); lock_.AssertAcquired();
DCHECK(!is_closed_); DCHECK(!is_closed_);
// By default, not supported. Only needed for buffer dispatchers. // By default, not supported. Only needed for buffer dispatchers.
......
...@@ -25,6 +25,11 @@ ...@@ -25,6 +25,11 @@
#include "mojo/system/system_impl_export.h" #include "mojo/system/system_impl_export.h"
namespace mojo { namespace mojo {
namespace embedder {
class PlatformSharedBufferMapping;
}
namespace system { namespace system {
class Channel; class Channel;
...@@ -34,7 +39,6 @@ class DispatcherTransport; ...@@ -34,7 +39,6 @@ class DispatcherTransport;
class HandleTable; class HandleTable;
class LocalMessagePipeEndpoint; class LocalMessagePipeEndpoint;
class ProxyMessagePipeEndpoint; class ProxyMessagePipeEndpoint;
class RawSharedBufferMapping;
class TransportData; class TransportData;
class Waiter; class Waiter;
...@@ -113,10 +117,11 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher ...@@ -113,10 +117,11 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
MojoResult DuplicateBufferHandle( MojoResult DuplicateBufferHandle(
UserPointer<const MojoDuplicateBufferHandleOptions> options, UserPointer<const MojoDuplicateBufferHandleOptions> options,
scoped_refptr<Dispatcher>* new_dispatcher); scoped_refptr<Dispatcher>* new_dispatcher);
MojoResult MapBuffer(uint64_t offset, MojoResult MapBuffer(
uint64_t offset,
uint64_t num_bytes, uint64_t num_bytes,
MojoMapBufferFlags flags, MojoMapBufferFlags flags,
scoped_ptr<RawSharedBufferMapping>* mapping); scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping);
// Gets the current handle signals state. (The default implementation simply // Gets the current handle signals state. (The default implementation simply
// returns a default-constructed |HandleSignalsState|, i.e., no signals // returns a default-constructed |HandleSignalsState|, i.e., no signals
...@@ -260,7 +265,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher ...@@ -260,7 +265,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
uint64_t offset, uint64_t offset,
uint64_t num_bytes, uint64_t num_bytes,
MojoMapBufferFlags flags, MojoMapBufferFlags flags,
scoped_ptr<RawSharedBufferMapping>* mapping); scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping);
virtual HandleSignalsState GetHandleSignalsStateImplNoLock() const; virtual HandleSignalsState GetHandleSignalsStateImplNoLock() const;
virtual MojoResult AddWaiterImplNoLock(Waiter* waiter, virtual MojoResult AddWaiterImplNoLock(Waiter* waiter,
MojoHandleSignals signals, MojoHandleSignals signals,
......
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
#include "base/memory/scoped_vector.h" #include "base/memory/scoped_vector.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "base/threading/simple_thread.h" #include "base/threading/simple_thread.h"
#include "mojo/embedder/platform_shared_buffer.h"
#include "mojo/system/memory.h" #include "mojo/system/memory.h"
#include "mojo/system/raw_shared_buffer.h"
#include "mojo/system/waiter.h" #include "mojo/system/waiter.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -223,7 +223,7 @@ class ThreadSafetyStressThread : public base::SimpleThread { ...@@ -223,7 +223,7 @@ class ThreadSafetyStressThread : public base::SimpleThread {
break; break;
} }
case MAP_BUFFER: { case MAP_BUFFER: {
scoped_ptr<RawSharedBufferMapping> unused; scoped_ptr<embedder::PlatformSharedBufferMapping> unused;
EXPECT_EQ( EXPECT_EQ(
MOJO_RESULT_INVALID_ARGUMENT, MOJO_RESULT_INVALID_ARGUMENT,
dispatcher_->MapBuffer(0u, 0u, MOJO_MAP_BUFFER_FLAG_NONE, &unused)); dispatcher_->MapBuffer(0u, 0u, MOJO_MAP_BUFFER_FLAG_NONE, &unused));
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
#include "mojo/system/mapping_table.h" #include "mojo/system/mapping_table.h"
#include "base/logging.h" #include "base/logging.h"
#include "mojo/embedder/platform_shared_buffer.h"
#include "mojo/system/constants.h" #include "mojo/system/constants.h"
#include "mojo/system/raw_shared_buffer.h"
namespace mojo { namespace mojo {
namespace system { namespace system {
...@@ -20,13 +20,13 @@ MappingTable::~MappingTable() { ...@@ -20,13 +20,13 @@ MappingTable::~MappingTable() {
} }
MojoResult MappingTable::AddMapping( MojoResult MappingTable::AddMapping(
scoped_ptr<RawSharedBufferMapping> mapping) { scoped_ptr<embedder::PlatformSharedBufferMapping> mapping) {
DCHECK(mapping); DCHECK(mapping);
if (address_to_mapping_map_.size() >= kMaxMappingTableSize) if (address_to_mapping_map_.size() >= kMaxMappingTableSize)
return MOJO_RESULT_RESOURCE_EXHAUSTED; return MOJO_RESULT_RESOURCE_EXHAUSTED;
uintptr_t address = reinterpret_cast<uintptr_t>(mapping->base()); uintptr_t address = reinterpret_cast<uintptr_t>(mapping->GetBase());
DCHECK(address_to_mapping_map_.find(address) == DCHECK(address_to_mapping_map_.find(address) ==
address_to_mapping_map_.end()); address_to_mapping_map_.end());
address_to_mapping_map_[address] = mapping.release(); address_to_mapping_map_[address] = mapping.release();
...@@ -37,7 +37,7 @@ MojoResult MappingTable::RemoveMapping(uintptr_t address) { ...@@ -37,7 +37,7 @@ MojoResult MappingTable::RemoveMapping(uintptr_t address) {
AddressToMappingMap::iterator it = address_to_mapping_map_.find(address); AddressToMappingMap::iterator it = address_to_mapping_map_.find(address);
if (it == address_to_mapping_map_.end()) if (it == address_to_mapping_map_.end())
return MOJO_RESULT_INVALID_ARGUMENT; return MOJO_RESULT_INVALID_ARGUMENT;
RawSharedBufferMapping* mapping_to_delete = it->second; embedder::PlatformSharedBufferMapping* mapping_to_delete = it->second;
address_to_mapping_map_.erase(it); address_to_mapping_map_.erase(it);
delete mapping_to_delete; delete mapping_to_delete;
return MOJO_RESULT_OK; return MOJO_RESULT_OK;
......
...@@ -16,10 +16,14 @@ ...@@ -16,10 +16,14 @@
#include "mojo/system/system_impl_export.h" #include "mojo/system/system_impl_export.h"
namespace mojo { namespace mojo {
namespace embedder {
class PlatformSharedBufferMapping;
}
namespace system { namespace system {
class Core; class Core;
class RawSharedBufferMapping;
// Test-only function (defined/used in embedder/test_embedder.cc). Declared here // Test-only function (defined/used in embedder/test_embedder.cc). Declared here
// so it can be friended. // so it can be friended.
...@@ -28,7 +32,7 @@ bool ShutdownCheckNoLeaks(Core*); ...@@ -28,7 +32,7 @@ bool ShutdownCheckNoLeaks(Core*);
} }
// This class provides the (global) table of memory mappings (owned by |Core|), // This class provides the (global) table of memory mappings (owned by |Core|),
// which maps mapping base addresses to |RawSharedBuffer::Mapping|s. // which maps mapping base addresses to |PlatformSharedBufferMapping|s.
// //
// This class is NOT thread-safe; locking is left to |Core|. // This class is NOT thread-safe; locking is left to |Core|.
class MOJO_SYSTEM_IMPL_EXPORT MappingTable { class MOJO_SYSTEM_IMPL_EXPORT MappingTable {
...@@ -38,13 +42,14 @@ class MOJO_SYSTEM_IMPL_EXPORT MappingTable { ...@@ -38,13 +42,14 @@ class MOJO_SYSTEM_IMPL_EXPORT MappingTable {
// Tries to add a mapping. (Takes ownership of the mapping in all cases; on // Tries to add a mapping. (Takes ownership of the mapping in all cases; on
// failure, it will be destroyed.) // failure, it will be destroyed.)
MojoResult AddMapping(scoped_ptr<RawSharedBufferMapping> mapping); MojoResult AddMapping(
scoped_ptr<embedder::PlatformSharedBufferMapping> mapping);
MojoResult RemoveMapping(uintptr_t address); MojoResult RemoveMapping(uintptr_t address);
private: private:
friend bool internal::ShutdownCheckNoLeaks(Core*); friend bool internal::ShutdownCheckNoLeaks(Core*);
typedef base::hash_map<uintptr_t, RawSharedBufferMapping*> typedef base::hash_map<uintptr_t, embedder::PlatformSharedBufferMapping*>
AddressToMappingMap; AddressToMappingMap;
AddressToMappingMap address_to_mapping_map_; AddressToMappingMap address_to_mapping_map_;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "build/build_config.h" // TODO(vtl): Remove this. #include "build/build_config.h" // TODO(vtl): Remove this.
#include "mojo/common/test/multiprocess_test_helper.h" #include "mojo/common/test/multiprocess_test_helper.h"
#include "mojo/common/test/test_utils.h" #include "mojo/common/test/test_utils.h"
#include "mojo/embedder/platform_shared_buffer.h"
#include "mojo/embedder/scoped_platform_handle.h" #include "mojo/embedder/scoped_platform_handle.h"
#include "mojo/system/channel.h" #include "mojo/system/channel.h"
#include "mojo/system/dispatcher.h" #include "mojo/system/dispatcher.h"
...@@ -29,7 +30,6 @@ ...@@ -29,7 +30,6 @@
#include "mojo/system/platform_handle_dispatcher.h" #include "mojo/system/platform_handle_dispatcher.h"
#include "mojo/system/proxy_message_pipe_endpoint.h" #include "mojo/system/proxy_message_pipe_endpoint.h"
#include "mojo/system/raw_channel.h" #include "mojo/system/raw_channel.h"
#include "mojo/system/raw_shared_buffer.h"
#include "mojo/system/shared_buffer_dispatcher.h" #include "mojo/system/shared_buffer_dispatcher.h"
#include "mojo/system/test_utils.h" #include "mojo/system/test_utils.h"
#include "mojo/system/waiter.h" #include "mojo/system/waiter.h"
...@@ -358,16 +358,16 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { ...@@ -358,16 +358,16 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) {
static_cast<SharedBufferDispatcher*>(dispatchers[0].get())); static_cast<SharedBufferDispatcher*>(dispatchers[0].get()));
// Make a mapping. // Make a mapping.
scoped_ptr<RawSharedBufferMapping> mapping; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
CHECK_EQ(dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping), CHECK_EQ(dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping),
MOJO_RESULT_OK); MOJO_RESULT_OK);
CHECK(mapping); CHECK(mapping);
CHECK(mapping->base()); CHECK(mapping->GetBase());
CHECK_EQ(mapping->length(), 100u); CHECK_EQ(mapping->GetLength(), 100u);
// Write some stuff to the shared buffer. // Write some stuff to the shared buffer.
static const char kHello[] = "hello"; static const char kHello[] = "hello";
memcpy(mapping->base(), kHello, sizeof(kHello)); memcpy(mapping->GetBase(), kHello, sizeof(kHello));
// We should be able to close the dispatcher now. // We should be able to close the dispatcher now.
dispatcher->Close(); dispatcher->Close();
...@@ -404,7 +404,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { ...@@ -404,7 +404,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) {
// It should have written something to the shared buffer. // It should have written something to the shared buffer.
static const char kWorld[] = "world!!!"; static const char kWorld[] = "world!!!";
CHECK_EQ(memcmp(mapping->base(), kWorld, sizeof(kWorld)), 0); CHECK_EQ(memcmp(mapping->GetBase(), kWorld, sizeof(kWorld)), 0);
// And we're done. // And we're done.
mp->Close(0); mp->Close(0);
...@@ -435,12 +435,12 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { ...@@ -435,12 +435,12 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) {
ASSERT_TRUE(dispatcher); ASSERT_TRUE(dispatcher);
// Make a mapping. // Make a mapping.
scoped_ptr<RawSharedBufferMapping> mapping; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
EXPECT_EQ(MOJO_RESULT_OK, EXPECT_EQ(MOJO_RESULT_OK,
dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
ASSERT_TRUE(mapping); ASSERT_TRUE(mapping);
ASSERT_TRUE(mapping->base()); ASSERT_TRUE(mapping->GetBase());
ASSERT_EQ(100u, mapping->length()); ASSERT_EQ(100u, mapping->GetLength());
// Send the shared buffer. // Send the shared buffer.
const std::string go1("go 1"); const std::string go1("go 1");
...@@ -483,11 +483,11 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { ...@@ -483,11 +483,11 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) {
// After we get it, the child should have written something to the shared // After we get it, the child should have written something to the shared
// buffer. // buffer.
static const char kHello[] = "hello"; static const char kHello[] = "hello";
EXPECT_EQ(0, memcmp(mapping->base(), kHello, sizeof(kHello))); EXPECT_EQ(0, memcmp(mapping->GetBase(), kHello, sizeof(kHello)));
// Now we'll write some stuff to the shared buffer. // Now we'll write some stuff to the shared buffer.
static const char kWorld[] = "world!!!"; static const char kWorld[] = "world!!!";
memcpy(mapping->base(), kWorld, sizeof(kWorld)); memcpy(mapping->GetBase(), kWorld, sizeof(kWorld));
// And send a message to signal that we've written stuff. // And send a message to signal that we've written stuff.
const std::string go3("go 3"); const std::string go3("go 3");
......
...@@ -25,6 +25,7 @@ RawSharedBuffer* RawSharedBuffer::Create(size_t num_bytes) { ...@@ -25,6 +25,7 @@ RawSharedBuffer* RawSharedBuffer::Create(size_t num_bytes) {
return rv; return rv;
} }
// static
RawSharedBuffer* RawSharedBuffer::CreateFromPlatformHandle( RawSharedBuffer* RawSharedBuffer::CreateFromPlatformHandle(
size_t num_bytes, size_t num_bytes,
embedder::ScopedPlatformHandle platform_handle) { embedder::ScopedPlatformHandle platform_handle) {
...@@ -41,10 +42,15 @@ RawSharedBuffer* RawSharedBuffer::CreateFromPlatformHandle( ...@@ -41,10 +42,15 @@ RawSharedBuffer* RawSharedBuffer::CreateFromPlatformHandle(
return rv; return rv;
} }
scoped_ptr<RawSharedBufferMapping> RawSharedBuffer::Map(size_t offset, size_t RawSharedBuffer::GetNumBytes() const {
return num_bytes_;
}
scoped_ptr<embedder::PlatformSharedBufferMapping> RawSharedBuffer::Map(
size_t offset,
size_t length) { size_t length) {
if (!IsValidMap(offset, length)) if (!IsValidMap(offset, length))
return scoped_ptr<RawSharedBufferMapping>(); return scoped_ptr<embedder::PlatformSharedBufferMapping>();
return MapNoCheck(offset, length); return MapNoCheck(offset, length);
} }
...@@ -61,7 +67,8 @@ bool RawSharedBuffer::IsValidMap(size_t offset, size_t length) { ...@@ -61,7 +67,8 @@ bool RawSharedBuffer::IsValidMap(size_t offset, size_t length) {
return true; return true;
} }
scoped_ptr<RawSharedBufferMapping> RawSharedBuffer::MapNoCheck(size_t offset, scoped_ptr<embedder::PlatformSharedBufferMapping> RawSharedBuffer::MapNoCheck(
size_t offset,
size_t length) { size_t length) {
DCHECK(IsValidMap(offset, length)); DCHECK(IsValidMap(offset, length));
return MapImpl(offset, length); return MapImpl(offset, length);
...@@ -82,5 +89,17 @@ RawSharedBuffer::RawSharedBuffer(size_t num_bytes) : num_bytes_(num_bytes) { ...@@ -82,5 +89,17 @@ RawSharedBuffer::RawSharedBuffer(size_t num_bytes) : num_bytes_(num_bytes) {
RawSharedBuffer::~RawSharedBuffer() { RawSharedBuffer::~RawSharedBuffer() {
} }
RawSharedBufferMapping::~RawSharedBufferMapping() {
Unmap();
}
void* RawSharedBufferMapping::GetBase() const {
return base_;
}
size_t RawSharedBufferMapping::GetLength() const {
return length_;
}
} // namespace system } // namespace system
} // namespace mojo } // namespace mojo
...@@ -8,33 +8,15 @@ ...@@ -8,33 +8,15 @@
#include <stddef.h> #include <stddef.h>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "mojo/embedder/platform_shared_buffer.h"
#include "base/memory/scoped_ptr.h"
#include "mojo/embedder/scoped_platform_handle.h"
#include "mojo/system/system_impl_export.h" #include "mojo/system/system_impl_export.h"
namespace mojo { namespace mojo {
namespace system { namespace system {
class RawSharedBufferMapping; // A simple implementation of |embedder::PlatformSharedBuffer|.
// |RawSharedBuffer| is a thread-safe, ref-counted wrapper around OS-specific
// shared memory. It has the following features:
// - A |RawSharedBuffer| simply represents a piece of shared memory that *may*
// be mapped and *may* be shared to another process.
// - A single |RawSharedBuffer| may be mapped multiple times. The lifetime of
// the mapping (owned by |RawSharedBufferMapping|) is separate from the
// lifetime of the |RawSharedBuffer|.
// - Sizes/offsets (of the shared memory and mappings) are arbitrary, and not
// restricted by page size. However, more memory may actually be mapped than
// requested.
//
// It currently does NOT support the following:
// - Sharing read-only. (This will probably eventually be supported.)
//
// TODO(vtl): Rectify this with |base::SharedMemory|.
class MOJO_SYSTEM_IMPL_EXPORT RawSharedBuffer class MOJO_SYSTEM_IMPL_EXPORT RawSharedBuffer
: public base::RefCountedThreadSafe<RawSharedBuffer> { : public embedder::PlatformSharedBuffer {
public: public:
// Creates a shared buffer of size |num_bytes| bytes (initially zero-filled). // Creates a shared buffer of size |num_bytes| bytes (initially zero-filled).
// |num_bytes| must be nonzero. Returns null on failure. // |num_bytes| must be nonzero. Returns null on failure.
...@@ -44,34 +26,21 @@ class MOJO_SYSTEM_IMPL_EXPORT RawSharedBuffer ...@@ -44,34 +26,21 @@ class MOJO_SYSTEM_IMPL_EXPORT RawSharedBuffer
size_t num_bytes, size_t num_bytes,
embedder::ScopedPlatformHandle platform_handle); embedder::ScopedPlatformHandle platform_handle);
// Maps (some) of the shared buffer into memory; [|offset|, |offset + length|] // |embedder::PlatformSharedBuffer| implementation:
// must be contained in [0, |num_bytes|], and |length| must be at least 1. virtual size_t GetNumBytes() const OVERRIDE;
// Returns null on failure. virtual scoped_ptr<embedder::PlatformSharedBufferMapping> Map(
scoped_ptr<RawSharedBufferMapping> Map(size_t offset, size_t length); size_t offset,
size_t length) OVERRIDE;
// Checks if |offset| and |length| are valid arguments. virtual bool IsValidMap(size_t offset, size_t length) OVERRIDE;
bool IsValidMap(size_t offset, size_t length); virtual scoped_ptr<embedder::PlatformSharedBufferMapping> MapNoCheck(
size_t offset,
// Like |Map()|, but doesn't check its arguments (which should have been size_t length) OVERRIDE;
// preflighted using |IsValidMap()|). virtual embedder::ScopedPlatformHandle DuplicatePlatformHandle() OVERRIDE;
scoped_ptr<RawSharedBufferMapping> MapNoCheck(size_t offset, size_t length); virtual embedder::ScopedPlatformHandle PassPlatformHandle() OVERRIDE;
// Duplicates the underlying platform handle and passes it to the caller.
embedder::ScopedPlatformHandle DuplicatePlatformHandle();
// Passes the underlying platform handle to the caller. This should only be
// called if there's a unique reference to this object (owned by the caller).
// After calling this, this object should no longer be used, but should only
// be disposed of.
embedder::ScopedPlatformHandle PassPlatformHandle();
size_t num_bytes() const { return num_bytes_; }
private: private:
friend class base::RefCountedThreadSafe<RawSharedBuffer>;
explicit RawSharedBuffer(size_t num_bytes); explicit RawSharedBuffer(size_t num_bytes);
~RawSharedBuffer(); virtual ~RawSharedBuffer();
// Implemented in raw_shared_buffer_{posix,win}.cc: // Implemented in raw_shared_buffer_{posix,win}.cc:
...@@ -84,7 +53,8 @@ class MOJO_SYSTEM_IMPL_EXPORT RawSharedBuffer ...@@ -84,7 +53,8 @@ class MOJO_SYSTEM_IMPL_EXPORT RawSharedBuffer
bool InitFromPlatformHandle(embedder::ScopedPlatformHandle platform_handle); bool InitFromPlatformHandle(embedder::ScopedPlatformHandle platform_handle);
// The platform-dependent part of |Map()|; doesn't check arguments. // The platform-dependent part of |Map()|; doesn't check arguments.
scoped_ptr<RawSharedBufferMapping> MapImpl(size_t offset, size_t length); scoped_ptr<embedder::PlatformSharedBufferMapping> MapImpl(size_t offset,
size_t length);
const size_t num_bytes_; const size_t num_bytes_;
...@@ -96,20 +66,15 @@ class MOJO_SYSTEM_IMPL_EXPORT RawSharedBuffer ...@@ -96,20 +66,15 @@ class MOJO_SYSTEM_IMPL_EXPORT RawSharedBuffer
DISALLOW_COPY_AND_ASSIGN(RawSharedBuffer); DISALLOW_COPY_AND_ASSIGN(RawSharedBuffer);
}; };
// A mapping of a |RawSharedBuffer| (compararable to a "file view" in Windows); // An implementation of |embedder::PlatformSharedBufferMapping|, produced by
// see above. Created by |RawSharedBuffer::Map()|. Automatically unmaps memory // |RawSharedBuffer|.
// on destruction. class MOJO_SYSTEM_IMPL_EXPORT RawSharedBufferMapping
// : public embedder::PlatformSharedBufferMapping {
// Mappings are NOT thread-safe.
//
// Note: This is an entirely separate class (instead of
// |RawSharedBuffer::Mapping|) so that it can be forward-declared.
class MOJO_SYSTEM_IMPL_EXPORT RawSharedBufferMapping {
public: public:
~RawSharedBufferMapping() { Unmap(); } virtual ~RawSharedBufferMapping();
void* base() const { return base_; } virtual void* GetBase() const OVERRIDE;
size_t length() const { return length_; } virtual size_t GetLength() const OVERRIDE;
private: private:
friend class RawSharedBuffer; friend class RawSharedBuffer;
......
...@@ -115,7 +115,8 @@ bool RawSharedBuffer::InitFromPlatformHandle( ...@@ -115,7 +115,8 @@ bool RawSharedBuffer::InitFromPlatformHandle(
return true; return true;
} }
scoped_ptr<RawSharedBufferMapping> RawSharedBuffer::MapImpl(size_t offset, scoped_ptr<embedder::PlatformSharedBufferMapping> RawSharedBuffer::MapImpl(
size_t offset,
size_t length) { size_t length) {
size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity(); size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity();
size_t real_offset = offset - offset_rounding; size_t real_offset = offset - offset_rounding;
...@@ -136,11 +137,11 @@ scoped_ptr<RawSharedBufferMapping> RawSharedBuffer::MapImpl(size_t offset, ...@@ -136,11 +137,11 @@ scoped_ptr<RawSharedBufferMapping> RawSharedBuffer::MapImpl(size_t offset,
// return null either. // return null either.
if (real_base == MAP_FAILED || !real_base) { if (real_base == MAP_FAILED || !real_base) {
PLOG(ERROR) << "mmap"; PLOG(ERROR) << "mmap";
return scoped_ptr<RawSharedBufferMapping>(); return scoped_ptr<embedder::PlatformSharedBufferMapping>();
} }
void* base = static_cast<char*>(real_base) + offset_rounding; void* base = static_cast<char*>(real_base) + offset_rounding;
return make_scoped_ptr( return scoped_ptr<embedder::PlatformSharedBufferMapping>(
new RawSharedBufferMapping(base, length, real_base, real_length)); new RawSharedBufferMapping(base, length, real_base, real_length));
} }
......
...@@ -28,10 +28,11 @@ TEST(RawSharedBufferTest, Basic) { ...@@ -28,10 +28,11 @@ TEST(RawSharedBufferTest, Basic) {
// Map it all, scribble some stuff, and then unmap it. // Map it all, scribble some stuff, and then unmap it.
{ {
EXPECT_TRUE(buffer->IsValidMap(0, kNumBytes)); EXPECT_TRUE(buffer->IsValidMap(0, kNumBytes));
scoped_ptr<RawSharedBufferMapping> mapping(buffer->Map(0, kNumBytes)); scoped_ptr<embedder::PlatformSharedBufferMapping> mapping(
buffer->Map(0, kNumBytes));
ASSERT_TRUE(mapping); ASSERT_TRUE(mapping);
ASSERT_TRUE(mapping->base()); ASSERT_TRUE(mapping->GetBase());
int* stuff = static_cast<int*>(mapping->base()); int* stuff = static_cast<int*>(mapping->GetBase());
for (size_t i = 0; i < kNumInts; i++) for (size_t i = 0; i < kNumInts; i++)
stuff[i] = static_cast<int>(i) + kFudge; stuff[i] = static_cast<int>(i) + kFudge;
} }
...@@ -43,19 +44,19 @@ TEST(RawSharedBufferTest, Basic) { ...@@ -43,19 +44,19 @@ TEST(RawSharedBufferTest, Basic) {
{ {
ASSERT_TRUE(buffer->IsValidMap(0, kNumBytes)); ASSERT_TRUE(buffer->IsValidMap(0, kNumBytes));
// Use |MapNoCheck()| this time. // Use |MapNoCheck()| this time.
scoped_ptr<RawSharedBufferMapping> mapping1( scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1(
buffer->MapNoCheck(0, kNumBytes)); buffer->MapNoCheck(0, kNumBytes));
ASSERT_TRUE(mapping1); ASSERT_TRUE(mapping1);
ASSERT_TRUE(mapping1->base()); ASSERT_TRUE(mapping1->GetBase());
int* stuff1 = static_cast<int*>(mapping1->base()); int* stuff1 = static_cast<int*>(mapping1->GetBase());
for (size_t i = 0; i < kNumInts; i++) for (size_t i = 0; i < kNumInts; i++)
EXPECT_EQ(static_cast<int>(i) + kFudge, stuff1[i]) << i; EXPECT_EQ(static_cast<int>(i) + kFudge, stuff1[i]) << i;
scoped_ptr<RawSharedBufferMapping> mapping2( scoped_ptr<embedder::PlatformSharedBufferMapping> mapping2(
buffer->Map((kNumInts / 2) * sizeof(int), 2 * sizeof(int))); buffer->Map((kNumInts / 2) * sizeof(int), 2 * sizeof(int)));
ASSERT_TRUE(mapping2); ASSERT_TRUE(mapping2);
ASSERT_TRUE(mapping2->base()); ASSERT_TRUE(mapping2->GetBase());
int* stuff2 = static_cast<int*>(mapping2->base()); int* stuff2 = static_cast<int*>(mapping2->GetBase());
EXPECT_EQ(static_cast<int>(kNumInts / 2) + kFudge, stuff2[0]); EXPECT_EQ(static_cast<int>(kNumInts / 2) + kFudge, stuff2[0]);
EXPECT_EQ(static_cast<int>(kNumInts / 2) + 1 + kFudge, stuff2[1]); EXPECT_EQ(static_cast<int>(kNumInts / 2) + 1 + kFudge, stuff2[1]);
...@@ -75,11 +76,11 @@ TEST(RawSharedBufferTest, Basic) { ...@@ -75,11 +76,11 @@ TEST(RawSharedBufferTest, Basic) {
// it to be. // it to be.
{ {
EXPECT_TRUE(buffer->IsValidMap(sizeof(int), kNumBytes - sizeof(int))); EXPECT_TRUE(buffer->IsValidMap(sizeof(int), kNumBytes - sizeof(int)));
scoped_ptr<RawSharedBufferMapping> mapping( scoped_ptr<embedder::PlatformSharedBufferMapping> mapping(
buffer->Map(sizeof(int), kNumBytes - sizeof(int))); buffer->Map(sizeof(int), kNumBytes - sizeof(int)));
ASSERT_TRUE(mapping); ASSERT_TRUE(mapping);
ASSERT_TRUE(mapping->base()); ASSERT_TRUE(mapping->GetBase());
int* stuff = static_cast<int*>(mapping->base()); int* stuff = static_cast<int*>(mapping->GetBase());
for (size_t j = 0; j < kNumInts - 1; j++) { for (size_t j = 0; j < kNumInts - 1; j++) {
int i = static_cast<int>(j) + 1; int i = static_cast<int>(j) + 1;
...@@ -140,40 +141,43 @@ TEST(RawSharedBufferTest, TooBig) { ...@@ -140,40 +141,43 @@ TEST(RawSharedBufferTest, TooBig) {
// using the address as the key for unmapping. // using the address as the key for unmapping.
TEST(RawSharedBufferTest, MappingsDistinct) { TEST(RawSharedBufferTest, MappingsDistinct) {
scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(100)); scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(100));
scoped_ptr<RawSharedBufferMapping> mapping1(buffer->Map(0, 100)); scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1(
scoped_ptr<RawSharedBufferMapping> mapping2(buffer->Map(0, 100)); buffer->Map(0, 100));
EXPECT_NE(mapping1->base(), mapping2->base()); scoped_ptr<embedder::PlatformSharedBufferMapping> mapping2(
buffer->Map(0, 100));
EXPECT_NE(mapping1->GetBase(), mapping2->GetBase());
} }
TEST(RawSharedBufferTest, BufferZeroInitialized) { TEST(RawSharedBufferTest, BufferZeroInitialized) {
static const size_t kSizes[] = {10, 100, 1000, 10000, 100000}; static const size_t kSizes[] = {10, 100, 1000, 10000, 100000};
for (size_t i = 0; i < arraysize(kSizes); i++) { for (size_t i = 0; i < arraysize(kSizes); i++) {
scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(kSizes[i])); scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(kSizes[i]));
scoped_ptr<RawSharedBufferMapping> mapping(buffer->Map(0, kSizes[i])); scoped_ptr<embedder::PlatformSharedBufferMapping> mapping(
buffer->Map(0, kSizes[i]));
for (size_t j = 0; j < kSizes[i]; j++) { for (size_t j = 0; j < kSizes[i]; j++) {
// "Assert" instead of "expect" so we don't spam the output with thousands // "Assert" instead of "expect" so we don't spam the output with thousands
// of failures if we fail. // of failures if we fail.
ASSERT_EQ('\0', static_cast<char*>(mapping->base())[j]) ASSERT_EQ('\0', static_cast<char*>(mapping->GetBase())[j])
<< "size " << kSizes[i] << ", offset " << j; << "size " << kSizes[i] << ", offset " << j;
} }
} }
} }
TEST(RawSharedBufferTest, MappingsOutliveBuffer) { TEST(RawSharedBufferTest, MappingsOutliveBuffer) {
scoped_ptr<RawSharedBufferMapping> mapping1; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1;
scoped_ptr<RawSharedBufferMapping> mapping2; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping2;
{ {
scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(100)); scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(100));
mapping1 = buffer->Map(0, 100).Pass(); mapping1 = buffer->Map(0, 100).Pass();
mapping2 = buffer->Map(50, 50).Pass(); mapping2 = buffer->Map(50, 50).Pass();
static_cast<char*>(mapping1->base())[50] = 'x'; static_cast<char*>(mapping1->GetBase())[50] = 'x';
} }
EXPECT_EQ('x', static_cast<char*>(mapping2->base())[0]); EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]);
static_cast<char*>(mapping2->base())[1] = 'y'; static_cast<char*>(mapping2->GetBase())[1] = 'y';
EXPECT_EQ('y', static_cast<char*>(mapping1->base())[51]); EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]);
} }
} // namespace } // namespace
......
...@@ -57,7 +57,8 @@ bool RawSharedBuffer::InitFromPlatformHandle( ...@@ -57,7 +57,8 @@ bool RawSharedBuffer::InitFromPlatformHandle(
return false; return false;
} }
scoped_ptr<RawSharedBufferMapping> RawSharedBuffer::MapImpl(size_t offset, scoped_ptr<embedder::PlatformSharedBufferMapping> RawSharedBuffer::MapImpl(
size_t offset,
size_t length) { size_t length) {
size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity(); size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity();
size_t real_offset = offset - offset_rounding; size_t real_offset = offset - offset_rounding;
...@@ -75,11 +76,11 @@ scoped_ptr<RawSharedBufferMapping> RawSharedBuffer::MapImpl(size_t offset, ...@@ -75,11 +76,11 @@ scoped_ptr<RawSharedBufferMapping> RawSharedBuffer::MapImpl(size_t offset,
real_length); real_length);
if (!real_base) { if (!real_base) {
PLOG(ERROR) << "MapViewOfFile"; PLOG(ERROR) << "MapViewOfFile";
return scoped_ptr<RawSharedBufferMapping>(); return scoped_ptr<embedder::PlatformSharedBufferMapping>();
} }
void* base = static_cast<char*>(real_base) + offset_rounding; void* base = static_cast<char*>(real_base) + offset_rounding;
return make_scoped_ptr( return scoped_ptr<embedder::PlatformSharedBufferMapping>(
new RawSharedBufferMapping(base, length, real_base, real_length)); new RawSharedBufferMapping(base, length, real_base, real_length));
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "build/build_config.h" // TODO(vtl): Remove this. #include "build/build_config.h" // TODO(vtl): Remove this.
#include "mojo/common/test/test_utils.h" #include "mojo/common/test/test_utils.h"
#include "mojo/embedder/platform_channel_pair.h" #include "mojo/embedder/platform_channel_pair.h"
#include "mojo/embedder/platform_shared_buffer.h"
#include "mojo/embedder/scoped_platform_handle.h" #include "mojo/embedder/scoped_platform_handle.h"
#include "mojo/system/channel.h" #include "mojo/system/channel.h"
#include "mojo/system/local_message_pipe_endpoint.h" #include "mojo/system/local_message_pipe_endpoint.h"
...@@ -708,16 +709,16 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { ...@@ -708,16 +709,16 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) {
ASSERT_TRUE(dispatcher); ASSERT_TRUE(dispatcher);
// Make a mapping. // Make a mapping.
scoped_ptr<RawSharedBufferMapping> mapping0; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping0;
EXPECT_EQ( EXPECT_EQ(
MOJO_RESULT_OK, MOJO_RESULT_OK,
dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping0)); dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping0));
ASSERT_TRUE(mapping0); ASSERT_TRUE(mapping0);
ASSERT_TRUE(mapping0->base()); ASSERT_TRUE(mapping0->GetBase());
ASSERT_EQ(100u, mapping0->length()); ASSERT_EQ(100u, mapping0->GetLength());
static_cast<char*>(mapping0->base())[0] = 'A'; static_cast<char*>(mapping0->GetBase())[0] = 'A';
static_cast<char*>(mapping0->base())[50] = 'B'; static_cast<char*>(mapping0->GetBase())[50] = 'B';
static_cast<char*>(mapping0->base())[99] = 'C'; static_cast<char*>(mapping0->GetBase())[99] = 'C';
// Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do
// it later, it might already be readable.) // it later, it might already be readable.)
...@@ -780,27 +781,27 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { ...@@ -780,27 +781,27 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) {
dispatcher = static_cast<SharedBufferDispatcher*>(read_dispatchers[0].get()); dispatcher = static_cast<SharedBufferDispatcher*>(read_dispatchers[0].get());
// Make another mapping. // Make another mapping.
scoped_ptr<RawSharedBufferMapping> mapping1; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1;
EXPECT_EQ( EXPECT_EQ(
MOJO_RESULT_OK, MOJO_RESULT_OK,
dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1));
ASSERT_TRUE(mapping1); ASSERT_TRUE(mapping1);
ASSERT_TRUE(mapping1->base()); ASSERT_TRUE(mapping1->GetBase());
ASSERT_EQ(100u, mapping1->length()); ASSERT_EQ(100u, mapping1->GetLength());
EXPECT_NE(mapping1->base(), mapping0->base()); EXPECT_NE(mapping1->GetBase(), mapping0->GetBase());
EXPECT_EQ('A', static_cast<char*>(mapping1->base())[0]); EXPECT_EQ('A', static_cast<char*>(mapping1->GetBase())[0]);
EXPECT_EQ('B', static_cast<char*>(mapping1->base())[50]); EXPECT_EQ('B', static_cast<char*>(mapping1->GetBase())[50]);
EXPECT_EQ('C', static_cast<char*>(mapping1->base())[99]); EXPECT_EQ('C', static_cast<char*>(mapping1->GetBase())[99]);
// Write stuff either way. // Write stuff either way.
static_cast<char*>(mapping1->base())[1] = 'x'; static_cast<char*>(mapping1->GetBase())[1] = 'x';
EXPECT_EQ('x', static_cast<char*>(mapping0->base())[1]); EXPECT_EQ('x', static_cast<char*>(mapping0->GetBase())[1]);
static_cast<char*>(mapping0->base())[2] = 'y'; static_cast<char*>(mapping0->GetBase())[2] = 'y';
EXPECT_EQ('y', static_cast<char*>(mapping1->base())[2]); EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[2]);
// Kill the first mapping; the second should still be valid. // Kill the first mapping; the second should still be valid.
mapping0.reset(); mapping0.reset();
EXPECT_EQ('A', static_cast<char*>(mapping1->base())[0]); EXPECT_EQ('A', static_cast<char*>(mapping1->GetBase())[0]);
// Close everything that belongs to us. // Close everything that belongs to us.
mp0->Close(0); mp0->Close(0);
...@@ -808,7 +809,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { ...@@ -808,7 +809,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) {
EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
// The second mapping should still be good. // The second mapping should still be good.
EXPECT_EQ('x', static_cast<char*>(mapping1->base())[1]); EXPECT_EQ('x', static_cast<char*>(mapping1->GetBase())[1]);
} }
#if defined(OS_POSIX) #if defined(OS_POSIX)
......
...@@ -70,7 +70,8 @@ MojoResult SharedBufferDispatcher::Create( ...@@ -70,7 +70,8 @@ MojoResult SharedBufferDispatcher::Create(
if (num_bytes > kMaxSharedMemoryNumBytes) if (num_bytes > kMaxSharedMemoryNumBytes)
return MOJO_RESULT_RESOURCE_EXHAUSTED; return MOJO_RESULT_RESOURCE_EXHAUSTED;
scoped_refptr<RawSharedBuffer> shared_buffer( // TODO(vtl): Call out to "platform support" for this.
scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer(
RawSharedBuffer::Create(static_cast<size_t>(num_bytes))); RawSharedBuffer::Create(static_cast<size_t>(num_bytes)));
if (!shared_buffer) if (!shared_buffer)
return MOJO_RESULT_RESOURCE_EXHAUSTED; return MOJO_RESULT_RESOURCE_EXHAUSTED;
...@@ -119,7 +120,7 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( ...@@ -119,7 +120,7 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
// Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be
// closed even if creation fails. // closed even if creation fails.
scoped_refptr<RawSharedBuffer> shared_buffer( scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer(
RawSharedBuffer::CreateFromPlatformHandle( RawSharedBuffer::CreateFromPlatformHandle(
num_bytes, embedder::ScopedPlatformHandle(platform_handle))); num_bytes, embedder::ScopedPlatformHandle(platform_handle)));
if (!shared_buffer) { if (!shared_buffer) {
...@@ -133,7 +134,7 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( ...@@ -133,7 +134,7 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
} }
SharedBufferDispatcher::SharedBufferDispatcher( SharedBufferDispatcher::SharedBufferDispatcher(
scoped_refptr<RawSharedBuffer> shared_buffer) scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer)
: shared_buffer_(shared_buffer) { : shared_buffer_(shared_buffer) {
DCHECK(shared_buffer_); DCHECK(shared_buffer_);
} }
...@@ -183,7 +184,7 @@ scoped_refptr<Dispatcher> ...@@ -183,7 +184,7 @@ scoped_refptr<Dispatcher>
SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
lock().AssertAcquired(); lock().AssertAcquired();
DCHECK(shared_buffer_); DCHECK(shared_buffer_);
scoped_refptr<RawSharedBuffer> shared_buffer; scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer;
shared_buffer.swap(shared_buffer_); shared_buffer.swap(shared_buffer_);
return scoped_refptr<Dispatcher>(new SharedBufferDispatcher(shared_buffer)); return scoped_refptr<Dispatcher>(new SharedBufferDispatcher(shared_buffer));
} }
...@@ -206,7 +207,7 @@ MojoResult SharedBufferDispatcher::MapBufferImplNoLock( ...@@ -206,7 +207,7 @@ MojoResult SharedBufferDispatcher::MapBufferImplNoLock(
uint64_t offset, uint64_t offset,
uint64_t num_bytes, uint64_t num_bytes,
MojoMapBufferFlags flags, MojoMapBufferFlags flags,
scoped_ptr<RawSharedBufferMapping>* mapping) { scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) {
lock().AssertAcquired(); lock().AssertAcquired();
DCHECK(shared_buffer_); DCHECK(shared_buffer_);
...@@ -258,7 +259,7 @@ bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock( ...@@ -258,7 +259,7 @@ bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock(
return false; return false;
} }
serialization->num_bytes = shared_buffer_->num_bytes(); serialization->num_bytes = shared_buffer_->GetNumBytes();
serialization->platform_handle_index = platform_handles->size(); serialization->platform_handle_index = platform_handles->size();
platform_handles->push_back(platform_handle.release()); platform_handles->push_back(platform_handle.release());
*actual_size = sizeof(SerializedSharedBufferDispatcher); *actual_size = sizeof(SerializedSharedBufferDispatcher);
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
#define MOJO_SYSTEM_SHARED_BUFFER_DISPATCHER_H_ #define MOJO_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
#include "base/macros.h" #include "base/macros.h"
#include "mojo/embedder/platform_shared_buffer.h"
#include "mojo/system/memory.h" #include "mojo/system/memory.h"
#include "mojo/system/raw_shared_buffer.h"
#include "mojo/system/simple_dispatcher.h" #include "mojo/system/simple_dispatcher.h"
#include "mojo/system/system_impl_export.h" #include "mojo/system/system_impl_export.h"
...@@ -53,7 +53,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher { ...@@ -53,7 +53,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher {
private: private:
explicit SharedBufferDispatcher( explicit SharedBufferDispatcher(
scoped_refptr<RawSharedBuffer> shared_buffer_); scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer_);
virtual ~SharedBufferDispatcher(); virtual ~SharedBufferDispatcher();
// Validates and/or sets default options for // Validates and/or sets default options for
...@@ -76,7 +76,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher { ...@@ -76,7 +76,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher {
uint64_t offset, uint64_t offset,
uint64_t num_bytes, uint64_t num_bytes,
MojoMapBufferFlags flags, MojoMapBufferFlags flags,
scoped_ptr<RawSharedBufferMapping>* mapping) OVERRIDE; scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) OVERRIDE;
virtual void StartSerializeImplNoLock(Channel* channel, virtual void StartSerializeImplNoLock(Channel* channel,
size_t* max_size, size_t* max_size,
size_t* max_platform_handles) OVERRIDE; size_t* max_platform_handles) OVERRIDE;
...@@ -86,7 +86,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher { ...@@ -86,7 +86,7 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher {
size_t* actual_size, size_t* actual_size,
embedder::PlatformHandleVector* platform_handles) OVERRIDE; embedder::PlatformHandleVector* platform_handles) OVERRIDE;
scoped_refptr<RawSharedBuffer> shared_buffer_; scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer_;
DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcher); DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcher);
}; };
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "mojo/embedder/platform_shared_buffer.h"
#include "mojo/system/dispatcher.h" #include "mojo/system/dispatcher.h"
#include "mojo/system/raw_shared_buffer.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace mojo { namespace mojo {
...@@ -109,31 +109,31 @@ TEST(SharedBufferDispatcherTest, CreateAndMapBuffer) { ...@@ -109,31 +109,31 @@ TEST(SharedBufferDispatcherTest, CreateAndMapBuffer) {
EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher->GetType()); EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher->GetType());
// Make a couple of mappings. // Make a couple of mappings.
scoped_ptr<RawSharedBufferMapping> mapping1; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1;
EXPECT_EQ( EXPECT_EQ(
MOJO_RESULT_OK, MOJO_RESULT_OK,
dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1));
ASSERT_TRUE(mapping1); ASSERT_TRUE(mapping1);
ASSERT_TRUE(mapping1->base()); ASSERT_TRUE(mapping1->GetBase());
EXPECT_EQ(100u, mapping1->length()); EXPECT_EQ(100u, mapping1->GetLength());
// Write something. // Write something.
static_cast<char*>(mapping1->base())[50] = 'x'; static_cast<char*>(mapping1->GetBase())[50] = 'x';
scoped_ptr<RawSharedBufferMapping> mapping2; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping2;
EXPECT_EQ( EXPECT_EQ(
MOJO_RESULT_OK, MOJO_RESULT_OK,
dispatcher->MapBuffer(50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2)); dispatcher->MapBuffer(50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2));
ASSERT_TRUE(mapping2); ASSERT_TRUE(mapping2);
ASSERT_TRUE(mapping2->base()); ASSERT_TRUE(mapping2->GetBase());
EXPECT_EQ(50u, mapping2->length()); EXPECT_EQ(50u, mapping2->GetLength());
EXPECT_EQ('x', static_cast<char*>(mapping2->base())[0]); EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]);
EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
// Check that we can still read/write to mappings after the dispatcher has // Check that we can still read/write to mappings after the dispatcher has
// gone away. // gone away.
static_cast<char*>(mapping2->base())[1] = 'y'; static_cast<char*>(mapping2->GetBase())[1] = 'y';
EXPECT_EQ('y', static_cast<char*>(mapping1->base())[51]); EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]);
} }
TEST(SharedBufferDispatcher, DuplicateBufferHandle) { TEST(SharedBufferDispatcher, DuplicateBufferHandle) {
...@@ -144,11 +144,11 @@ TEST(SharedBufferDispatcher, DuplicateBufferHandle) { ...@@ -144,11 +144,11 @@ TEST(SharedBufferDispatcher, DuplicateBufferHandle) {
SharedBufferDispatcher::kDefaultCreateOptions, 100, &dispatcher1)); SharedBufferDispatcher::kDefaultCreateOptions, 100, &dispatcher1));
// Map and write something. // Map and write something.
scoped_ptr<RawSharedBufferMapping> mapping; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
EXPECT_EQ( EXPECT_EQ(
MOJO_RESULT_OK, MOJO_RESULT_OK,
dispatcher1->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); dispatcher1->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
static_cast<char*>(mapping->base())[0] = 'x'; static_cast<char*>(mapping->GetBase())[0] = 'x';
mapping.reset(); mapping.reset();
// Duplicate |dispatcher1| and then close it. // Duplicate |dispatcher1| and then close it.
...@@ -165,7 +165,7 @@ TEST(SharedBufferDispatcher, DuplicateBufferHandle) { ...@@ -165,7 +165,7 @@ TEST(SharedBufferDispatcher, DuplicateBufferHandle) {
EXPECT_EQ( EXPECT_EQ(
MOJO_RESULT_OK, MOJO_RESULT_OK,
dispatcher2->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); dispatcher2->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
EXPECT_EQ('x', static_cast<char*>(mapping->base())[0]); EXPECT_EQ('x', static_cast<char*>(mapping->GetBase())[0]);
EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
} }
...@@ -250,7 +250,7 @@ TEST(SharedBufferDispatcherTest, MapBufferInvalidArguments) { ...@@ -250,7 +250,7 @@ TEST(SharedBufferDispatcherTest, MapBufferInvalidArguments) {
SharedBufferDispatcher::Create( SharedBufferDispatcher::Create(
SharedBufferDispatcher::kDefaultCreateOptions, 100, &dispatcher)); SharedBufferDispatcher::kDefaultCreateOptions, 100, &dispatcher));
scoped_ptr<RawSharedBufferMapping> mapping; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
dispatcher->MapBuffer(0, 101, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); dispatcher->MapBuffer(0, 101, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
EXPECT_FALSE(mapping); EXPECT_FALSE(mapping);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment