1// Copyright (c) 2012 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// This file contains the tests for the FencedAllocator class. 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/memory/aligned_memory.h" 10#include "base/message_loop/message_loop.h" 11#include "gpu/command_buffer/client/cmd_buffer_helper.h" 12#include "gpu/command_buffer/client/fenced_allocator.h" 13#include "gpu/command_buffer/service/cmd_buffer_engine.h" 14#include "gpu/command_buffer/service/command_buffer_service.h" 15#include "gpu/command_buffer/service/gpu_scheduler.h" 16#include "gpu/command_buffer/service/mocks.h" 17#include "gpu/command_buffer/service/transfer_buffer_manager.h" 18#include "testing/gtest/include/gtest/gtest.h" 19 20#if defined(OS_MACOSX) 21#include "base/mac/scoped_nsautorelease_pool.h" 22#endif 23 24namespace gpu { 25 26using testing::Return; 27using testing::Mock; 28using testing::Truly; 29using testing::Sequence; 30using testing::DoAll; 31using testing::Invoke; 32using testing::InvokeWithoutArgs; 33using testing::_; 34 35class BaseFencedAllocatorTest : public testing::Test { 36 protected: 37 static const unsigned int kBufferSize = 1024; 38 static const int kAllocAlignment = 16; 39 40 virtual void SetUp() { 41 api_mock_.reset(new AsyncAPIMock(true)); 42 // ignore noops in the mock - we don't want to inspect the internals of the 43 // helper. 44 EXPECT_CALL(*api_mock_, DoCommand(cmd::kNoop, 0, _)) 45 .WillRepeatedly(Return(error::kNoError)); 46 // Forward the SetToken calls to the engine 47 EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _)) 48 .WillRepeatedly(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken), 49 Return(error::kNoError))); 50 51 { 52 TransferBufferManager* manager = new TransferBufferManager(); 53 transfer_buffer_manager_.reset(manager); 54 EXPECT_TRUE(manager->Initialize()); 55 } 56 command_buffer_.reset( 57 new CommandBufferService(transfer_buffer_manager_.get())); 58 EXPECT_TRUE(command_buffer_->Initialize()); 59 60 gpu_scheduler_.reset(new GpuScheduler( 61 command_buffer_.get(), api_mock_.get(), NULL)); 62 command_buffer_->SetPutOffsetChangeCallback(base::Bind( 63 &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get()))); 64 command_buffer_->SetGetBufferChangeCallback(base::Bind( 65 &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get()))); 66 67 api_mock_->set_engine(gpu_scheduler_.get()); 68 69 helper_.reset(new CommandBufferHelper(command_buffer_.get())); 70 helper_->Initialize(kBufferSize); 71 } 72 73 int32 GetToken() { 74 return command_buffer_->GetLastState().token; 75 } 76 77#if defined(OS_MACOSX) 78 base::mac::ScopedNSAutoreleasePool autorelease_pool_; 79#endif 80 base::MessageLoop message_loop_; 81 scoped_ptr<AsyncAPIMock> api_mock_; 82 scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; 83 scoped_ptr<CommandBufferService> command_buffer_; 84 scoped_ptr<GpuScheduler> gpu_scheduler_; 85 scoped_ptr<CommandBufferHelper> helper_; 86}; 87 88#ifndef _MSC_VER 89const unsigned int BaseFencedAllocatorTest::kBufferSize; 90#endif 91 92namespace { 93void EmptyPoll() { 94} 95} 96 97// Test fixture for FencedAllocator test - Creates a FencedAllocator, using a 98// CommandBufferHelper with a mock AsyncAPIInterface for its interface (calling 99// it directly, not through the RPC mechanism), making sure Noops are ignored 100// and SetToken are properly forwarded to the engine. 101class FencedAllocatorTest : public BaseFencedAllocatorTest { 102 protected: 103 virtual void SetUp() { 104 BaseFencedAllocatorTest::SetUp(); 105 allocator_.reset(new FencedAllocator(kBufferSize, 106 helper_.get(), 107 base::Bind(&EmptyPoll))); 108 } 109 110 virtual void TearDown() { 111 // If the GpuScheduler posts any tasks, this forces them to run. 112 base::MessageLoop::current()->RunUntilIdle(); 113 114 EXPECT_TRUE(allocator_->CheckConsistency()); 115 116 BaseFencedAllocatorTest::TearDown(); 117 } 118 119 scoped_ptr<FencedAllocator> allocator_; 120}; 121 122// Checks basic alloc and free. 123TEST_F(FencedAllocatorTest, TestBasic) { 124 allocator_->CheckConsistency(); 125 EXPECT_FALSE(allocator_->InUse()); 126 127 const unsigned int kSize = 16; 128 FencedAllocator::Offset offset = allocator_->Alloc(kSize); 129 EXPECT_TRUE(allocator_->InUse()); 130 EXPECT_NE(FencedAllocator::kInvalidOffset, offset); 131 EXPECT_GE(kBufferSize, offset+kSize); 132 EXPECT_TRUE(allocator_->CheckConsistency()); 133 134 allocator_->Free(offset); 135 EXPECT_FALSE(allocator_->InUse()); 136 EXPECT_TRUE(allocator_->CheckConsistency()); 137} 138 139// Test alloc 0 fails. 140TEST_F(FencedAllocatorTest, TestAllocZero) { 141 FencedAllocator::Offset offset = allocator_->Alloc(0); 142 EXPECT_EQ(FencedAllocator::kInvalidOffset, offset); 143 EXPECT_FALSE(allocator_->InUse()); 144 EXPECT_TRUE(allocator_->CheckConsistency()); 145} 146 147// Checks out-of-memory condition. 148TEST_F(FencedAllocatorTest, TestOutOfMemory) { 149 EXPECT_TRUE(allocator_->CheckConsistency()); 150 151 const unsigned int kSize = 16; 152 const unsigned int kAllocCount = kBufferSize / kSize; 153 CHECK(kAllocCount * kSize == kBufferSize); 154 155 // Allocate several buffers to fill in the memory. 156 FencedAllocator::Offset offsets[kAllocCount]; 157 for (unsigned int i = 0; i < kAllocCount; ++i) { 158 offsets[i] = allocator_->Alloc(kSize); 159 EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]); 160 EXPECT_GE(kBufferSize, offsets[i]+kSize); 161 EXPECT_TRUE(allocator_->CheckConsistency()); 162 } 163 164 // This allocation should fail. 165 FencedAllocator::Offset offset_failed = allocator_->Alloc(kSize); 166 EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed); 167 EXPECT_TRUE(allocator_->CheckConsistency()); 168 169 // Free one successful allocation, reallocate with half the size 170 allocator_->Free(offsets[0]); 171 EXPECT_TRUE(allocator_->CheckConsistency()); 172 offsets[0] = allocator_->Alloc(kSize/2); 173 EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[0]); 174 EXPECT_GE(kBufferSize, offsets[0]+kSize); 175 EXPECT_TRUE(allocator_->CheckConsistency()); 176 177 // This allocation should fail as well. 178 offset_failed = allocator_->Alloc(kSize); 179 EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed); 180 EXPECT_TRUE(allocator_->CheckConsistency()); 181 182 // Free up everything. 183 for (unsigned int i = 0; i < kAllocCount; ++i) { 184 allocator_->Free(offsets[i]); 185 EXPECT_TRUE(allocator_->CheckConsistency()); 186 } 187} 188 189// Checks the free-pending-token mechanism. 190TEST_F(FencedAllocatorTest, TestFreePendingToken) { 191 EXPECT_TRUE(allocator_->CheckConsistency()); 192 193 const unsigned int kSize = 16; 194 const unsigned int kAllocCount = kBufferSize / kSize; 195 CHECK(kAllocCount * kSize == kBufferSize); 196 197 // Allocate several buffers to fill in the memory. 198 FencedAllocator::Offset offsets[kAllocCount]; 199 for (unsigned int i = 0; i < kAllocCount; ++i) { 200 offsets[i] = allocator_->Alloc(kSize); 201 EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]); 202 EXPECT_GE(kBufferSize, offsets[i]+kSize); 203 EXPECT_TRUE(allocator_->CheckConsistency()); 204 } 205 206 // This allocation should fail. 207 FencedAllocator::Offset offset_failed = allocator_->Alloc(kSize); 208 EXPECT_EQ(FencedAllocator::kInvalidOffset, offset_failed); 209 EXPECT_TRUE(allocator_->CheckConsistency()); 210 211 // Free one successful allocation, pending fence. 212 int32 token = helper_.get()->InsertToken(); 213 allocator_->FreePendingToken(offsets[0], token); 214 EXPECT_TRUE(allocator_->CheckConsistency()); 215 216 // The way we hooked up the helper and engine, it won't process commands 217 // until it has to wait for something. Which means the token shouldn't have 218 // passed yet at this point. 219 EXPECT_GT(token, GetToken()); 220 221 // This allocation will need to reclaim the space freed above, so that should 222 // process the commands until the token is passed. 223 offsets[0] = allocator_->Alloc(kSize); 224 EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[0]); 225 EXPECT_GE(kBufferSize, offsets[0]+kSize); 226 EXPECT_TRUE(allocator_->CheckConsistency()); 227 // Check that the token has indeed passed. 228 EXPECT_LE(token, GetToken()); 229 230 // Free up everything. 231 for (unsigned int i = 0; i < kAllocCount; ++i) { 232 allocator_->Free(offsets[i]); 233 EXPECT_TRUE(allocator_->CheckConsistency()); 234 } 235} 236 237// Checks the free-pending-token mechanism using FreeUnused 238TEST_F(FencedAllocatorTest, FreeUnused) { 239 EXPECT_TRUE(allocator_->CheckConsistency()); 240 241 const unsigned int kSize = 16; 242 const unsigned int kAllocCount = kBufferSize / kSize; 243 CHECK(kAllocCount * kSize == kBufferSize); 244 245 // Allocate several buffers to fill in the memory. 246 FencedAllocator::Offset offsets[kAllocCount]; 247 for (unsigned int i = 0; i < kAllocCount; ++i) { 248 offsets[i] = allocator_->Alloc(kSize); 249 EXPECT_NE(FencedAllocator::kInvalidOffset, offsets[i]); 250 EXPECT_GE(kBufferSize, offsets[i]+kSize); 251 EXPECT_TRUE(allocator_->CheckConsistency()); 252 } 253 EXPECT_TRUE(allocator_->InUse()); 254 255 // No memory should be available. 256 EXPECT_EQ(0u, allocator_->GetLargestFreeSize()); 257 258 // Free one successful allocation, pending fence. 259 int32 token = helper_.get()->InsertToken(); 260 allocator_->FreePendingToken(offsets[0], token); 261 EXPECT_TRUE(allocator_->CheckConsistency()); 262 263 // Force the command buffer to process the token. 264 helper_->Finish(); 265 266 // Tell the allocator to update what's available based on the current token. 267 allocator_->FreeUnused(); 268 269 // Check that the new largest free size takes into account the unused block. 270 EXPECT_EQ(kSize, allocator_->GetLargestFreeSize()); 271 272 // Free two more. 273 token = helper_.get()->InsertToken(); 274 allocator_->FreePendingToken(offsets[1], token); 275 token = helper_.get()->InsertToken(); 276 allocator_->FreePendingToken(offsets[2], token); 277 EXPECT_TRUE(allocator_->CheckConsistency()); 278 279 // Check that nothing has changed. 280 EXPECT_EQ(kSize, allocator_->GetLargestFreeSize()); 281 282 // Force the command buffer to process the token. 283 helper_->Finish(); 284 285 // Tell the allocator to update what's available based on the current token. 286 allocator_->FreeUnused(); 287 288 // Check that the new largest free size takes into account the unused blocks. 289 EXPECT_EQ(kSize * 3, allocator_->GetLargestFreeSize()); 290 EXPECT_TRUE(allocator_->InUse()); 291 292 // Free up everything. 293 for (unsigned int i = 3; i < kAllocCount; ++i) { 294 allocator_->Free(offsets[i]); 295 EXPECT_TRUE(allocator_->CheckConsistency()); 296 } 297 EXPECT_FALSE(allocator_->InUse()); 298} 299 300// Tests GetLargestFreeSize 301TEST_F(FencedAllocatorTest, TestGetLargestFreeSize) { 302 EXPECT_TRUE(allocator_->CheckConsistency()); 303 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize()); 304 305 FencedAllocator::Offset offset = allocator_->Alloc(kBufferSize); 306 ASSERT_NE(FencedAllocator::kInvalidOffset, offset); 307 EXPECT_EQ(0u, allocator_->GetLargestFreeSize()); 308 allocator_->Free(offset); 309 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize()); 310 311 const unsigned int kSize = 16; 312 offset = allocator_->Alloc(kSize); 313 ASSERT_NE(FencedAllocator::kInvalidOffset, offset); 314 // The following checks that the buffer is allocated "smartly" - which is 315 // dependent on the implementation. But both first-fit or best-fit would 316 // ensure that. 317 EXPECT_EQ(kBufferSize - kSize, allocator_->GetLargestFreeSize()); 318 319 // Allocate 2 more buffers (now 3), and then free the first two. This is to 320 // ensure a hole. Note that this is dependent on the first-fit current 321 // implementation. 322 FencedAllocator::Offset offset1 = allocator_->Alloc(kSize); 323 ASSERT_NE(FencedAllocator::kInvalidOffset, offset1); 324 FencedAllocator::Offset offset2 = allocator_->Alloc(kSize); 325 ASSERT_NE(FencedAllocator::kInvalidOffset, offset2); 326 allocator_->Free(offset); 327 allocator_->Free(offset1); 328 EXPECT_EQ(kBufferSize - 3 * kSize, allocator_->GetLargestFreeSize()); 329 330 offset = allocator_->Alloc(kBufferSize - 3 * kSize); 331 ASSERT_NE(FencedAllocator::kInvalidOffset, offset); 332 EXPECT_EQ(2 * kSize, allocator_->GetLargestFreeSize()); 333 334 offset1 = allocator_->Alloc(2 * kSize); 335 ASSERT_NE(FencedAllocator::kInvalidOffset, offset1); 336 EXPECT_EQ(0u, allocator_->GetLargestFreeSize()); 337 338 allocator_->Free(offset); 339 allocator_->Free(offset1); 340 allocator_->Free(offset2); 341} 342 343// Tests GetLargestFreeOrPendingSize 344TEST_F(FencedAllocatorTest, TestGetLargestFreeOrPendingSize) { 345 EXPECT_TRUE(allocator_->CheckConsistency()); 346 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize()); 347 348 FencedAllocator::Offset offset = allocator_->Alloc(kBufferSize); 349 ASSERT_NE(FencedAllocator::kInvalidOffset, offset); 350 EXPECT_EQ(0u, allocator_->GetLargestFreeOrPendingSize()); 351 allocator_->Free(offset); 352 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize()); 353 354 const unsigned int kSize = 16; 355 offset = allocator_->Alloc(kSize); 356 ASSERT_NE(FencedAllocator::kInvalidOffset, offset); 357 // The following checks that the buffer is allocates "smartly" - which is 358 // dependent on the implementation. But both first-fit or best-fit would 359 // ensure that. 360 EXPECT_EQ(kBufferSize - kSize, allocator_->GetLargestFreeOrPendingSize()); 361 362 // Allocate 2 more buffers (now 3), and then free the first two. This is to 363 // ensure a hole. Note that this is dependent on the first-fit current 364 // implementation. 365 FencedAllocator::Offset offset1 = allocator_->Alloc(kSize); 366 ASSERT_NE(FencedAllocator::kInvalidOffset, offset1); 367 FencedAllocator::Offset offset2 = allocator_->Alloc(kSize); 368 ASSERT_NE(FencedAllocator::kInvalidOffset, offset2); 369 allocator_->Free(offset); 370 allocator_->Free(offset1); 371 EXPECT_EQ(kBufferSize - 3 * kSize, 372 allocator_->GetLargestFreeOrPendingSize()); 373 374 // Free the last one, pending a token. 375 int32 token = helper_.get()->InsertToken(); 376 allocator_->FreePendingToken(offset2, token); 377 378 // Now all the buffers have been freed... 379 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize()); 380 // .. but one is still waiting for the token. 381 EXPECT_EQ(kBufferSize - 3 * kSize, 382 allocator_->GetLargestFreeSize()); 383 384 // The way we hooked up the helper and engine, it won't process commands 385 // until it has to wait for something. Which means the token shouldn't have 386 // passed yet at this point. 387 EXPECT_GT(token, GetToken()); 388 // This allocation will need to reclaim the space freed above, so that should 389 // process the commands until the token is passed, but it will succeed. 390 offset = allocator_->Alloc(kBufferSize); 391 ASSERT_NE(FencedAllocator::kInvalidOffset, offset); 392 // Check that the token has indeed passed. 393 EXPECT_LE(token, GetToken()); 394 allocator_->Free(offset); 395 396 // Everything now has been freed... 397 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize()); 398 // ... for real. 399 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSize()); 400} 401 402class FencedAllocatorPollTest : public BaseFencedAllocatorTest { 403 public: 404 static const unsigned int kAllocSize = 128; 405 406 MOCK_METHOD0(MockedPoll, void()); 407 408 protected: 409 virtual void TearDown() { 410 // If the GpuScheduler posts any tasks, this forces them to run. 411 base::MessageLoop::current()->RunUntilIdle(); 412 413 BaseFencedAllocatorTest::TearDown(); 414 } 415}; 416 417TEST_F(FencedAllocatorPollTest, TestPoll) { 418 scoped_ptr<FencedAllocator> allocator( 419 new FencedAllocator(kBufferSize, 420 helper_.get(), 421 base::Bind(&FencedAllocatorPollTest::MockedPoll, 422 base::Unretained(this)))); 423 424 FencedAllocator::Offset mem1 = allocator->Alloc(kAllocSize); 425 FencedAllocator::Offset mem2 = allocator->Alloc(kAllocSize); 426 EXPECT_NE(mem1, FencedAllocator::kInvalidOffset); 427 EXPECT_NE(mem2, FencedAllocator::kInvalidOffset); 428 EXPECT_TRUE(allocator->CheckConsistency()); 429 EXPECT_EQ(allocator->bytes_in_use(), kAllocSize * 2); 430 431 // Check that no-op Poll doesn't affect the state. 432 EXPECT_CALL(*this, MockedPoll()).RetiresOnSaturation(); 433 allocator->FreeUnused(); 434 EXPECT_TRUE(allocator->CheckConsistency()); 435 EXPECT_EQ(allocator->bytes_in_use(), kAllocSize * 2); 436 437 // Check that freeing in Poll works. 438 base::Closure free_mem1_closure = 439 base::Bind(&FencedAllocator::Free, 440 base::Unretained(allocator.get()), 441 mem1); 442 EXPECT_CALL(*this, MockedPoll()) 443 .WillOnce(InvokeWithoutArgs(&free_mem1_closure, &base::Closure::Run)) 444 .RetiresOnSaturation(); 445 allocator->FreeUnused(); 446 EXPECT_TRUE(allocator->CheckConsistency()); 447 EXPECT_EQ(allocator->bytes_in_use(), kAllocSize * 1); 448 449 // Check that freeing still works. 450 EXPECT_CALL(*this, MockedPoll()).RetiresOnSaturation(); 451 allocator->Free(mem2); 452 allocator->FreeUnused(); 453 EXPECT_TRUE(allocator->CheckConsistency()); 454 EXPECT_EQ(allocator->bytes_in_use(), 0u); 455 456 allocator.reset(); 457} 458 459// Test fixture for FencedAllocatorWrapper test - Creates a 460// FencedAllocatorWrapper, using a CommandBufferHelper with a mock 461// AsyncAPIInterface for its interface (calling it directly, not through the 462// RPC mechanism), making sure Noops are ignored and SetToken are properly 463// forwarded to the engine. 464class FencedAllocatorWrapperTest : public BaseFencedAllocatorTest { 465 protected: 466 virtual void SetUp() { 467 BaseFencedAllocatorTest::SetUp(); 468 469 // Though allocating this buffer isn't strictly necessary, it makes 470 // allocations point to valid addresses, so they could be used for 471 // something. 472 buffer_.reset(static_cast<char*>(base::AlignedAlloc( 473 kBufferSize, kAllocAlignment))); 474 allocator_.reset(new FencedAllocatorWrapper(kBufferSize, 475 helper_.get(), 476 base::Bind(&EmptyPoll), 477 buffer_.get())); 478 } 479 480 virtual void TearDown() { 481 // If the GpuScheduler posts any tasks, this forces them to run. 482 base::MessageLoop::current()->RunUntilIdle(); 483 484 EXPECT_TRUE(allocator_->CheckConsistency()); 485 486 BaseFencedAllocatorTest::TearDown(); 487 } 488 489 scoped_ptr<FencedAllocatorWrapper> allocator_; 490 scoped_ptr<char, base::AlignedFreeDeleter> buffer_; 491}; 492 493// Checks basic alloc and free. 494TEST_F(FencedAllocatorWrapperTest, TestBasic) { 495 allocator_->CheckConsistency(); 496 497 const unsigned int kSize = 16; 498 void *pointer = allocator_->Alloc(kSize); 499 ASSERT_TRUE(pointer); 500 EXPECT_LE(buffer_.get(), static_cast<char *>(pointer)); 501 EXPECT_GE(kBufferSize, static_cast<char *>(pointer) - buffer_.get() + kSize); 502 EXPECT_TRUE(allocator_->CheckConsistency()); 503 504 allocator_->Free(pointer); 505 EXPECT_TRUE(allocator_->CheckConsistency()); 506 507 char *pointer_char = allocator_->AllocTyped<char>(kSize); 508 ASSERT_TRUE(pointer_char); 509 EXPECT_LE(buffer_.get(), pointer_char); 510 EXPECT_GE(buffer_.get() + kBufferSize, pointer_char + kSize); 511 allocator_->Free(pointer_char); 512 EXPECT_TRUE(allocator_->CheckConsistency()); 513 514 unsigned int *pointer_uint = allocator_->AllocTyped<unsigned int>(kSize); 515 ASSERT_TRUE(pointer_uint); 516 EXPECT_LE(buffer_.get(), reinterpret_cast<char *>(pointer_uint)); 517 EXPECT_GE(buffer_.get() + kBufferSize, 518 reinterpret_cast<char *>(pointer_uint + kSize)); 519 520 // Check that it did allocate kSize * sizeof(unsigned int). We can't tell 521 // directly, except from the remaining size. 522 EXPECT_EQ(kBufferSize - kSize * sizeof(*pointer_uint), 523 allocator_->GetLargestFreeSize()); 524 allocator_->Free(pointer_uint); 525} 526 527// Test alloc 0 fails. 528TEST_F(FencedAllocatorWrapperTest, TestAllocZero) { 529 allocator_->CheckConsistency(); 530 531 void *pointer = allocator_->Alloc(0); 532 ASSERT_FALSE(pointer); 533 EXPECT_TRUE(allocator_->CheckConsistency()); 534} 535 536// Checks that allocation offsets are aligned to multiples of 16 bytes. 537TEST_F(FencedAllocatorWrapperTest, TestAlignment) { 538 allocator_->CheckConsistency(); 539 540 const unsigned int kSize1 = 75; 541 void *pointer1 = allocator_->Alloc(kSize1); 542 ASSERT_TRUE(pointer1); 543 EXPECT_EQ(reinterpret_cast<intptr_t>(pointer1) & (kAllocAlignment - 1), 0); 544 EXPECT_TRUE(allocator_->CheckConsistency()); 545 546 const unsigned int kSize2 = 43; 547 void *pointer2 = allocator_->Alloc(kSize2); 548 ASSERT_TRUE(pointer2); 549 EXPECT_EQ(reinterpret_cast<intptr_t>(pointer2) & (kAllocAlignment - 1), 0); 550 EXPECT_TRUE(allocator_->CheckConsistency()); 551 552 allocator_->Free(pointer2); 553 EXPECT_TRUE(allocator_->CheckConsistency()); 554 555 allocator_->Free(pointer1); 556 EXPECT_TRUE(allocator_->CheckConsistency()); 557} 558 559// Checks out-of-memory condition. 560TEST_F(FencedAllocatorWrapperTest, TestOutOfMemory) { 561 allocator_->CheckConsistency(); 562 563 const unsigned int kSize = 16; 564 const unsigned int kAllocCount = kBufferSize / kSize; 565 CHECK(kAllocCount * kSize == kBufferSize); 566 567 // Allocate several buffers to fill in the memory. 568 void *pointers[kAllocCount]; 569 for (unsigned int i = 0; i < kAllocCount; ++i) { 570 pointers[i] = allocator_->Alloc(kSize); 571 EXPECT_TRUE(pointers[i]); 572 EXPECT_TRUE(allocator_->CheckConsistency()); 573 } 574 575 // This allocation should fail. 576 void *pointer_failed = allocator_->Alloc(kSize); 577 EXPECT_FALSE(pointer_failed); 578 EXPECT_TRUE(allocator_->CheckConsistency()); 579 580 // Free one successful allocation, reallocate with half the size 581 allocator_->Free(pointers[0]); 582 EXPECT_TRUE(allocator_->CheckConsistency()); 583 pointers[0] = allocator_->Alloc(kSize/2); 584 EXPECT_TRUE(pointers[0]); 585 EXPECT_TRUE(allocator_->CheckConsistency()); 586 587 // This allocation should fail as well. 588 pointer_failed = allocator_->Alloc(kSize); 589 EXPECT_FALSE(pointer_failed); 590 EXPECT_TRUE(allocator_->CheckConsistency()); 591 592 // Free up everything. 593 for (unsigned int i = 0; i < kAllocCount; ++i) { 594 allocator_->Free(pointers[i]); 595 EXPECT_TRUE(allocator_->CheckConsistency()); 596 } 597} 598 599// Checks the free-pending-token mechanism. 600TEST_F(FencedAllocatorWrapperTest, TestFreePendingToken) { 601 allocator_->CheckConsistency(); 602 603 const unsigned int kSize = 16; 604 const unsigned int kAllocCount = kBufferSize / kSize; 605 CHECK(kAllocCount * kSize == kBufferSize); 606 607 // Allocate several buffers to fill in the memory. 608 void *pointers[kAllocCount]; 609 for (unsigned int i = 0; i < kAllocCount; ++i) { 610 pointers[i] = allocator_->Alloc(kSize); 611 EXPECT_TRUE(pointers[i]); 612 EXPECT_TRUE(allocator_->CheckConsistency()); 613 } 614 615 // This allocation should fail. 616 void *pointer_failed = allocator_->Alloc(kSize); 617 EXPECT_FALSE(pointer_failed); 618 EXPECT_TRUE(allocator_->CheckConsistency()); 619 620 // Free one successful allocation, pending fence. 621 int32 token = helper_.get()->InsertToken(); 622 allocator_->FreePendingToken(pointers[0], token); 623 EXPECT_TRUE(allocator_->CheckConsistency()); 624 625 // The way we hooked up the helper and engine, it won't process commands 626 // until it has to wait for something. Which means the token shouldn't have 627 // passed yet at this point. 628 EXPECT_GT(token, GetToken()); 629 630 // This allocation will need to reclaim the space freed above, so that should 631 // process the commands until the token is passed. 632 pointers[0] = allocator_->Alloc(kSize); 633 EXPECT_TRUE(pointers[0]); 634 EXPECT_TRUE(allocator_->CheckConsistency()); 635 // Check that the token has indeed passed. 636 EXPECT_LE(token, GetToken()); 637 638 // Free up everything. 639 for (unsigned int i = 0; i < kAllocCount; ++i) { 640 allocator_->Free(pointers[i]); 641 EXPECT_TRUE(allocator_->CheckConsistency()); 642 } 643} 644 645} // namespace gpu 646