Mojo: Implement MojoUnmapBuffer().
Still to do: more tests.
[email protected]
Review URL: https://codereview.chromium.org/220113003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260832 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/mojo/mojo.gyp b/mojo/mojo.gyp
index 4c24e47d..ee5ec8b 100644
--- a/mojo/mojo.gyp
+++ b/mojo/mojo.gyp
@@ -132,6 +132,8 @@
'system/local_data_pipe.h',
'system/local_message_pipe_endpoint.cc',
'system/local_message_pipe_endpoint.h',
+ 'system/mapping_table.cc',
+ 'system/mapping_table.h',
'system/memory.cc',
'system/memory.h',
'system/message_in_transit.cc',
diff --git a/mojo/public/c/system/tests/core_unittest.cc b/mojo/public/c/system/tests/core_unittest.cc
index c9acd00..bb6c458 100644
--- a/mojo/public/c/system/tests/core_unittest.cc
+++ b/mojo/public/c/system/tests/core_unittest.cc
@@ -251,8 +251,7 @@
static_cast<char*>(pointer)[51] = 'y';
// Unmap it.
- // TODO(vtl): Not yet implemented.
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, MojoUnmapBuffer(pointer));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(pointer));
// Map half of |h1|.
pointer = NULL;
@@ -265,8 +264,7 @@
EXPECT_EQ('y', static_cast<char*>(pointer)[1]);
// Unmap it.
- // TODO(vtl): Not yet implemented.
- EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, MojoUnmapBuffer(pointer));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(pointer));
EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1));
}
diff --git a/mojo/system/constants.h b/mojo/system/constants.h
index 6c287b53..b92eef10 100644
--- a/mojo/system/constants.h
+++ b/mojo/system/constants.h
@@ -10,11 +10,14 @@
namespace mojo {
namespace system {
-// Maximum of open (Mojo) handles.
+// Maximum number of open (Mojo) handles.
// TODO(vtl): This doesn't count "live" handles, some of which may live in
// messages.
const size_t kMaxHandleTableSize = 1000000;
+// Maximum number of active memory mappings.
+const size_t kMaxMappingTableSize = 1000000;
+
const size_t kMaxWaitManyNumHandles = kMaxHandleTableSize;
const size_t kMaxMessageNumBytes = 4 * 1024 * 1024;
diff --git a/mojo/system/core_impl.cc b/mojo/system/core_impl.cc
index f6f28086..12c1be57 100644
--- a/mojo/system/core_impl.cc
+++ b/mojo/system/core_impl.cc
@@ -59,7 +59,7 @@
// (which subclasses can use to protect their data).
//
// The lock ordering is as follows:
-// 1. global handle table lock
+// 1. global handle table lock, global mapping table lock
// 2. |Dispatcher| locks
// 3. secondary object locks
// ...
@@ -503,19 +503,21 @@
return result;
DCHECK(mapping);
- *buffer = mapping->base();
+ void* address = mapping->base();
+ {
+ base::AutoLock locker(mapping_table_lock_);
+ result = mapping_table_.AddMapping(mapping.Pass());
+ }
+ if (result != MOJO_RESULT_OK)
+ return result;
- // TODO(vtl): FIXME -- Record the mapping somewhere, so that it can be
- // unmapped properly. For now, just leak it.
- ignore_result(mapping.release());
-
+ *buffer = address;
return MOJO_RESULT_OK;
}
MojoResult CoreImpl::UnmapBuffer(void* buffer) {
- // TODO(vtl): FIXME
- NOTIMPLEMENTED();
- return MOJO_RESULT_UNIMPLEMENTED;
+ base::AutoLock locker(mapping_table_lock_);
+ return mapping_table_.RemoveMapping(buffer);
}
scoped_refptr<Dispatcher> CoreImpl::GetDispatcher(MojoHandle handle) {
diff --git a/mojo/system/core_impl.h b/mojo/system/core_impl.h
index 63b4b08b..e0cbd1e 100644
--- a/mojo/system/core_impl.h
+++ b/mojo/system/core_impl.h
@@ -11,6 +11,7 @@
#include "base/synchronization/lock.h"
#include "mojo/public/system/core_private.h"
#include "mojo/system/handle_table.h"
+#include "mojo/system/mapping_table.h"
#include "mojo/system/system_impl_export.h"
namespace mojo {
@@ -138,6 +139,9 @@
base::Lock handle_table_lock_; // Protects |handle_table_|.
HandleTable handle_table_;
+ base::Lock mapping_table_lock_; // Protects |mapping_table_|.
+ MappingTable mapping_table_;
+
// ---------------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN(CoreImpl);
diff --git a/mojo/system/handle_table.cc b/mojo/system/handle_table.cc
index fc03e2e77..798b6103 100644
--- a/mojo/system/handle_table.cc
+++ b/mojo/system/handle_table.cc
@@ -181,9 +181,6 @@
return MOJO_RESULT_OK;
}
-
-//////////////
-
MojoHandle HandleTable::AddDispatcherNoSizeCheck(
const scoped_refptr<Dispatcher>& dispatcher) {
DCHECK(dispatcher);
diff --git a/mojo/system/mapping_table.cc b/mojo/system/mapping_table.cc
new file mode 100644
index 0000000..39b79bcd
--- /dev/null
+++ b/mojo/system/mapping_table.cc
@@ -0,0 +1,48 @@
+// 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.
+
+#include "mojo/system/mapping_table.h"
+
+#include "base/logging.h"
+#include "mojo/system/constants.h"
+#include "mojo/system/raw_shared_buffer.h"
+
+namespace mojo {
+namespace system {
+
+MappingTable::MappingTable() {
+}
+
+MappingTable::~MappingTable() {
+ // This should usually not be reached (the only instance should be owned by
+ // the singleton |CoreImpl|, which lives forever), except in tests.
+}
+
+MojoResult MappingTable::AddMapping(
+ scoped_ptr<RawSharedBufferMapping> mapping) {
+ DCHECK(mapping);
+
+ if (address_to_mapping_map_.size() >= kMaxMappingTableSize)
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+
+ uintptr_t address = reinterpret_cast<uintptr_t>(mapping->base());
+ DCHECK(address_to_mapping_map_.find(address) ==
+ address_to_mapping_map_.end());
+ address_to_mapping_map_[address] = mapping.release();
+ return MOJO_RESULT_OK;
+}
+
+MojoResult MappingTable::RemoveMapping(void* address) {
+ AddressToMappingMap::iterator it =
+ address_to_mapping_map_.find(reinterpret_cast<uintptr_t>(address));
+ if (it == address_to_mapping_map_.end())
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ RawSharedBufferMapping* mapping_to_delete = it->second;
+ address_to_mapping_map_.erase(it);
+ delete mapping_to_delete;
+ return MOJO_RESULT_OK;
+}
+
+} // namespace system
+} // namespace mojo
diff --git a/mojo/system/mapping_table.h b/mojo/system/mapping_table.h
new file mode 100644
index 0000000..bbae097
--- /dev/null
+++ b/mojo/system/mapping_table.h
@@ -0,0 +1,58 @@
+// 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_SYSTEM_MAPPING_TABLE_H_
+#define MOJO_SYSTEM_MAPPING_TABLE_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/containers/hash_tables.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "mojo/public/c/system/core.h"
+#include "mojo/system/system_impl_export.h"
+
+namespace mojo {
+namespace system {
+
+class CoreImpl;
+class RawSharedBufferMapping;
+
+// Test-only function (defined/used in embedder/test_embedder.cc). Declared here
+// so it can be friended.
+namespace internal {
+bool ShutdownCheckNoLeaks(CoreImpl*);
+}
+
+// This class provides the (global) table of memory mappings (owned by
+// |CoreImpl|), which maps mapping base addresses to
+// |RawSharedBuffer::Mapping|s.
+//
+// This class is NOT thread-safe; locking is left to |CoreImpl|.
+class MOJO_SYSTEM_IMPL_EXPORT MappingTable {
+ public:
+ MappingTable();
+ ~MappingTable();
+
+ // Tries to add a mapping. (Takes ownership of the mapping in all cases; on
+ // failure, it will be destroyed.)
+ MojoResult AddMapping(scoped_ptr<RawSharedBufferMapping> mapping);
+ MojoResult RemoveMapping(void* address);
+
+ private:
+ friend bool internal::ShutdownCheckNoLeaks(CoreImpl*);
+
+ typedef base::hash_map<uintptr_t, RawSharedBufferMapping*>
+ AddressToMappingMap;
+ AddressToMappingMap address_to_mapping_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(MappingTable);
+};
+
+} // namespace system
+} // namespace mojo
+
+#endif // MOJO_SYSTEM_MAPPING_TABLE_H_