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.
4
5#ifndef MOJO_SYSTEM_CORE_IMPL_H_
6#define MOJO_SYSTEM_CORE_IMPL_H_
7
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"
15
16namespace mojo {
17namespace system {
18
19class CoreImpl;
20class Dispatcher;
21
22namespace test {
23class CoreTestBase;
24}
25
26// |CoreImpl| is a singleton object that implements the Mojo system calls. With
27// the (obvious) exception of |Init()|, which must be called first (and the call
28// completed) before making any other calls, all the public methods are
29// thread-safe.
30class MOJO_SYSTEM_IMPL_EXPORT CoreImpl : public CorePrivate {
31 public:
32  static void Init();
33
34  // |CorePrivate| implementation:
35  virtual MojoTimeTicks GetTimeTicksNow() OVERRIDE;
36  virtual MojoResult Close(MojoHandle handle) OVERRIDE;
37  virtual MojoResult Wait(MojoHandle handle,
38                          MojoWaitFlags flags,
39                          MojoDeadline deadline) OVERRIDE;
40  virtual MojoResult WaitMany(const MojoHandle* handles,
41                              const MojoWaitFlags* flags,
42                              uint32_t num_handles,
43                              MojoDeadline deadline) OVERRIDE;
44  virtual MojoResult CreateMessagePipe(
45      MojoHandle* message_pipe_handle_0,
46      MojoHandle* message_pipe_handle_1) OVERRIDE;
47  virtual MojoResult WriteMessage(MojoHandle message_pipe_handle,
48                                  const void* bytes,
49                                  uint32_t num_bytes,
50                                  const MojoHandle* handles,
51                                  uint32_t num_handles,
52                                  MojoWriteMessageFlags flags) OVERRIDE;
53  virtual MojoResult ReadMessage(MojoHandle message_pipe_handle,
54                                 void* bytes,
55                                 uint32_t* num_bytes,
56                                 MojoHandle* handles,
57                                 uint32_t* num_handles,
58                                 MojoReadMessageFlags flags) OVERRIDE;
59  virtual MojoResult CreateDataPipe(
60      const MojoCreateDataPipeOptions* options,
61      MojoHandle* data_pipe_producer_handle,
62      MojoHandle* data_pipe_consumer_handle) OVERRIDE;
63  virtual MojoResult WriteData(MojoHandle data_pipe_producer_handle,
64                               const void* elements,
65                               uint32_t* num_elements,
66                               MojoWriteDataFlags flags) OVERRIDE;
67  virtual MojoResult BeginWriteData(MojoHandle data_pipe_producer_handle,
68                                    void** buffer,
69                                    uint32_t* buffer_num_elements,
70                                    MojoWriteDataFlags flags) OVERRIDE;
71  virtual MojoResult EndWriteData(MojoHandle data_pipe_producer_handle,
72                                  uint32_t num_elements_written) OVERRIDE;
73  virtual MojoResult ReadData(MojoHandle data_pipe_consumer_handle,
74                              void* elements,
75                              uint32_t* num_elements,
76                              MojoReadDataFlags flags) OVERRIDE;
77  virtual MojoResult BeginReadData(MojoHandle data_pipe_consumer_handle,
78                                   const void** buffer,
79                                   uint32_t* buffer_num_elements,
80                                   MojoReadDataFlags flags) OVERRIDE;
81  virtual MojoResult EndReadData(MojoHandle data_pipe_consumer_handle,
82                                 uint32_t num_elements_read) OVERRIDE;
83
84 private:
85  friend class test::CoreTestBase;
86
87  // The |busy| member is used only to deal with functions (in particular
88  // |WriteMessage()|) that want to hold on to a dispatcher and later remove it
89  // from the handle table, without holding on to the handle table lock.
90  //
91  // For example, if |WriteMessage()| is called with a handle to be sent, (under
92  // the handle table lock) it must first check that that handle is not busy (if
93  // it is busy, then it fails with |MOJO_RESULT_BUSY|) and then marks it as
94  // busy. To avoid deadlock, it should also try to acquire the locks for all
95  // the dispatchers for the handles that it is sending (and fail with
96  // |MOJO_RESULT_BUSY| if the attempt fails). At this point, it can release the
97  // handle table lock.
98  //
99  // If |Close()| is simultaneously called on that handle, it too checks if the
100  // handle is marked busy. If it is, it fails (with |MOJO_RESULT_BUSY|). This
101  // prevents |WriteMessage()| from sending a handle that has been closed (or
102  // learning about this too late).
103  //
104  // TODO(vtl): Move this implementation note.
105  // To properly cancel waiters and avoid other races, |WriteMessage()| does not
106  // transfer dispatchers from one handle to another, even when sending a
107  // message in-process. Instead, it must transfer the "contents" of the
108  // dispatcher to a new dispatcher, and then close the old dispatcher. If this
109  // isn't done, in the in-process case, calls on the old handle may complete
110  // after the the message has been received and a new handle created (and
111  // possibly even after calls have been made on the new handle).
112  struct HandleTableEntry {
113    HandleTableEntry();
114    explicit HandleTableEntry(const scoped_refptr<Dispatcher>& dispatcher);
115    ~HandleTableEntry();
116
117    scoped_refptr<Dispatcher> dispatcher;
118    bool busy;
119  };
120  typedef base::hash_map<MojoHandle, HandleTableEntry> HandleTableMap;
121
122  CoreImpl();
123  virtual ~CoreImpl();
124
125  // Looks up the dispatcher for the given handle. Returns null if the handle is
126  // invalid.
127  scoped_refptr<Dispatcher> GetDispatcher(MojoHandle handle);
128
129  // Assigns a new handle for the given dispatcher (which must be valid);
130  // returns |MOJO_HANDLE_INVALID| on failure (due to hitting resource limits).
131  // Must be called under |handle_table_lock_|.
132  MojoHandle AddDispatcherNoLock(const scoped_refptr<Dispatcher>& dispatcher);
133
134  // Internal implementation of |Wait()| and |WaitMany()|; doesn't do basic
135  // validation of arguments.
136  MojoResult WaitManyInternal(const MojoHandle* handles,
137                              const MojoWaitFlags* flags,
138                              uint32_t num_handles,
139                              MojoDeadline deadline);
140
141  // ---------------------------------------------------------------------------
142
143  // TODO(vtl): |handle_table_lock_| should be a reader-writer lock (if only we
144  // had them).
145  base::Lock handle_table_lock_;  // Protects the immediately-following members.
146  HandleTableMap handle_table_;
147  MojoHandle next_handle_;  // Invariant: never |MOJO_HANDLE_INVALID|.
148
149  // ---------------------------------------------------------------------------
150
151  DISALLOW_COPY_AND_ASSIGN(CoreImpl);
152};
153
154}  // namespace system
155}  // namespace mojo
156
157#endif  // MOJO_SYSTEM_CORE_IMPL_H_
158