| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "base/memory/discardable_memory_provider.h" | 5 #include "base/memory/discardable_memory_provider.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/memory/discardable_memory.h" | 8 #include "base/memory/discardable_memory.h" |
| 9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 provider_->Register(this, size); | 24 provider_->Register(this, size); |
| 25 } | 25 } |
| 26 | 26 |
| 27 virtual ~TestDiscardableMemory() { | 27 virtual ~TestDiscardableMemory() { |
| 28 if (is_locked_) | 28 if (is_locked_) |
| 29 Unlock(); | 29 Unlock(); |
| 30 provider_->Unregister(this); | 30 provider_->Unregister(this); |
| 31 } | 31 } |
| 32 | 32 |
| 33 // Overridden from DiscardableMemory: | 33 // Overridden from DiscardableMemory: |
| 34 virtual LockDiscardableMemoryStatus Lock() OVERRIDE { | 34 virtual DiscardableMemoryLockStatus Lock() OVERRIDE { |
| 35 DCHECK(!is_locked_); | 35 DCHECK(!is_locked_); |
| 36 | 36 |
| 37 bool purged = false; | 37 bool purged = false; |
| 38 memory_ = provider_->Acquire(this, &purged); | 38 memory_ = provider_->Acquire(this, &purged); |
| 39 if (!memory_) | 39 if (!memory_) |
| 40 return DISCARDABLE_MEMORY_FAILED; | 40 return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; |
| 41 | 41 |
| 42 is_locked_ = true; | 42 is_locked_ = true; |
| 43 return purged ? DISCARDABLE_MEMORY_PURGED : DISCARDABLE_MEMORY_SUCCESS; | 43 return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED |
| 44 : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS; |
| 44 } | 45 } |
| 45 virtual void Unlock() OVERRIDE { | 46 virtual void Unlock() OVERRIDE { |
| 46 DCHECK(is_locked_); | 47 DCHECK(is_locked_); |
| 47 provider_->Release(this, memory_.Pass()); | 48 provider_->Release(this, memory_.Pass()); |
| 48 is_locked_ = false; | 49 is_locked_ = false; |
| 49 } | 50 } |
| 50 virtual void* Memory() const OVERRIDE { | 51 virtual void* Memory() const OVERRIDE { |
| 51 DCHECK(memory_); | 52 DCHECK(memory_); |
| 52 return memory_.get(); | 53 return memory_.get(); |
| 53 } | 54 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 provider_->SetDiscardableMemoryLimit(bytes); | 87 provider_->SetDiscardableMemoryLimit(bytes); |
| 87 } | 88 } |
| 88 | 89 |
| 89 void SetBytesToReclaimUnderModeratePressure(size_t bytes) { | 90 void SetBytesToReclaimUnderModeratePressure(size_t bytes) { |
| 90 provider_->SetBytesToReclaimUnderModeratePressure(bytes); | 91 provider_->SetBytesToReclaimUnderModeratePressure(bytes); |
| 91 } | 92 } |
| 92 | 93 |
| 93 scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size) { | 94 scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size) { |
| 94 scoped_ptr<TestDiscardableMemory> memory( | 95 scoped_ptr<TestDiscardableMemory> memory( |
| 95 new TestDiscardableMemory(provider_.get(), size)); | 96 new TestDiscardableMemory(provider_.get(), size)); |
| 96 if (memory->Lock() != DISCARDABLE_MEMORY_PURGED) | 97 if (memory->Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_PURGED) |
| 97 return scoped_ptr<DiscardableMemory>(); | 98 return scoped_ptr<DiscardableMemory>(); |
| 98 return memory.PassAs<DiscardableMemory>(); | 99 return memory.PassAs<DiscardableMemory>(); |
| 99 } | 100 } |
| 100 | 101 |
| 101 private: | 102 private: |
| 102 MessageLoop message_loop_; | 103 MessageLoop message_loop_; |
| 103 scoped_ptr<internal::DiscardableMemoryProvider> provider_; | 104 scoped_ptr<internal::DiscardableMemoryProvider> provider_; |
| 104 }; | 105 }; |
| 105 | 106 |
| 106 class DiscardableMemoryProviderTest | 107 class DiscardableMemoryProviderTest |
| (...skipping 25 matching lines...) Expand all Loading... |
| 132 const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size)); | 133 const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size)); |
| 133 EXPECT_TRUE(IsRegistered(discardable.get())); | 134 EXPECT_TRUE(IsRegistered(discardable.get())); |
| 134 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get())); | 135 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get())); |
| 135 EXPECT_EQ(1024u, BytesAllocated()); | 136 EXPECT_EQ(1024u, BytesAllocated()); |
| 136 EXPECT_FALSE(CanBePurged(discardable.get())); | 137 EXPECT_FALSE(CanBePurged(discardable.get())); |
| 137 | 138 |
| 138 // Now unlock so we can lock later. | 139 // Now unlock so we can lock later. |
| 139 discardable->Unlock(); | 140 discardable->Unlock(); |
| 140 EXPECT_TRUE(CanBePurged(discardable.get())); | 141 EXPECT_TRUE(CanBePurged(discardable.get())); |
| 141 | 142 |
| 142 EXPECT_EQ(DISCARDABLE_MEMORY_SUCCESS, discardable->Lock()); | 143 EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable->Lock()); |
| 143 EXPECT_FALSE(CanBePurged(discardable.get())); | 144 EXPECT_FALSE(CanBePurged(discardable.get())); |
| 144 } | 145 } |
| 145 | 146 |
| 146 TEST_F(DiscardableMemoryProviderTest, LockAfterPurge) { | 147 TEST_F(DiscardableMemoryProviderTest, LockAfterPurge) { |
| 147 size_t size = 1024; | 148 size_t size = 1024; |
| 148 const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size)); | 149 const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size)); |
| 149 EXPECT_TRUE(IsRegistered(discardable.get())); | 150 EXPECT_TRUE(IsRegistered(discardable.get())); |
| 150 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get())); | 151 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get())); |
| 151 EXPECT_EQ(1024u, BytesAllocated()); | 152 EXPECT_EQ(1024u, BytesAllocated()); |
| 152 EXPECT_FALSE(CanBePurged(discardable.get())); | 153 EXPECT_FALSE(CanBePurged(discardable.get())); |
| 153 | 154 |
| 154 // Now unlock so we can lock later. | 155 // Now unlock so we can lock later. |
| 155 discardable->Unlock(); | 156 discardable->Unlock(); |
| 156 EXPECT_TRUE(CanBePurged(discardable.get())); | 157 EXPECT_TRUE(CanBePurged(discardable.get())); |
| 157 | 158 |
| 158 // Force the system to purge. | 159 // Force the system to purge. |
| 159 MemoryPressureListener::NotifyMemoryPressure( | 160 MemoryPressureListener::NotifyMemoryPressure( |
| 160 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL); | 161 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL); |
| 161 | 162 |
| 162 // Required because ObserverListThreadSafe notifies via PostTask. | 163 // Required because ObserverListThreadSafe notifies via PostTask. |
| 163 RunLoop().RunUntilIdle(); | 164 RunLoop().RunUntilIdle(); |
| 164 | 165 |
| 165 EXPECT_EQ(DISCARDABLE_MEMORY_PURGED, discardable->Lock()); | 166 EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable->Lock()); |
| 166 EXPECT_FALSE(CanBePurged(discardable.get())); | 167 EXPECT_FALSE(CanBePurged(discardable.get())); |
| 167 } | 168 } |
| 168 | 169 |
| 169 TEST_F(DiscardableMemoryProviderTest, LockAfterPurgeAndCannotReallocate) { | 170 TEST_F(DiscardableMemoryProviderTest, LockAfterPurgeAndCannotReallocate) { |
| 170 size_t size = 1024; | 171 size_t size = 1024; |
| 171 const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size)); | 172 const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size)); |
| 172 EXPECT_TRUE(IsRegistered(discardable.get())); | 173 EXPECT_TRUE(IsRegistered(discardable.get())); |
| 173 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get())); | 174 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get())); |
| 174 EXPECT_EQ(1024u, BytesAllocated()); | 175 EXPECT_EQ(1024u, BytesAllocated()); |
| 175 EXPECT_FALSE(CanBePurged(discardable.get())); | 176 EXPECT_FALSE(CanBePurged(discardable.get())); |
| 176 | 177 |
| 177 // Now unlock so we can lock later. | 178 // Now unlock so we can lock later. |
| 178 discardable->Unlock(); | 179 discardable->Unlock(); |
| 179 EXPECT_TRUE(CanBePurged(discardable.get())); | 180 EXPECT_TRUE(CanBePurged(discardable.get())); |
| 180 | 181 |
| 181 // Set max allowed allocation to 1 byte. This will make cause the memory | 182 // Set max allowed allocation to 1 byte. This will make cause the memory |
| 182 // to be purged. | 183 // to be purged. |
| 183 SetDiscardableMemoryLimit(1); | 184 SetDiscardableMemoryLimit(1); |
| 184 | 185 |
| 185 EXPECT_EQ(DISCARDABLE_MEMORY_PURGED, discardable->Lock()); | 186 EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable->Lock()); |
| 186 EXPECT_FALSE(CanBePurged(discardable.get())); | 187 EXPECT_FALSE(CanBePurged(discardable.get())); |
| 187 } | 188 } |
| 188 | 189 |
| 189 TEST_F(DiscardableMemoryProviderTest, Overflow) { | 190 TEST_F(DiscardableMemoryProviderTest, Overflow) { |
| 190 { | 191 { |
| 191 size_t size = 1024; | 192 size_t size = 1024; |
| 192 const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size)); | 193 const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size)); |
| 193 EXPECT_TRUE(IsRegistered(discardable.get())); | 194 EXPECT_TRUE(IsRegistered(discardable.get())); |
| 194 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get())); | 195 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get())); |
| 195 EXPECT_EQ(1024u, BytesAllocated()); | 196 EXPECT_EQ(1024u, BytesAllocated()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 // Use discardable memory in order specified by ordering parameter. | 228 // Use discardable memory in order specified by ordering parameter. |
| 228 void CreateAndUseDiscardableMemory() { | 229 void CreateAndUseDiscardableMemory() { |
| 229 for (int i = 0; i < 3; ++i) { | 230 for (int i = 0; i < 3; ++i) { |
| 230 discardables_[i] = CreateLockedMemory(1024); | 231 discardables_[i] = CreateLockedMemory(1024); |
| 231 EXPECT_TRUE(discardables_[i]); | 232 EXPECT_TRUE(discardables_[i]); |
| 232 EXPECT_NE(static_cast<void*>(NULL), Memory(discardables_[i].get())); | 233 EXPECT_NE(static_cast<void*>(NULL), Memory(discardables_[i].get())); |
| 233 discardables_[i]->Unlock(); | 234 discardables_[i]->Unlock(); |
| 234 } | 235 } |
| 235 for (int i = 0; i < 3; ++i) { | 236 for (int i = 0; i < 3; ++i) { |
| 236 int index = GetParam().ordering()[i]; | 237 int index = GetParam().ordering()[i]; |
| 237 EXPECT_NE(DISCARDABLE_MEMORY_FAILED, discardables_[index]->Lock()); | 238 EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, |
| 239 discardables_[index]->Lock()); |
| 238 // Leave i == 0 locked. | 240 // Leave i == 0 locked. |
| 239 if (i > 0) | 241 if (i > 0) |
| 240 discardables_[index]->Unlock(); | 242 discardables_[index]->Unlock(); |
| 241 } | 243 } |
| 242 } | 244 } |
| 243 | 245 |
| 244 DiscardableMemory* discardable(unsigned position) { | 246 DiscardableMemory* discardable(unsigned position) { |
| 245 return discardables_[GetParam().ordering()[position]].get(); | 247 return discardables_[GetParam().ordering()[position]].get(); |
| 246 } | 248 } |
| 247 | 249 |
| 248 private: | 250 private: |
| 249 scoped_ptr<DiscardableMemory> discardables_[3]; | 251 scoped_ptr<DiscardableMemory> discardables_[3]; |
| 250 }; | 252 }; |
| 251 | 253 |
| 252 // Verify that memory was discarded in the correct order after applying | 254 // Verify that memory was discarded in the correct order after applying |
| 253 // memory pressure. | 255 // memory pressure. |
| 254 TEST_P(DiscardableMemoryProviderPermutationTest, LRUDiscardedModeratePressure) { | 256 TEST_P(DiscardableMemoryProviderPermutationTest, LRUDiscardedModeratePressure) { |
| 255 CreateAndUseDiscardableMemory(); | 257 CreateAndUseDiscardableMemory(); |
| 256 | 258 |
| 257 SetBytesToReclaimUnderModeratePressure(1024); | 259 SetBytesToReclaimUnderModeratePressure(1024); |
| 258 MemoryPressureListener::NotifyMemoryPressure( | 260 MemoryPressureListener::NotifyMemoryPressure( |
| 259 MemoryPressureListener::MEMORY_PRESSURE_MODERATE); | 261 MemoryPressureListener::MEMORY_PRESSURE_MODERATE); |
| 260 RunLoop().RunUntilIdle(); | 262 RunLoop().RunUntilIdle(); |
| 261 | 263 |
| 262 EXPECT_NE(DISCARDABLE_MEMORY_FAILED, discardable(2)->Lock()); | 264 EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, discardable(2)->Lock()); |
| 263 EXPECT_NE(DISCARDABLE_MEMORY_SUCCESS, discardable(1)->Lock()); | 265 EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable(1)->Lock()); |
| 264 // 0 should still be locked. | 266 // 0 should still be locked. |
| 265 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0))); | 267 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0))); |
| 266 } | 268 } |
| 267 | 269 |
| 268 // Verify that memory was discarded in the correct order after changing | 270 // Verify that memory was discarded in the correct order after changing |
| 269 // memory limit. | 271 // memory limit. |
| 270 TEST_P(DiscardableMemoryProviderPermutationTest, LRUDiscardedExceedLimit) { | 272 TEST_P(DiscardableMemoryProviderPermutationTest, LRUDiscardedExceedLimit) { |
| 271 CreateAndUseDiscardableMemory(); | 273 CreateAndUseDiscardableMemory(); |
| 272 | 274 |
| 273 SetBytesToReclaimUnderModeratePressure(1024); | 275 SetBytesToReclaimUnderModeratePressure(1024); |
| 274 SetDiscardableMemoryLimit(2048); | 276 SetDiscardableMemoryLimit(2048); |
| 275 | 277 |
| 276 EXPECT_NE(DISCARDABLE_MEMORY_FAILED, discardable(2)->Lock()); | 278 EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, discardable(2)->Lock()); |
| 277 EXPECT_NE(DISCARDABLE_MEMORY_SUCCESS, discardable(1)->Lock()); | 279 EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable(1)->Lock()); |
| 278 // 0 should still be locked. | 280 // 0 should still be locked. |
| 279 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0))); | 281 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0))); |
| 280 } | 282 } |
| 281 | 283 |
| 282 // Verify that no more memory than necessary was discarded after changing | 284 // Verify that no more memory than necessary was discarded after changing |
| 283 // memory limit. | 285 // memory limit. |
| 284 TEST_P(DiscardableMemoryProviderPermutationTest, LRUDiscardedAmount) { | 286 TEST_P(DiscardableMemoryProviderPermutationTest, LRUDiscardedAmount) { |
| 285 SetBytesToReclaimUnderModeratePressure(2048); | 287 SetBytesToReclaimUnderModeratePressure(2048); |
| 286 SetDiscardableMemoryLimit(4096); | 288 SetDiscardableMemoryLimit(4096); |
| 287 | 289 |
| 288 CreateAndUseDiscardableMemory(); | 290 CreateAndUseDiscardableMemory(); |
| 289 | 291 |
| 290 SetDiscardableMemoryLimit(2048); | 292 SetDiscardableMemoryLimit(2048); |
| 291 | 293 |
| 292 EXPECT_EQ(DISCARDABLE_MEMORY_SUCCESS, discardable(2)->Lock()); | 294 EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable(2)->Lock()); |
| 293 EXPECT_EQ(DISCARDABLE_MEMORY_PURGED, discardable(1)->Lock()); | 295 EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable(1)->Lock()); |
| 294 // 0 should still be locked. | 296 // 0 should still be locked. |
| 295 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0))); | 297 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0))); |
| 296 } | 298 } |
| 297 | 299 |
| 298 TEST_P(DiscardableMemoryProviderPermutationTest, | 300 TEST_P(DiscardableMemoryProviderPermutationTest, |
| 299 CriticalPressureFreesAllUnlocked) { | 301 CriticalPressureFreesAllUnlocked) { |
| 300 CreateAndUseDiscardableMemory(); | 302 CreateAndUseDiscardableMemory(); |
| 301 | 303 |
| 302 MemoryPressureListener::NotifyMemoryPressure( | 304 MemoryPressureListener::NotifyMemoryPressure( |
| 303 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL); | 305 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL); |
| 304 RunLoop().RunUntilIdle(); | 306 RunLoop().RunUntilIdle(); |
| 305 | 307 |
| 306 for (int i = 0; i < 3; ++i) { | 308 for (int i = 0; i < 3; ++i) { |
| 307 if (i == 0) | 309 if (i == 0) |
| 308 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(i))); | 310 EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(i))); |
| 309 else | 311 else |
| 310 EXPECT_EQ(DISCARDABLE_MEMORY_PURGED, discardable(i)->Lock()); | 312 EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable(i)->Lock()); |
| 311 } | 313 } |
| 312 } | 314 } |
| 313 | 315 |
| 314 INSTANTIATE_TEST_CASE_P(DiscardableMemoryProviderPermutationTests, | 316 INSTANTIATE_TEST_CASE_P(DiscardableMemoryProviderPermutationTests, |
| 315 DiscardableMemoryProviderPermutationTest, | 317 DiscardableMemoryProviderPermutationTest, |
| 316 ::testing::Values(PermutationTestData(0, 1, 2), | 318 ::testing::Values(PermutationTestData(0, 1, 2), |
| 317 PermutationTestData(0, 2, 1), | 319 PermutationTestData(0, 2, 1), |
| 318 PermutationTestData(1, 0, 2), | 320 PermutationTestData(1, 0, 2), |
| 319 PermutationTestData(1, 2, 0), | 321 PermutationTestData(1, 2, 0), |
| 320 PermutationTestData(2, 0, 1), | 322 PermutationTestData(2, 0, 1), |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 Bind(&ThreadedDiscardableMemoryProviderTest::UseMemoryHelper, | 399 Bind(&ThreadedDiscardableMemoryProviderTest::UseMemoryHelper, |
| 398 Unretained(this))); | 400 Unretained(this))); |
| 399 memory_usage_thread_.message_loop()->PostTask( | 401 memory_usage_thread_.message_loop()->PostTask( |
| 400 FROM_HERE, | 402 FROM_HERE, |
| 401 Bind(&ThreadedDiscardableMemoryProviderTest::SignalHelper, | 403 Bind(&ThreadedDiscardableMemoryProviderTest::SignalHelper, |
| 402 Unretained(this))); | 404 Unretained(this))); |
| 403 thread_sync_.Wait(); | 405 thread_sync_.Wait(); |
| 404 } | 406 } |
| 405 | 407 |
| 406 } // namespace base | 408 } // namespace base |
| OLD | NEW |