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

Side by Side Diff: cc/scheduler/scheduler_unittest.cc

Issue 1139613003: cc: Avoid deadlock with the UI thread and NPAPI in more cases (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright 2011 The Chromium Authors. All rights reserved. 1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/scheduler/scheduler.h" 5 #include "cc/scheduler/scheduler.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 1360 matching lines...) Expand 10 before | Expand all | Expand 10 after
1371 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true)); 1371 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true));
1372 } 1372 }
1373 1373
1374 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) { 1374 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) {
1375 // Set up client so that estimates indicate that we can commit and activate 1375 // Set up client so that estimates indicate that we can commit and activate
1376 // before the deadline (~8ms by default), but also enable impl latency takes 1376 // before the deadline (~8ms by default), but also enable impl latency takes
1377 // priority mode. 1377 // priority mode.
1378 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true)); 1378 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true));
1379 } 1379 }
1380 1380
1381 TEST_F(SchedulerTest, PollForCommitCompletion) { 1381 TEST_F(SchedulerTest,
1382 Deadlock_NotifyReadyToCommitMakesProgressWhileSwapTrottled) {
sunnyps 2015/05/14 00:02:02 Does this allow us to remove commit polling?
brianderson 2015/05/14 01:12:03 We can remove commit polling once TextureUploader
1383 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1384 // thread. This prevents the scheduler from receiving any pending swap acks.
1385 // This test makes sure that we keep updating the TextureUploader with
1386 // DidAnticipatedDrawTimeChange's so that it can make forward progress and
1387 // upload all the textures needed for the commit to complete.
1388
1382 // Since we are simulating a long commit, set up a client with draw duration 1389 // Since we are simulating a long commit, set up a client with draw duration
1383 // estimates that prevent skipping main frames to get to low latency mode. 1390 // estimates that prevent skipping main frames to get to low latency mode.
1384 SchedulerClientWithFixedEstimates* client = 1391 SchedulerClientWithFixedEstimates* client =
1385 new SchedulerClientWithFixedEstimates( 1392 new SchedulerClientWithFixedEstimates(
1386 base::TimeDelta::FromMilliseconds(1), 1393 base::TimeDelta::FromMilliseconds(1),
1387 base::TimeDelta::FromMilliseconds(32), 1394 base::TimeDelta::FromMilliseconds(32),
1388 base::TimeDelta::FromMilliseconds(32)); 1395 base::TimeDelta::FromMilliseconds(32));
1389 scheduler_settings_.use_external_begin_frame_source = true; 1396 scheduler_settings_.use_external_begin_frame_source = true;
1390 SetUpScheduler(make_scoped_ptr(client).Pass(), true); 1397 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1391 1398
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1432 task_runner().DelayToNextTaskTime().InMicroseconds()) 1439 task_runner().DelayToNextTaskTime().InMicroseconds())
1433 << scheduler_->AsValue()->ToString(); 1440 << scheduler_->AsValue()->ToString();
1434 task_runner().RunPendingTasks(); 1441 task_runner().RunPendingTasks();
1435 EXPECT_GT(client->num_actions_(), actions_so_far); 1442 EXPECT_GT(client->num_actions_(), actions_so_far);
1436 EXPECT_STREQ(client->Action(client->num_actions_() - 1), 1443 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1437 "DidAnticipatedDrawTimeChange"); 1444 "DidAnticipatedDrawTimeChange");
1438 actions_so_far = client->num_actions_(); 1445 actions_so_far = client->num_actions_();
1439 } 1446 }
1440 } 1447 }
1441 1448
1449 TEST_F(
1450 SchedulerTest,
1451 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) {
1452 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1453 // thread. This prevents the scheduler from receiving any pending swap acks.
1454 // The scheduler normally prioritizes draws over the commits, but doing so
1455 // unconditionally will result in deadlocks.
1456
1457 // Since we are simulating a long commit, set up a client with draw duration
1458 // estimates that prevent skipping main frames to get to low latency mode.
1459 SchedulerClientWithFixedEstimates* client =
1460 new SchedulerClientWithFixedEstimates(
1461 base::TimeDelta::FromMilliseconds(1),
1462 base::TimeDelta::FromMilliseconds(32),
1463 base::TimeDelta::FromMilliseconds(32));
1464 scheduler_settings_.use_external_begin_frame_source = true;
1465 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1466 scheduler_settings_.impl_side_painting = true;
1467 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1468
1469 // Disables automatic swap acks so this test can force swap ack throttling
1470 // to simulate a blocked Browser ui thread.
1471 scheduler_->SetMaxSwapsPending(1);
1472 client_->SetAutomaticSwapAck(false);
1473
1474 // Get a new active tree in main-thread high latency mode and put us
1475 // in a swap throttled state.
1476 client_->Reset();
1477 EXPECT_FALSE(scheduler_->CommitPending());
1478 scheduler_->SetNeedsCommit();
1479 scheduler_->SetNeedsRedraw();
1480 EXPECT_SCOPED(AdvanceFrame());
1481 EXPECT_TRUE(scheduler_->CommitPending());
1482 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1483 task_runner().RunPendingTasks(); // Run posted deadlines.
sunnyps 2015/05/14 00:02:02 RunTasksWhile(DeadlinePending).
1484 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1485 scheduler_->NotifyBeginMainFrameStarted();
1486 scheduler_->NotifyReadyToCommit();
1487 scheduler_->NotifyReadyToActivate();
1488 EXPECT_FALSE(scheduler_->CommitPending());
1489 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
sunnyps 2015/05/14 00:02:01 EXPECT_ACTION?
1490 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1491 EXPECT_TRUE(client->HasAction("ScheduledActionCommit"));
1492 EXPECT_TRUE(client->HasAction("ScheduledActionActivateSyncTree"));
1493
1494 // Make sure that we can finish the next commit even while swap throttled.
1495 client_->Reset();
1496 EXPECT_FALSE(scheduler_->CommitPending());
1497 scheduler_->SetNeedsCommit();
1498 EXPECT_SCOPED(AdvanceFrame());
1499 scheduler_->NotifyBeginMainFrameStarted();
1500 scheduler_->NotifyReadyToCommit();
1501 scheduler_->NotifyReadyToActivate();
1502 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1503 task_runner().RunPendingTasks(); // Run posted deadlines.
1504 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1505 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
sunnyps 2015/05/14 00:02:02 EXPECT_ACTION?
1506 EXPECT_TRUE(client->HasAction("ScheduledActionCommit"));
1507 EXPECT_FALSE(client->HasAction("ScheduledActionActivateSyncTree"));
1508
1509 // Make sure we do not send a BeginMainFrame while swap throttled and
1510 // we have both a pending tree and an active tree.
1511 client_->Reset();
1512 EXPECT_FALSE(scheduler_->CommitPending());
1513 scheduler_->SetNeedsCommit();
1514 EXPECT_SCOPED(AdvanceFrame());
1515 EXPECT_FALSE(scheduler_->CommitPending());
1516 task_runner().RunPendingTasks(); // Run posted deadline.
1517 EXPECT_FALSE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1518 }
1519
1520 TEST_F(SchedulerTest,
1521 Deadlock_CommitMakesProgressWhenIdleAndActiveTreeNeedsFirstDraw) {
sunnyps 2015/05/14 00:02:02 I think this test is for the "HavePendingTree" cas
brianderson 2015/05/14 01:12:03 It's also both. Will rename.
1522 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1523 // thread. This prevents the scheduler from receiving any pending swap acks.
1524 // The scheduler normally prioritizes draws over the commits, but doing so
1525 // unconditionally will result in deadlocks.
1526
1527 // Since we are simulating a long commit, set up a client with draw duration
1528 // estimates that prevent skipping main frames to get to low latency mode.
1529 SchedulerClientWithFixedEstimates* client =
1530 new SchedulerClientWithFixedEstimates(
1531 base::TimeDelta::FromMilliseconds(1),
1532 base::TimeDelta::FromMilliseconds(32),
1533 base::TimeDelta::FromMilliseconds(32));
1534 scheduler_settings_.use_external_begin_frame_source = true;
1535 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1536 scheduler_settings_.main_frame_before_activation_enabled = true;
1537 scheduler_settings_.impl_side_painting = true;
1538 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1539
1540 // Disables automatic swap acks so this test can force swap ack throttling
1541 // to simulate a blocked Browser ui thread.
1542 scheduler_->SetMaxSwapsPending(1);
1543 client_->SetAutomaticSwapAck(false);
1544
1545 // Start a new commit in main-thread high latency mode and hold off on
1546 // activation.
1547 client_->Reset();
1548 EXPECT_FALSE(scheduler_->CommitPending());
1549 scheduler_->SetNeedsCommit();
1550 scheduler_->SetNeedsRedraw();
1551 EXPECT_SCOPED(AdvanceFrame());
1552 EXPECT_TRUE(scheduler_->CommitPending());
1553 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1554 task_runner().RunPendingTasks(); // Run posted deadlines.
sunnyps 2015/05/14 00:02:02 RunTasksWhile(DeadlinePending).
1555 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1556 scheduler_->DidSwapBuffersComplete();
1557 scheduler_->NotifyBeginMainFrameStarted();
1558 scheduler_->NotifyReadyToCommit();
1559 EXPECT_FALSE(scheduler_->CommitPending());
1560 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
sunnyps 2015/05/14 00:02:01 EXPECT_ACTION?
1561 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1562 EXPECT_TRUE(client->HasAction("ScheduledActionCommit"));
1563 EXPECT_FALSE(client->HasAction("ScheduledActionActivateSyncTree"));
1564
1565 // Start another commit while we still have an active tree.
1566 client_->Reset();
1567 EXPECT_FALSE(scheduler_->CommitPending());
1568 scheduler_->SetNeedsCommit();
1569 scheduler_->SetNeedsRedraw();
1570 EXPECT_SCOPED(AdvanceFrame());
1571 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1572 EXPECT_TRUE(scheduler_->CommitPending());
1573 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1574 task_runner().RunPendingTasks(); // Run posted deadlines.
1575 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1576 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1577 scheduler_->DidSwapBuffersComplete();
1578 scheduler_->NotifyBeginMainFrameStarted();
1579
1580 // Can't commit yet because there's still a pending tree.
1581 scheduler_->NotifyReadyToCommit();
1582 EXPECT_FALSE(client->HasAction("ScheduledActionActivateSyncTree"));
1583 EXPECT_FALSE(client->HasAction("ScheduledActionCommit"));
1584
1585 // Activate the pending tree, which also unblocks the commit immediately.
1586 scheduler_->NotifyReadyToActivate();
1587 EXPECT_TRUE(client->HasAction("ScheduledActionActivateSyncTree"));
1588 EXPECT_TRUE(client->HasAction("ScheduledActionCommit"));
1589 }
1590
1591 TEST_F(SchedulerTest,
1592 Deadlock_NoBeginMainFrameWhileSwapTrottledAndHavePendingTree) {
sunnyps 2015/05/14 00:02:02 This is the "ActiveTreeNeedsFirstDraw" case.
brianderson 2015/05/14 01:12:03 It's both, I will change the name to: Deadlock_NoB
1593 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1594 // thread. This prevents the scheduler from receiving any pending swap acks.
1595 // The scheduler normally prioritizes draws over the commits, but doing so
1596 // unconditionally will result in deadlocks.
1597
1598 // Since we are simulating a long commit, set up a client with draw duration
1599 // estimates that prevent skipping main frames to get to low latency mode.
1600 SchedulerClientWithFixedEstimates* client =
1601 new SchedulerClientWithFixedEstimates(
1602 base::TimeDelta::FromMilliseconds(1),
1603 base::TimeDelta::FromMilliseconds(32),
1604 base::TimeDelta::FromMilliseconds(32));
1605 scheduler_settings_.use_external_begin_frame_source = true;
1606 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1607 scheduler_settings_.main_frame_before_activation_enabled = true;
1608 scheduler_settings_.impl_side_painting = true;
1609 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1610
1611 // Disables automatic swap acks so this test can force swap ack throttling
1612 // to simulate a blocked Browser ui thread.
1613 scheduler_->SetMaxSwapsPending(1);
1614 client_->SetAutomaticSwapAck(false);
1615
1616 // Start a new commit in main-thread high latency mode and hold off on
1617 // activation.
1618 client_->Reset();
1619 EXPECT_FALSE(scheduler_->CommitPending());
1620 scheduler_->SetNeedsCommit();
1621 scheduler_->SetNeedsRedraw();
1622 EXPECT_SCOPED(AdvanceFrame());
1623 EXPECT_TRUE(scheduler_->CommitPending());
1624 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1625 task_runner().RunPendingTasks(); // Run posted deadlines.
1626 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1627 scheduler_->DidSwapBuffersComplete();
1628 scheduler_->NotifyBeginMainFrameStarted();
1629 scheduler_->NotifyReadyToCommit();
1630 EXPECT_FALSE(scheduler_->CommitPending());
1631 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1632 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1633 EXPECT_TRUE(client->HasAction("ScheduledActionCommit"));
1634 EXPECT_FALSE(client->HasAction("ScheduledActionActivateSyncTree"));
1635
1636 // Start another commit while we still have an active tree.
1637 // Enter a swap throttled state.
1638 client_->Reset();
1639 EXPECT_FALSE(scheduler_->CommitPending());
1640 scheduler_->SetNeedsCommit();
1641 scheduler_->SetNeedsRedraw();
1642 EXPECT_SCOPED(AdvanceFrame());
1643 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1644 EXPECT_TRUE(scheduler_->CommitPending());
1645 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1646 task_runner().RunPendingTasks(); // Run posted deadlines.
1647 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1648 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1649 scheduler_->NotifyBeginMainFrameStarted();
1650
1651 // Can't commit yet because there's still a pending tree.
1652 scheduler_->NotifyReadyToCommit();
1653 EXPECT_FALSE(client->HasAction("ScheduledActionActivateSyncTree"));
1654 EXPECT_FALSE(client->HasAction("ScheduledActionCommit"));
1655
1656 // Activate the pending tree, which also unblocks the commit immediately.
1657 scheduler_->NotifyReadyToActivate();
1658 EXPECT_TRUE(client->HasAction("ScheduledActionActivateSyncTree"));
1659 EXPECT_TRUE(client->HasAction("ScheduledActionCommit"));
1660
1661 // Make sure we do not send a BeginMainFrame while swap throttled and
1662 // we have both a pending tree and an active tree that still needs
1663 // it's first draw.
1664 client_->Reset();
1665 EXPECT_FALSE(scheduler_->CommitPending());
1666 scheduler_->SetNeedsCommit();
1667 EXPECT_SCOPED(AdvanceFrame());
1668 EXPECT_FALSE(scheduler_->CommitPending());
1669 task_runner().RunPendingTasks(); // Run posted deadline.
1670 EXPECT_FALSE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1671 }
1672
1673 TEST_F(SchedulerTest,
1674 Deadlock_NoBeginMainFrameWhileSwapTrottledAndActiveTreeNeedsFirstDraw) {
sunnyps 2015/05/14 00:02:02 In this case BeginMainFrame is blocked because of
brianderson 2015/05/14 01:12:03 Sorry, my comments in the test were wrong. This te
1675 // This test only applies with non-impl-side painting, where we do not have a
1676 // pending tree and might not be able to commit if we send a BeginMainFrame.
1677
1678 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1679 // thread. This prevents the scheduler from receiving any pending swap acks.
1680 // The scheduler normally prioritizes draws over the commits, but doing so
1681 // unconditionally will result in deadlocks.
1682
1683 // Since we are simulating a long commit, set up a client with draw duration
1684 // estimates that prevent skipping main frames to get to low latency mode.
1685 SchedulerClientWithFixedEstimates* client =
1686 new SchedulerClientWithFixedEstimates(
1687 base::TimeDelta::FromMilliseconds(1),
1688 base::TimeDelta::FromMilliseconds(32),
1689 base::TimeDelta::FromMilliseconds(32));
1690 scheduler_settings_.use_external_begin_frame_source = true;
1691 scheduler_settings_.impl_side_painting = false;
1692 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1693
1694 // Disables automatic swap acks so this test can force swap ack throttling
1695 // to simulate a blocked Browser ui thread.
1696 scheduler_->SetMaxSwapsPending(1);
1697 client_->SetAutomaticSwapAck(false);
1698
1699 // Get a new active tree in main-thread high latency mode.
1700 client_->Reset();
1701 EXPECT_FALSE(scheduler_->CommitPending());
1702 scheduler_->SetNeedsCommit();
1703 scheduler_->SetNeedsRedraw();
1704 EXPECT_SCOPED(AdvanceFrame());
1705 EXPECT_TRUE(scheduler_->CommitPending());
1706 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1707 task_runner().RunPendingTasks(); // Run posted deadlines.
1708 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1709 scheduler_->NotifyBeginMainFrameStarted();
1710 scheduler_->NotifyReadyToCommit();
1711 EXPECT_FALSE(scheduler_->CommitPending());
1712 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1713 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1714 EXPECT_TRUE(client->HasAction("ScheduledActionCommit"));
1715
1716 // Make sure we do not send a BeginMainFrame while swap throttled and
1717 // we have both a pending tree and an active tree.
1718 client_->Reset();
1719 EXPECT_FALSE(scheduler_->CommitPending());
1720 scheduler_->SetNeedsCommit();
1721 EXPECT_SCOPED(AdvanceFrame());
1722 EXPECT_FALSE(scheduler_->CommitPending());
1723 task_runner().RunPendingTasks(); // Run posted deadline.
1724 EXPECT_FALSE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1725 }
1726
1442 TEST_F(SchedulerTest, BeginRetroFrame) { 1727 TEST_F(SchedulerTest, BeginRetroFrame) {
1443 scheduler_settings_.use_external_begin_frame_source = true; 1728 scheduler_settings_.use_external_begin_frame_source = true;
1444 SetUpScheduler(true); 1729 SetUpScheduler(true);
1445 1730
1446 // SetNeedsCommit should begin the frame on the next BeginImplFrame. 1731 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1447 scheduler_->SetNeedsCommit(); 1732 scheduler_->SetNeedsCommit();
1448 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); 1733 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1449 client_->Reset(); 1734 client_->Reset();
1450 1735
1451 // Create a BeginFrame with a long deadline to avoid race conditions. 1736 // Create a BeginFrame with a long deadline to avoid race conditions.
(...skipping 1187 matching lines...) Expand 10 before | Expand all | Expand 10 after
2639 2924
2640 // At the next BeginFrame, authoritative interval is used instead of previous 2925 // At the next BeginFrame, authoritative interval is used instead of previous
2641 // interval. 2926 // interval.
2642 EXPECT_NE(initial_interval, scheduler_->begin_impl_frame_args().interval); 2927 EXPECT_NE(initial_interval, scheduler_->begin_impl_frame_args().interval);
2643 EXPECT_EQ(authoritative_interval, 2928 EXPECT_EQ(authoritative_interval,
2644 scheduler_->begin_impl_frame_args().interval); 2929 scheduler_->begin_impl_frame_args().interval);
2645 } 2930 }
2646 2931
2647 } // namespace 2932 } // namespace
2648 } // namespace cc 2933 } // namespace cc
OLDNEW
« cc/scheduler/scheduler_state_machine.cc ('K') | « cc/scheduler/scheduler_state_machine.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698