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

Side by Side Diff: base/memory/discardable_shared_memory.cc

Issue 1413163006: Revert of base: Use MADV_REMOVE instead of ftruncate to purge discardable memory segments. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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_shared_memory.h" 5 #include "base/memory/discardable_shared_memory.h"
6 6
7 #if defined(OS_POSIX) && !defined(OS_NACL) 7 #if defined(OS_POSIX)
8 // For madvise() which is available on all POSIX compatible systems. 8 #include <unistd.h>
9 #include <sys/mman.h>
10 #endif 9 #endif
11 10
12 #include <algorithm> 11 #include <algorithm>
13 12
14 #include "base/atomicops.h" 13 #include "base/atomicops.h"
15 #include "base/bits.h" 14 #include "base/bits.h"
16 #include "base/logging.h" 15 #include "base/logging.h"
17 #include "base/numerics/safe_math.h" 16 #include "base/numerics/safe_math.h"
18 #include "base/process/process_metrics.h" 17 #include "base/process/process_metrics.h"
19 18
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 } 294 }
296 295
297 void* DiscardableSharedMemory::memory() const { 296 void* DiscardableSharedMemory::memory() const {
298 return reinterpret_cast<uint8*>(shared_memory_.memory()) + 297 return reinterpret_cast<uint8*>(shared_memory_.memory()) +
299 AlignToPageSize(sizeof(SharedState)); 298 AlignToPageSize(sizeof(SharedState));
300 } 299 }
301 300
302 bool DiscardableSharedMemory::Purge(Time current_time) { 301 bool DiscardableSharedMemory::Purge(Time current_time) {
303 // Calls to this function must be synchronized properly. 302 // Calls to this function must be synchronized properly.
304 DFAKE_SCOPED_LOCK(thread_collision_warner_); 303 DFAKE_SCOPED_LOCK(thread_collision_warner_);
305 DCHECK(shared_memory_.memory()); 304
305 // Early out if not mapped. This can happen if the segment was previously
306 // unmapped using a call to Close().
307 if (!shared_memory_.memory())
308 return true;
306 309
307 SharedState old_state(SharedState::UNLOCKED, last_known_usage_); 310 SharedState old_state(SharedState::UNLOCKED, last_known_usage_);
308 SharedState new_state(SharedState::UNLOCKED, Time()); 311 SharedState new_state(SharedState::UNLOCKED, Time());
309 SharedState result(subtle::Acquire_CompareAndSwap( 312 SharedState result(subtle::Acquire_CompareAndSwap(
310 &SharedStateFromSharedMemory(shared_memory_)->value.i, 313 &SharedStateFromSharedMemory(shared_memory_)->value.i,
311 old_state.value.i, 314 old_state.value.i,
312 new_state.value.i)); 315 new_state.value.i));
313 316
314 // Update |last_known_usage_| to |current_time| if the memory is locked. This 317 // Update |last_known_usage_| to |current_time| if the memory is locked. This
315 // allows the caller to determine if purging failed because last known usage 318 // allows the caller to determine if purging failed because last known usage
316 // was incorrect or memory was locked. In the second case, the caller should 319 // was incorrect or memory was locked. In the second case, the caller should
317 // most likely wait for some amount of time before attempting to purge the 320 // most likely wait for some amount of time before attempting to purge the
318 // the memory again. 321 // the memory again.
319 if (result.value.u != old_state.value.u) { 322 if (result.value.u != old_state.value.u) {
320 last_known_usage_ = result.GetLockState() == SharedState::LOCKED 323 last_known_usage_ = result.GetLockState() == SharedState::LOCKED
321 ? current_time 324 ? current_time
322 : result.GetTimestamp(); 325 : result.GetTimestamp();
323 return false; 326 return false;
324 } 327 }
325 328
326 #if defined(OS_POSIX) && !defined(OS_NACL)
327 // Linux and Android provide MADV_REMOVE which is preferred as it has a
328 // behavior that can be verified in tests. Other POSIX flavors (MacOSX, BSDs),
329 // provide MADV_FREE which has the same result but memory is purged lazily.
330 #if defined(OS_LINUX) || defined(OS_ANDROID)
331 #define MADV_PURGE_ARGUMENT MADV_REMOVE
332 #else
333 #define MADV_PURGE_ARGUMENT MADV_FREE
334 #endif
335 // Advise the kernel to remove resources associated with purged pages.
336 // Subsequent accesses of memory pages will succeed, but might result in
337 // zero-fill-on-demand pages.
338 if (madvise(reinterpret_cast<char*>(shared_memory_.memory()) +
339 AlignToPageSize(sizeof(SharedState)),
340 AlignToPageSize(mapped_size_), MADV_PURGE_ARGUMENT)) {
341 DPLOG(ERROR) << "madvise() failed";
342 }
343 #endif
344
345 last_known_usage_ = Time(); 329 last_known_usage_ = Time();
346 return true; 330 return true;
347 } 331 }
348 332
349 bool DiscardableSharedMemory::IsMemoryResident() const { 333 bool DiscardableSharedMemory::IsMemoryResident() const {
350 DCHECK(shared_memory_.memory()); 334 DCHECK(shared_memory_.memory());
351 335
352 SharedState result(subtle::NoBarrier_Load( 336 SharedState result(subtle::NoBarrier_Load(
353 &SharedStateFromSharedMemory(shared_memory_)->value.i)); 337 &SharedStateFromSharedMemory(shared_memory_)->value.i));
354 338
355 return result.GetLockState() == SharedState::LOCKED || 339 return result.GetLockState() == SharedState::LOCKED ||
356 !result.GetTimestamp().is_null(); 340 !result.GetTimestamp().is_null();
357 } 341 }
358 342
359 bool DiscardableSharedMemory::IsMemoryLocked() const { 343 bool DiscardableSharedMemory::IsMemoryLocked() const {
360 DCHECK(shared_memory_.memory()); 344 DCHECK(shared_memory_.memory());
361 345
362 SharedState result(subtle::NoBarrier_Load( 346 SharedState result(subtle::NoBarrier_Load(
363 &SharedStateFromSharedMemory(shared_memory_)->value.i)); 347 &SharedStateFromSharedMemory(shared_memory_)->value.i));
364 348
365 return result.GetLockState() == SharedState::LOCKED; 349 return result.GetLockState() == SharedState::LOCKED;
366 } 350 }
367 351
368 void DiscardableSharedMemory::Close() { 352 void DiscardableSharedMemory::Close() {
369 shared_memory_.Close(); 353 shared_memory_.Close();
370 } 354 }
371 355
356 #if defined(DISCARDABLE_SHARED_MEMORY_SHRINKING)
357 void DiscardableSharedMemory::Shrink() {
358 #if defined(OS_POSIX)
359 SharedMemoryHandle handle = shared_memory_.handle();
360 if (!SharedMemory::IsHandleValid(handle))
361 return;
362
363 // Truncate shared memory to size of SharedState.
364 if (HANDLE_EINTR(ftruncate(SharedMemory::GetFdFromSharedMemoryHandle(handle),
365 AlignToPageSize(sizeof(SharedState)))) != 0) {
366 DPLOG(ERROR) << "ftruncate() failed";
367 return;
368 }
369 mapped_size_ = 0;
370 #else
371 NOTIMPLEMENTED();
372 #endif
373 }
374 #endif
375
372 Time DiscardableSharedMemory::Now() const { 376 Time DiscardableSharedMemory::Now() const {
373 return Time::Now(); 377 return Time::Now();
374 } 378 }
375 379
376 } // namespace base 380 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/discardable_shared_memory.h ('k') | base/memory/discardable_shared_memory_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698