Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
4 : // Use of this source code is governed by a BSD-style license that can be
5 : // found in the LICENSE file.
6 :
7 : #include "chrome/common/ipc_message.h"
8 :
9 : #include "base/logging.h"
10 : #include "build/build_config.h"
11 :
12 : #if defined(OS_POSIX)
13 : #include "chrome/common/file_descriptor_set_posix.h"
14 : #endif
15 : #ifdef MOZ_TASK_TRACER
16 : #include "GeckoTaskTracerImpl.h"
17 : #endif
18 :
19 : #include "mozilla/Move.h"
20 :
21 : #ifdef MOZ_TASK_TRACER
22 : using namespace mozilla::tasktracer;
23 :
24 : #define MSG_HEADER_SZ (IsStartLogging() && GetOrCreateTraceInfo() == nullptr ? \
25 : sizeof(Header) : sizeof(HeaderTaskTracer))
26 : #else
27 : #define MSG_HEADER_SZ sizeof(Header)
28 : #endif
29 :
30 : namespace IPC {
31 :
32 : //------------------------------------------------------------------------------
33 :
34 3405 : Message::~Message() {
35 1418 : MOZ_COUNT_DTOR(IPC::Message);
36 2556 : }
37 :
38 3 : Message::Message()
39 3 : : Pickle(MSG_HEADER_SZ) {
40 3 : MOZ_COUNT_CTOR(IPC::Message);
41 3 : header()->routing = header()->type = header()->flags = 0;
42 : #if defined(OS_POSIX)
43 3 : header()->num_fds = 0;
44 : #endif
45 : #ifdef MOZ_TASK_TRACER
46 : if (UseTaskTracerHeader()) {
47 : header()->flags |= TASKTRACER_BIT;
48 : HeaderTaskTracer* _header = static_cast<HeaderTaskTracer*>(header());
49 : GetCurTraceInfo(&_header->source_event_id,
50 : &_header->parent_task_id,
51 : &_header->source_event_type);
52 : }
53 : #endif
54 3 : InitLoggingVariables();
55 3 : }
56 :
57 567 : Message::Message(int32_t routing_id,
58 : msgid_t type,
59 : uint32_t segment_capacity,
60 : NestedLevel nestedLevel,
61 : PriorityValue priority,
62 : MessageCompression compression,
63 : const char* const aName,
64 567 : bool recordWriteLatency)
65 567 : : Pickle(MSG_HEADER_SZ, segment_capacity) {
66 567 : MOZ_COUNT_CTOR(IPC::Message);
67 567 : header()->routing = routing_id;
68 567 : header()->type = type;
69 567 : header()->flags = nestedLevel;
70 567 : if (priority == HIGH_PRIORITY)
71 57 : header()->flags |= PRIO_BIT;
72 567 : if (compression == COMPRESSION_ENABLED)
73 57 : header()->flags |= COMPRESS_BIT;
74 510 : else if (compression == COMPRESSION_ALL)
75 4 : header()->flags |= COMPRESSALL_BIT;
76 : #if defined(OS_POSIX)
77 567 : header()->num_fds = 0;
78 : #endif
79 567 : header()->interrupt_remote_stack_depth_guess = static_cast<uint32_t>(-1);
80 567 : header()->interrupt_local_stack_depth = static_cast<uint32_t>(-1);
81 567 : header()->seqno = 0;
82 : #if defined(OS_MACOSX)
83 : header()->cookie = 0;
84 : #endif
85 : #ifdef MOZ_TASK_TRACER
86 : if (UseTaskTracerHeader()) {
87 : header()->flags |= TASKTRACER_BIT;
88 : HeaderTaskTracer* _header = static_cast<HeaderTaskTracer*>(header());
89 : GetCurTraceInfo(&_header->source_event_id,
90 : &_header->parent_task_id,
91 : &_header->source_event_type);
92 : }
93 : #endif
94 567 : if (recordWriteLatency) {
95 521 : create_time_ = mozilla::TimeStamp::Now();
96 : }
97 567 : InitLoggingVariables(aName);
98 567 : }
99 :
100 : #ifndef MOZ_TASK_TRACER
101 : #define MSG_HEADER_SZ_DATA sizeof(Header)
102 : #else
103 : #define MSG_HEADER_SZ_DATA \
104 : (reinterpret_cast<const Header*>(data)->flags & TASKTRACER_BIT ? \
105 : sizeof(HeaderTaskTracer) : sizeof(Header))
106 : #endif
107 :
108 388 : Message::Message(const char* data, int data_len)
109 388 : : Pickle(MSG_HEADER_SZ_DATA, data, data_len)
110 : {
111 388 : MOZ_COUNT_CTOR(IPC::Message);
112 388 : InitLoggingVariables();
113 388 : }
114 :
115 476 : Message::Message(Message&& other) : Pickle(mozilla::Move(other)) {
116 476 : MOZ_COUNT_CTOR(IPC::Message);
117 476 : InitLoggingVariables(other.name_);
118 : #if defined(OS_POSIX)
119 476 : file_descriptor_set_ = other.file_descriptor_set_.forget();
120 : #endif
121 476 : }
122 :
123 1490 : void Message::InitLoggingVariables(const char* const aName) {
124 1490 : name_ = aName;
125 1490 : }
126 :
127 56 : Message& Message::operator=(Message&& other) {
128 56 : *static_cast<Pickle*>(this) = mozilla::Move(other);
129 56 : InitLoggingVariables(other.name_);
130 : #if defined(OS_POSIX)
131 56 : file_descriptor_set_.swap(other.file_descriptor_set_);
132 : #endif
133 56 : return *this;
134 : }
135 :
136 :
137 : #if defined(OS_POSIX)
138 55 : bool Message::WriteFileDescriptor(const base::FileDescriptor& descriptor) {
139 : // We write the index of the descriptor so that we don't have to
140 : // keep the current descriptor as extra decoding state when deserialising.
141 : // Also, we rely on each file descriptor being accompanied by sizeof(int)
142 : // bytes of data in the message. See the comment for input_cmsg_buf_.
143 55 : WriteInt(file_descriptor_set()->size());
144 55 : if (descriptor.auto_close) {
145 55 : return file_descriptor_set()->AddAndAutoClose(descriptor.fd);
146 : } else {
147 0 : return file_descriptor_set()->Add(descriptor.fd);
148 : }
149 : }
150 :
151 52 : bool Message::ReadFileDescriptor(PickleIterator* iter,
152 : base::FileDescriptor* descriptor) const {
153 : int descriptor_index;
154 52 : if (!ReadInt(iter, &descriptor_index))
155 0 : return false;
156 :
157 52 : FileDescriptorSet* file_descriptor_set = file_descriptor_set_.get();
158 52 : if (!file_descriptor_set)
159 0 : return false;
160 :
161 52 : descriptor->fd = file_descriptor_set->GetDescriptorAt(descriptor_index);
162 52 : descriptor->auto_close = false;
163 :
164 52 : return descriptor->fd >= 0;
165 : }
166 :
167 956 : void Message::EnsureFileDescriptorSet() {
168 956 : if (file_descriptor_set_.get() == NULL)
169 433 : file_descriptor_set_ = new FileDescriptorSet;
170 956 : }
171 :
172 0 : uint32_t Message::num_fds() const {
173 0 : return file_descriptor_set() ? file_descriptor_set()->size() : 0;
174 : }
175 :
176 : #endif
177 :
178 : #ifdef MOZ_TASK_TRACER
179 : void *MessageTask() {
180 : return reinterpret_cast<void*>(&MessageTask);
181 : }
182 :
183 : void
184 : Message::TaskTracerDispatch() {
185 : if (header()->flags & TASKTRACER_BIT) {
186 : HeaderTaskTracer* _header = static_cast<HeaderTaskTracer*>(header());
187 : _header->task_id = GenNewUniqueTaskId();
188 : uintptr_t* vtab = reinterpret_cast<uintptr_t*>(&MessageTask);
189 : LogVirtualTablePtr(_header->task_id,
190 : _header->source_event_id,
191 : vtab);
192 : LogDispatch(_header->task_id,
193 : _header->parent_task_id,
194 : _header->source_event_id,
195 : _header->source_event_type);
196 : }
197 : }
198 :
199 : Message::AutoTaskTracerRun::AutoTaskTracerRun(Message& aMsg)
200 : : mMsg(aMsg)
201 : , mTaskId(0)
202 : , mSourceEventId(0) {
203 : if (mMsg.header()->flags & TASKTRACER_BIT) {
204 : const HeaderTaskTracer* _header =
205 : static_cast<HeaderTaskTracer*>(mMsg.header());
206 : LogBegin(_header->task_id,
207 : _header->source_event_id);
208 : SetCurTraceInfo(_header->source_event_id,
209 : _header->task_id,
210 : _header->source_event_type);
211 : mTaskId = _header->task_id;
212 : mSourceEventId = _header->source_event_id;
213 : } else {
214 : SetCurTraceInfo(0, 0, SourceEventType::Unknown);
215 : }
216 : }
217 :
218 : Message::AutoTaskTracerRun::~AutoTaskTracerRun() {
219 : if (mTaskId) {
220 : AddLabel("IPC Message %s", mMsg.name());
221 : LogEnd(mTaskId, mSourceEventId);
222 : }
223 : }
224 : #endif
225 :
226 : } // namespace IPC
|