Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Unified Diff: content/common/gpu/gpu_channel.cc

Issue 1308913004: GPU Channel's now maintain a global order number for each processed IPC. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: GPU Channel message queue placed in own class, applied suggestions Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/common/gpu/gpu_channel.cc
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc
index 636029cdd4765ede69dd2083c684ae54624867bd..909cc4fe2874199fc9cb8db80b4a7c1d715f14a5 100644
--- a/content/common/gpu/gpu_channel.cc
+++ b/content/common/gpu/gpu_channel.cc
@@ -9,7 +9,7 @@
#include "content/common/gpu/gpu_channel.h"
#include <algorithm>
-#include <queue>
+#include <deque>
#include <vector>
#include "base/bind.h"
@@ -18,8 +18,8 @@
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
+#include "base/synchronization/lock.h"
#include "base/thread_task_runner_handle.h"
-#include "base/timer/timer.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
@@ -67,6 +67,162 @@ const int64 kStopPreemptThresholdMs = kVsyncIntervalMs;
} // anonymous namespace
+struct ChannelMessage {
+ uint32_t order_number;
+ base::TimeTicks time_received;
+ IPC::Message message;
+
+ // TODO(dyen): Temporary sync point data, remove once new sync point lands.
+ bool retire_sync_point;
+ uint32 sync_point_number;
+
+ ChannelMessage(uint32_t order_num, const IPC::Message& msg)
+ : order_number(order_num),
+ time_received(base::TimeTicks::Now()),
+ message(msg),
+ retire_sync_point(false),
+ sync_point_number(0) {}
+};
+
+class GpuChannelMessageQueue : public base::RefCounted<GpuChannelMessageQueue> {
piman 2015/09/01 03:55:26 Needs to be RefCountedThreadSafe
David Yen 2015/09/01 19:08:02 Done.
+ public:
+ static scoped_refptr<GpuChannelMessageQueue> Create(
+ GpuChannelManager* gpu_channel_manager,
+ base::WeakPtr<GpuChannel> gpu_channel,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ return new GpuChannelMessageQueue(gpu_channel_manager, gpu_channel,
+ task_runner);
+ }
+
+ void PushBackMessage(uint32_t order_number,
+ const IPC::Message& message) {
piman 2015/09/01 03:55:26 nit: indent, here and below (run git cl format)
David Yen 2015/09/01 19:08:02 Done.
+ base::subtle::Release_Store(&unprocessed_order_num_, order_number);
+
+ base::AutoLock auto_lock(channel_messages_lock_);
+ const bool was_empty = channel_messages_.empty();
+ channel_messages_.push_back(new ChannelMessage(order_number, message));
+ if (was_empty)
+ ScheduleHandleMessageLocked();
+ }
+
+ void PushFrontMessage(const IPC::Message& message) {
+ // These are pushed out of order so should not have any order messages.
+ base::AutoLock auto_lock(channel_messages_lock_);
+ const bool was_empty = channel_messages_.empty();
+ channel_messages_.push_front(new ChannelMessage(static_cast<uint32_t>(-1),
piman 2015/09/01 03:55:26 nit: maybe define a const uint32_t kOutOfOrderNume
David Yen 2015/09/01 19:08:02 Done.
+ message));
+ if (was_empty)
+ ScheduleHandleMessageLocked();
+ }
+
+ void PushSyncPointMessage(uint32_t order_number,
+ const IPC::Message& message,
+ bool retire_sync_point,
+ uint32_t sync_point_num) {
+ DCHECK(message.type() == GpuCommandBufferMsg_InsertSyncPoint::ID);
+
+ base::subtle::Release_Store(&unprocessed_order_num_, order_number);
+ ChannelMessage* msg = new ChannelMessage(order_number, message);
+ msg->retire_sync_point = retire_sync_point;
+ msg->sync_point_number = sync_point_num;
+
+ base::AutoLock auto_lock(channel_messages_lock_);
+ const bool was_empty = channel_messages_.empty();
+ channel_messages_.push_back(msg);
+ if (was_empty)
+ ScheduleHandleMessageLocked();
+ }
piman 2015/09/01 03:55:26 nit: all 3 functions (and PushUnfinishedMessage) c
David Yen 2015/09/01 19:08:02 Done.
+
+ bool HasQueuedMessages() {
+ base::AutoLock auto_lock(channel_messages_lock_);
+ return !channel_messages_.empty();
+ }
+
+ base::TimeTicks GetNextMessageTimeTick() {
+ // We have to account for messages that are pushed out of order, the out
+ // of order messages are pushed back to front and have order numbers of -1.
+ base::TimeTicks next_time_tick;
+ base::AutoLock auto_lock(channel_messages_lock_);
+ for (const auto& msg : channel_messages_) {
+ if (msg->order_number != static_cast<uint32_t>(-1)) {
+ // Return the earliest time tick if we have some out of order ones.
+ return next_time_tick.is_null() ?
+ msg->time_received :
+ std::min(msg->time_received, next_time_tick);
+ } else {
+ // Store the last out of order message in next_time_tick.
+ next_time_tick = msg->time_received;
+ }
+ }
+ return next_time_tick;
+ }
+
+ protected:
+ virtual ~GpuChannelMessageQueue() {
piman 2015/09/01 03:55:26 This logic needs to happen on the main thread. Si
David Yen 2015/09/01 19:08:02 Ah, I just noticed that too. I've moved it to the
+ base::AutoLock auto_lock(channel_messages_lock_);
+ for (const auto& msg : channel_messages_) {
piman 2015/09/01 03:55:26 I'd suggest making this ChannelMessage* msg for cl
David Yen 2015/09/01 19:08:02 Done.
+ const uint32_t sync_point = msg->sync_point_number;
+ gpu_channel_manager_->sync_point_manager()->RetireSyncPoint(sync_point);
piman 2015/09/01 03:55:26 if (sync_point) gpu_channel_manager_->sync_point
David Yen 2015/09/01 19:08:02 Done.
+ }
+ STLDeleteElements(&channel_messages_);
+ }
+
+ private:
+ friend class GpuChannel;
+ friend class base::RefCounted<GpuChannelMessageQueue>;
+
+ GpuChannelMessageQueue(
+ GpuChannelManager* gpu_channel_manager,
+ base::WeakPtr<GpuChannel> gpu_channel,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : unprocessed_order_num_(0),
+ handle_messages_scheduled_(false),
+ gpu_channel_manager_(gpu_channel_manager),
+ gpu_channel_(gpu_channel),
+ task_runner_(task_runner) {
+ }
+
+ void PushUnfinishedMessage(uint32_t order_number,
+ const IPC::Message& message) {
+ // This is pushed only if it was unfinished, so order number is kept.
+ base::AutoLock auto_lock(channel_messages_lock_);
+ const bool was_empty = channel_messages_.empty();
+ channel_messages_.push_front(new ChannelMessage(order_number, message));
+ if (was_empty)
+ ScheduleHandleMessageLocked();
+ }
+
+ void ScheduleHandleMessage() {
+ base::AutoLock auto_lock(channel_messages_lock_);
+ ScheduleHandleMessageLocked();
+ }
+
+ void ScheduleHandleMessageLocked() {
+ channel_messages_lock_.AssertAcquired();
+ if (!handle_messages_scheduled_) {
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&GpuChannel::HandleMessage, gpu_channel_));
+ handle_messages_scheduled_ = true;
+ }
+ }
+
+ // Highest IPC order number seen, set when queued on the IO thread.
+ base::subtle::Atomic32 unprocessed_order_num_;
piman 2015/09/01 03:55:26 If we really need this, I'd prefer it to be a uint
David Yen 2015/09/01 19:08:02 Done.
+
+ std::deque<ChannelMessage*> channel_messages_;
+ bool handle_messages_scheduled_;
+
+ // This lock protects both handle_messages_scheduled_ and channel_messages_.
+ base::Lock channel_messages_lock_;
+
+ GpuChannelManager* gpu_channel_manager_;
+ base::WeakPtr<GpuChannel> gpu_channel_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuChannelMessageQueue);
+};
+
// This filter does three things:
// - it counts and timestamps each message forwarded to the channel
// so that we can preempt other channels if a message takes too long to
@@ -81,16 +237,17 @@ const int64 kStopPreemptThresholdMs = kVsyncIntervalMs;
class GpuChannelMessageFilter : public IPC::MessageFilter {
public:
GpuChannelMessageFilter(
+ scoped_refptr<GpuChannelMessageQueue> message_queue,
base::WeakPtr<GpuChannel> gpu_channel,
gpu::SyncPointManager* sync_point_manager,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
bool future_sync_points)
: preemption_state_(IDLE),
+ message_queue_(message_queue),
gpu_channel_(gpu_channel),
sender_(nullptr),
sync_point_manager_(sync_point_manager),
task_runner_(task_runner),
- messages_forwarded_to_channel_(0),
a_stub_is_descheduled_(false),
future_sync_points_(future_sync_points) {}
@@ -109,6 +266,7 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
bool OnMessageReceived(const IPC::Message& message) override {
DCHECK(sender_);
+ const uint32_t order_number = global_order_counter_++;
bool handled = false;
if ((message.type() == GpuCommandBufferMsg_RetireSyncPoint::ID) &&
!future_sync_points_) {
@@ -135,11 +293,9 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
uint32 sync_point = sync_point_manager_->GenerateSyncPoint();
GpuCommandBufferMsg_InsertSyncPoint::WriteReplyParams(reply, sync_point);
Send(reply);
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&GpuChannelMessageFilter::InsertSyncPointOnMainThread,
- gpu_channel_, sync_point_manager_, message.routing_id(),
- base::get<0>(retire), sync_point));
+
+ message_queue_->PushSyncPointMessage(order_number, message,
+ base::get<0>(retire), sync_point);
handled = true;
}
@@ -154,19 +310,24 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
return false;
}
- // All other messages get processed by the GpuChannel.
- messages_forwarded_to_channel_++;
- if (preempting_flag_.get())
- pending_messages_.push(PendingMessage(messages_forwarded_to_channel_));
- UpdatePreemptionState();
+ // Forward all other messages to the GPU Channel.
+ if (!handled && !message.is_reply() && !message.should_unblock()) {
+ if (message.type() == GpuCommandBufferMsg_WaitForTokenInRange::ID ||
+ message.type() == GpuCommandBufferMsg_WaitForGetOffsetInRange::ID) {
+ // Move Wait commands to the head of the queue, so the renderer
+ // doesn't have to wait any longer than necessary.
+ message_queue_->PushFrontMessage(message);
+ } else {
+ message_queue_->PushBackMessage(order_number, message);
+ }
+ handled = true;
+ }
+ UpdatePreemptionState();
return handled;
}
- void MessageProcessed(uint64 messages_processed) {
- while (!pending_messages_.empty() &&
- pending_messages_.front().message_number <= messages_processed)
- pending_messages_.pop();
+ void OnMessageProcessed() {
UpdatePreemptionState();
}
@@ -212,20 +373,10 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
// It is reset when we transition to IDLE.
base::TimeDelta max_preemption_time_;
- struct PendingMessage {
- uint64 message_number;
- base::TimeTicks time_received;
-
- explicit PendingMessage(uint64 message_number)
- : message_number(message_number),
- time_received(base::TimeTicks::Now()) {
- }
- };
-
void UpdatePreemptionState() {
switch (preemption_state_) {
case IDLE:
- if (preempting_flag_.get() && !pending_messages_.empty())
+ if (preempting_flag_.get() && message_queue_->HasQueuedMessages())
TransitionToWaiting();
break;
case WAITING:
@@ -233,21 +384,23 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
DCHECK(timer_->IsRunning());
break;
case CHECKING:
- if (!pending_messages_.empty()) {
- base::TimeDelta time_elapsed =
- base::TimeTicks::Now() - pending_messages_.front().time_received;
- if (time_elapsed.InMilliseconds() < kPreemptWaitTimeMs) {
- // Schedule another check for when the IPC may go long.
- timer_->Start(
- FROM_HERE,
- base::TimeDelta::FromMilliseconds(kPreemptWaitTimeMs) -
- time_elapsed,
- this, &GpuChannelMessageFilter::UpdatePreemptionState);
- } else {
- if (a_stub_is_descheduled_)
- TransitionToWouldPreemptDescheduled();
- else
- TransitionToPreempting();
+ {
+ base::TimeTicks time_tick = message_queue_->GetNextMessageTimeTick();
+ if (!time_tick.is_null()) {
+ base::TimeDelta time_elapsed = base::TimeTicks::Now() - time_tick;
+ if (time_elapsed.InMilliseconds() < kPreemptWaitTimeMs) {
+ // Schedule another check for when the IPC may go long.
+ timer_->Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kPreemptWaitTimeMs) -
+ time_elapsed,
+ this, &GpuChannelMessageFilter::UpdatePreemptionState);
+ } else {
+ if (a_stub_is_descheduled_)
+ TransitionToWouldPreemptDescheduled();
+ else
+ TransitionToPreempting();
+ }
}
}
break;
@@ -275,11 +428,11 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
void TransitionToIdleIfCaughtUp() {
DCHECK(preemption_state_ == PREEMPTING ||
preemption_state_ == WOULD_PREEMPT_DESCHEDULED);
- if (pending_messages_.empty()) {
+ base::TimeTicks next_tick = message_queue_->GetNextMessageTimeTick();
+ if (next_tick.is_null()) {
TransitionToIdle();
} else {
- base::TimeDelta time_elapsed =
- base::TimeTicks::Now() - pending_messages_.front().time_received;
+ base::TimeDelta time_elapsed = base::TimeTicks::Now() - next_tick;
if (time_elapsed.InMilliseconds() < kStopPreemptThresholdMs)
TransitionToIdle();
}
@@ -365,46 +518,16 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
UpdatePreemptionState();
}
- static void InsertSyncPointOnMainThread(
- base::WeakPtr<GpuChannel> gpu_channel,
- gpu::SyncPointManager* manager,
- int32 routing_id,
- bool retire,
- uint32 sync_point) {
- // This function must ensure that the sync point will be retired. Normally
- // we'll find the stub based on the routing ID, and associate the sync point
- // with it, but if that fails for any reason (channel or stub already
- // deleted, invalid routing id), we need to retire the sync point
- // immediately.
- if (gpu_channel) {
- GpuCommandBufferStub* stub = gpu_channel->LookupCommandBuffer(routing_id);
- if (stub) {
- stub->AddSyncPoint(sync_point);
- if (retire) {
- GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point);
- gpu_channel->OnMessageReceived(message);
- }
- return;
- } else {
- gpu_channel->MessageProcessed();
- }
- }
- manager->RetireSyncPoint(sync_point);
- }
-
- // NOTE: this weak pointer is never dereferenced on the IO thread, it's only
- // passed through - therefore the WeakPtr assumptions are respected.
+ // NOTE: The message_queue_ is used to handle messages on the main thread.
+ // The gpu_channel_ weak pointer is only dereferenced on the
+ // main thread - therefore the WeakPtr assumptions are respected.
+ scoped_refptr<GpuChannelMessageQueue> message_queue_;
base::WeakPtr<GpuChannel> gpu_channel_;
piman 2015/09/01 03:55:26 I don't think you need this any more.
David Yen 2015/09/01 19:08:02 Done.
IPC::Sender* sender_;
gpu::SyncPointManager* sync_point_manager_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
scoped_refptr<gpu::PreemptionFlag> preempting_flag_;
- std::queue<PendingMessage> pending_messages_;
-
- // Count of the number of IPCs forwarded to the GpuChannel.
- uint64 messages_forwarded_to_channel_;
-
// This timer is created and destroyed on the IO thread.
scoped_ptr<base::OneShotTimer<GpuChannelMessageFilter>> timer_;
@@ -412,8 +535,13 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
// True if this channel can create future sync points.
bool future_sync_points_;
+
+ // This number is only ever incremented/read on the IO thread.
+ static uint32_t global_order_counter_;
};
+uint32_t GpuChannelMessageFilter::global_order_counter_ = 0;
+
GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
GpuWatchdog* watchdog,
gfx::GLShareGroup* share_group,
@@ -426,7 +554,6 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
bool allow_future_sync_points)
: gpu_channel_manager_(gpu_channel_manager),
channel_id_(IPC::Channel::GenerateVerifiedChannelID("gpu")),
- messages_processed_(0),
client_id_(client_id),
client_tracing_id_(client_tracing_id),
task_runner_(task_runner),
@@ -439,16 +566,21 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
pending_valuebuffer_state_(new gpu::ValueStateMap),
watchdog_(watchdog),
software_(software),
- handle_messages_scheduled_(false),
- currently_processing_message_(nullptr),
+ current_order_num_(0),
+ processed_order_num_(0),
num_stubs_descheduled_(0),
allow_future_sync_points_(allow_future_sync_points),
weak_factory_(this) {
DCHECK(gpu_channel_manager);
DCHECK(client_id);
+ message_queue_ = GpuChannelMessageQueue::Create(gpu_channel_manager,
+ weak_factory_.GetWeakPtr(),
+ task_runner);
+
filter_ = new GpuChannelMessageFilter(
- weak_factory_.GetWeakPtr(), gpu_channel_manager_->sync_point_manager(),
+ message_queue_, weak_factory_.GetWeakPtr(),
+ gpu_channel_manager_->sync_point_manager(),
task_runner_, allow_future_sync_points_);
subscription_ref_set_->AddObserver(this);
@@ -458,7 +590,6 @@ GpuChannel::~GpuChannel() {
// Clear stubs first because of dependencies.
stubs_.clear();
- STLDeleteElements(&deferred_messages_);
subscription_ref_set_->RemoveObserver(this);
if (preempting_flag_.get())
preempting_flag_->Reset();
@@ -493,21 +624,9 @@ base::ProcessId GpuChannel::GetClientPID() const {
}
bool GpuChannel::OnMessageReceived(const IPC::Message& message) {
- DVLOG(1) << "received message @" << &message << " on channel @" << this
- << " with type " << message.type();
-
- if (message.type() == GpuCommandBufferMsg_WaitForTokenInRange::ID ||
- message.type() == GpuCommandBufferMsg_WaitForGetOffsetInRange::ID) {
- // Move Wait commands to the head of the queue, so the renderer
- // doesn't have to wait any longer than necessary.
- deferred_messages_.push_front(new IPC::Message(message));
- } else {
- deferred_messages_.push_back(new IPC::Message(message));
- }
-
- OnScheduled();
-
- return true;
+ // All messages should be pushed to channel_messages_ and handled separately.
+ NOTREACHED();
+ return false;
}
void GpuChannel::OnChannelError() {
@@ -540,32 +659,11 @@ void GpuChannel::OnRemoveSubscription(unsigned int target) {
new GpuHostMsg_RemoveSubscription(client_id_, target));
}
-void GpuChannel::RequeueMessage() {
- DCHECK(currently_processing_message_);
- deferred_messages_.push_front(
- new IPC::Message(*currently_processing_message_));
- messages_processed_--;
- currently_processing_message_ = NULL;
-}
-
-void GpuChannel::OnScheduled() {
- if (handle_messages_scheduled_)
- return;
- // Post a task to handle any deferred messages. The deferred message queue is
- // not emptied here, which ensures that OnMessageReceived will continue to
- // defer newly received messages until the ones in the queue have all been
- // handled by HandleMessage. HandleMessage is invoked as a
- // task to prevent reentrancy.
- task_runner_->PostTask(FROM_HERE, base::Bind(&GpuChannel::HandleMessage,
- weak_factory_.GetWeakPtr()));
- handle_messages_scheduled_ = true;
-}
-
void GpuChannel::StubSchedulingChanged(bool scheduled) {
bool a_stub_was_descheduled = num_stubs_descheduled_ > 0;
if (scheduled) {
num_stubs_descheduled_--;
- OnScheduled();
+ message_queue_->ScheduleHandleMessage();
} else {
num_stubs_descheduled_++;
}
@@ -662,6 +760,11 @@ gpu::PreemptionFlag* GpuChannel::GetPreemptionFlag() {
return preempting_flag_.get();
}
+bool GpuChannel::handle_messages_scheduled() const {
+ base::AutoLock auto_lock(message_queue_->channel_messages_lock_);
+ return message_queue_->handle_messages_scheduled_;
+}
+
void GpuChannel::SetPreemptByFlag(
scoped_refptr<gpu::PreemptionFlag> preempted_flag) {
preempted_flag_ = preempted_flag;
@@ -691,35 +794,83 @@ bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
}
void GpuChannel::HandleMessage() {
- handle_messages_scheduled_ = false;
- if (deferred_messages_.empty())
- return;
+ ChannelMessage* m = nullptr;
+ GpuCommandBufferStub* stub = nullptr;
+ uint32_t sync_point_retired = 0;
+ {
+ base::AutoLock auto_lock(message_queue_->channel_messages_lock_);
+ message_queue_->handle_messages_scheduled_ = false;
+ if (message_queue_->channel_messages_.empty()) {
+ return;
+ }
+ m = message_queue_->channel_messages_.front();
+ stub = stubs_.get(m->message.routing_id());
- IPC::Message* m = NULL;
- GpuCommandBufferStub* stub = NULL;
+ // TODO(dyen): Temporary handling of old sync points.
+ // This must ensure that the sync point will be retired. Normally we'll
+ // find the stub based on the routing ID, and associate the sync point
+ // with it, but if that fails for any reason (channel or stub already
+ // deleted, invalid routing id), we need to retire the sync point
+ // immediately.
+ if (m->message.type() == GpuCommandBufferMsg_InsertSyncPoint::ID) {
piman 2015/09/01 03:55:26 Why not move that part of the logic after the lock
David Yen 2015/09/01 19:08:02 Done.
+ const bool retire = m->retire_sync_point;
+ const uint32_t sync_point = m->sync_point_number;
+ const int32_t routing_id = m->message.routing_id();
+ if (stub) {
+ stub->AddSyncPoint(sync_point);
+ if (retire) {
+ m->message = GpuCommandBufferMsg_RetireSyncPoint(routing_id,
+ sync_point);
+ }
+ } else {
+ sync_point_retired = sync_point;
+ }
+ }
- m = deferred_messages_.front();
- stub = stubs_.get(m->routing_id());
- if (stub) {
- if (!stub->IsScheduled())
- return;
- if (stub->IsPreempted()) {
- OnScheduled();
- return;
+ if (!sync_point_retired && stub) {
+ if (!stub->IsScheduled())
+ return;
+ if (stub->IsPreempted()) {
+ message_queue_->ScheduleHandleMessageLocked();
+ return;
+ }
}
+
+ message_queue_->channel_messages_.pop_front();
+ if (!message_queue_->channel_messages_.empty())
+ message_queue_->ScheduleHandleMessageLocked();
+ }
+
+ // TODO(dyen): Temporary handling of old sync points.
+ if (sync_point_retired) {
+ current_order_num_ = m->order_number;
+ gpu_channel_manager_->sync_point_manager()->RetireSyncPoint(
+ sync_point_retired);
+ MessageProcessed(m->order_number);
+ return;
}
- scoped_ptr<IPC::Message> message(m);
- deferred_messages_.pop_front();
+ scoped_ptr<ChannelMessage> scoped_message(m);
+ const uint32_t order_number = m->order_number;
+ IPC::Message* message = &m->message;
+
+ DVLOG(1) << "received message @" << message << " on channel @" << this
+ << " with type " << message->type();
+
bool message_processed = true;
- currently_processing_message_ = message.get();
+ if (order_number != static_cast<uint32_t>(-1)) {
+ // Make sure this is a valid unprocessed order number.
+ DCHECK(order_number <= GetUnprocessedOrderNum() &&
+ order_number >= GetProcessedOrderNum());
+
+ current_order_num_ = order_number;
+ }
bool result;
if (message->routing_id() == MSG_ROUTING_CONTROL)
result = OnControlMessageReceived(*message);
else
result = router_.RouteMessage(*message);
- currently_processing_message_ = NULL;
if (!result) {
// Respond to sync messages even if router failed to route.
@@ -734,18 +885,14 @@ void GpuChannel::HandleMessage() {
// message to flush that command buffer.
if (stub) {
if (stub->HasUnprocessedCommands()) {
- deferred_messages_.push_front(new GpuCommandBufferMsg_Rescheduled(
- stub->route_id()));
+ message_queue_->PushUnfinishedMessage(
+ order_number, GpuCommandBufferMsg_Rescheduled(stub->route_id()));
message_processed = false;
}
}
}
if (message_processed)
- MessageProcessed();
-
- if (!deferred_messages_.empty()) {
- OnScheduled();
- }
+ MessageProcessed(order_number);
}
void GpuChannel::OnCreateOffscreenCommandBuffer(
@@ -814,12 +961,15 @@ void GpuChannel::OnCreateJpegDecoder(int32 route_id, IPC::Message* reply_msg) {
jpeg_decoder_->AddClient(route_id, reply_msg);
}
-void GpuChannel::MessageProcessed() {
- messages_processed_++;
+void GpuChannel::MessageProcessed(uint32_t order_number) {
+ if (order_number != static_cast<uint32_t>(-1)) {
+ DCHECK(current_order_num_ == order_number);
+ processed_order_num_ = order_number;
+ }
if (preempting_flag_.get()) {
io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&GpuChannelMessageFilter::MessageProcessed,
- filter_, messages_processed_));
+ FROM_HERE, base::Bind(&GpuChannelMessageFilter::OnMessageProcessed,
+ filter_));
}
}
@@ -888,4 +1038,8 @@ void GpuChannel::HandleUpdateValueState(
pending_valuebuffer_state_->UpdateState(target, state);
}
+uint32_t GpuChannel::GetUnprocessedOrderNum() const {
+ return base::subtle::Acquire_Load(&message_queue_->unprocessed_order_num_);
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698