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