1 // Copyright 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.
5 #ifndef MOJO_SYSTEM_CORE_IMPL_H_
6 #define MOJO_SYSTEM_CORE_IMPL_H_
8 #include "base/basictypes.h"
9 #include "base/compiler_specific.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/synchronization/lock.h"
13 #include "mojo/public/system/core_private.h"
14 #include "mojo/system/system_impl_export.h"
22 // Test-only function (defined/used in embedder/test_embedder.cc). Declared here
23 // so it can be friended.
25 bool ShutdownCheckNoLeaks(CoreImpl*);
28 // |CoreImpl| is a singleton object that implements the Mojo system calls. All
29 // public methods are thread-safe.
30 class MOJO_SYSTEM_IMPL_EXPORT CoreImpl : public Core {
32 // These methods are only to be used by via the embedder API.
35 MojoHandle AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher);
37 // |CorePrivate| implementation:
38 virtual MojoTimeTicks GetTimeTicksNow() OVERRIDE;
39 virtual MojoResult Close(MojoHandle handle) OVERRIDE;
40 virtual MojoResult Wait(MojoHandle handle,
42 MojoDeadline deadline) OVERRIDE;
43 virtual MojoResult WaitMany(const MojoHandle* handles,
44 const MojoWaitFlags* flags,
46 MojoDeadline deadline) OVERRIDE;
47 virtual MojoResult CreateMessagePipe(
48 MojoHandle* message_pipe_handle0,
49 MojoHandle* message_pipe_handle1) OVERRIDE;
50 virtual MojoResult WriteMessage(MojoHandle message_pipe_handle,
53 const MojoHandle* handles,
55 MojoWriteMessageFlags flags) OVERRIDE;
56 virtual MojoResult ReadMessage(MojoHandle message_pipe_handle,
60 uint32_t* num_handles,
61 MojoReadMessageFlags flags) OVERRIDE;
62 virtual MojoResult CreateDataPipe(
63 const MojoCreateDataPipeOptions* options,
64 MojoHandle* data_pipe_producer_handle,
65 MojoHandle* data_pipe_consumer_handle) OVERRIDE;
66 virtual MojoResult WriteData(MojoHandle data_pipe_producer_handle,
69 MojoWriteDataFlags flags) OVERRIDE;
70 virtual MojoResult BeginWriteData(MojoHandle data_pipe_producer_handle,
72 uint32_t* buffer_num_bytes,
73 MojoWriteDataFlags flags) OVERRIDE;
74 virtual MojoResult EndWriteData(MojoHandle data_pipe_producer_handle,
75 uint32_t num_bytes_written) OVERRIDE;
76 virtual MojoResult ReadData(MojoHandle data_pipe_consumer_handle,
79 MojoReadDataFlags flags) OVERRIDE;
80 virtual MojoResult BeginReadData(MojoHandle data_pipe_consumer_handle,
82 uint32_t* buffer_num_bytes,
83 MojoReadDataFlags flags) OVERRIDE;
84 virtual MojoResult EndReadData(MojoHandle data_pipe_consumer_handle,
85 uint32_t num_bytes_read) OVERRIDE;
86 virtual MojoResult CreateSharedBuffer(
87 const MojoCreateSharedBufferOptions* options,
89 MojoHandle* shared_buffer_handle) OVERRIDE;
90 virtual MojoResult DuplicateBufferHandle(
91 MojoHandle buffer_handle,
92 const MojoDuplicateBufferHandleOptions* options,
93 MojoHandle* new_buffer_handle) OVERRIDE;
94 virtual MojoResult MapBuffer(MojoHandle buffer_handle,
98 MojoMapBufferFlags flags) OVERRIDE;
99 virtual MojoResult UnmapBuffer(void* buffer) OVERRIDE;
102 friend bool internal::ShutdownCheckNoLeaks(CoreImpl*);
104 // The |busy| member is used only to deal with functions (in particular
105 // |WriteMessage()|) that want to hold on to a dispatcher and later remove it
106 // from the handle table, without holding on to the handle table lock.
108 // For example, if |WriteMessage()| is called with a handle to be sent, (under
109 // the handle table lock) it must first check that that handle is not busy (if
110 // it is busy, then it fails with |MOJO_RESULT_BUSY|) and then marks it as
111 // busy. To avoid deadlock, it should also try to acquire the locks for all
112 // the dispatchers for the handles that it is sending (and fail with
113 // |MOJO_RESULT_BUSY| if the attempt fails). At this point, it can release the
114 // handle table lock.
116 // If |Close()| is simultaneously called on that handle, it too checks if the
117 // handle is marked busy. If it is, it fails (with |MOJO_RESULT_BUSY|). This
118 // prevents |WriteMessage()| from sending a handle that has been closed (or
119 // learning about this too late).
121 // TODO(vtl): Move this implementation note.
122 // To properly cancel waiters and avoid other races, |WriteMessage()| does not
123 // transfer dispatchers from one handle to another, even when sending a
124 // message in-process. Instead, it must transfer the "contents" of the
125 // dispatcher to a new dispatcher, and then close the old dispatcher. If this
126 // isn't done, in the in-process case, calls on the old handle may complete
127 // after the the message has been received and a new handle created (and
128 // possibly even after calls have been made on the new handle).
129 struct HandleTableEntry {
131 explicit HandleTableEntry(const scoped_refptr<Dispatcher>& dispatcher);
134 scoped_refptr<Dispatcher> dispatcher;
137 typedef base::hash_map<MojoHandle, HandleTableEntry> HandleTableMap;
139 // Looks up the dispatcher for the given handle. Returns null if the handle is
141 scoped_refptr<Dispatcher> GetDispatcher(MojoHandle handle);
143 // Assigns a new handle for the given dispatcher; returns
144 // |MOJO_HANDLE_INVALID| on failure (due to hitting resource limits) or if
145 // |dispatcher| is null. Must be called under |handle_table_lock_|.
146 MojoHandle AddDispatcherNoLock(const scoped_refptr<Dispatcher>& dispatcher);
148 // Internal implementation of |Wait()| and |WaitMany()|; doesn't do basic
149 // validation of arguments.
150 MojoResult WaitManyInternal(const MojoHandle* handles,
151 const MojoWaitFlags* flags,
152 uint32_t num_handles,
153 MojoDeadline deadline);
155 // ---------------------------------------------------------------------------
157 // TODO(vtl): |handle_table_lock_| should be a reader-writer lock (if only we
159 base::Lock handle_table_lock_; // Protects the immediately-following members.
160 HandleTableMap handle_table_;
161 MojoHandle next_handle_; // Invariant: never |MOJO_HANDLE_INVALID|.
163 // ---------------------------------------------------------------------------
165 DISALLOW_COPY_AND_ASSIGN(CoreImpl);
168 } // namespace system
171 #endif // MOJO_SYSTEM_CORE_IMPL_H_