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

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

Issue 1409743002: Re-land: 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: update comments 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) 7 #if defined(OS_POSIX) && !defined(OS_NACL)
8 #include <unistd.h> 8 // For madvise() which is available on all POSIX compatible systems.
9 #include <sys/mman.h>
9 #endif 10 #endif
10 11
11 #include <algorithm> 12 #include <algorithm>
12 13
13 #include "base/atomicops.h" 14 #include "base/atomicops.h"
14 #include "base/bits.h" 15 #include "base/bits.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
16 #include "base/numerics/safe_math.h" 17 #include "base/numerics/safe_math.h"
17 #include "base/process/process_metrics.h" 18 #include "base/process/process_metrics.h"
18 19
19 #if defined(OS_ANDROID) 20 #if defined(OS_ANDROID)
20 #include "third_party/ashmem/ashmem.h" 21 #include "third_party/ashmem/ashmem.h"
21 #endif 22 #endif
22 23
24 // Linux and Android provide MADV_REMOVE which is preferred as it has a
25 // behavior that can be verified in tests. Other supported POSIX platforms,
26 // MacOSX to be specific, provide MADV_FREE instead. MADV_FREE has the
27 // same result but memory is purged lazily which makes it hard to test.
28 #if !defined(DISCARDABLE_SHARED_MEMORY_REMOVE)
29 #define MADV_REMOVE MADV_FREE
danakj 2015/10/21 18:34:25 Rather than defining MADV_REMOVE ourselves, can yo
30 #endif
31
23 namespace base { 32 namespace base {
24 namespace { 33 namespace {
25 34
26 // Use a machine-sized pointer as atomic type. It will use the Atomic32 or 35 // Use a machine-sized pointer as atomic type. It will use the Atomic32 or
27 // Atomic64 routines, depending on the architecture. 36 // Atomic64 routines, depending on the architecture.
28 typedef intptr_t AtomicType; 37 typedef intptr_t AtomicType;
29 typedef uintptr_t UAtomicType; 38 typedef uintptr_t UAtomicType;
30 39
31 // Template specialization for timestamp serialization/deserialization. This 40 // Template specialization for timestamp serialization/deserialization. This
32 // is used to serialize timestamps using Unix time on systems where AtomicType 41 // is used to serialize timestamps using Unix time on systems where AtomicType
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 } 303 }
295 304
296 void* DiscardableSharedMemory::memory() const { 305 void* DiscardableSharedMemory::memory() const {
297 return reinterpret_cast<uint8*>(shared_memory_.memory()) + 306 return reinterpret_cast<uint8*>(shared_memory_.memory()) +
298 AlignToPageSize(sizeof(SharedState)); 307 AlignToPageSize(sizeof(SharedState));
299 } 308 }
300 309
301 bool DiscardableSharedMemory::Purge(Time current_time) { 310 bool DiscardableSharedMemory::Purge(Time current_time) {
302 // Calls to this function must be synchronized properly. 311 // Calls to this function must be synchronized properly.
303 DFAKE_SCOPED_LOCK(thread_collision_warner_); 312 DFAKE_SCOPED_LOCK(thread_collision_warner_);
304 313 DCHECK(shared_memory_.memory());
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;
309 314
310 SharedState old_state(SharedState::UNLOCKED, last_known_usage_); 315 SharedState old_state(SharedState::UNLOCKED, last_known_usage_);
311 SharedState new_state(SharedState::UNLOCKED, Time()); 316 SharedState new_state(SharedState::UNLOCKED, Time());
312 SharedState result(subtle::Acquire_CompareAndSwap( 317 SharedState result(subtle::Acquire_CompareAndSwap(
313 &SharedStateFromSharedMemory(shared_memory_)->value.i, 318 &SharedStateFromSharedMemory(shared_memory_)->value.i,
314 old_state.value.i, 319 old_state.value.i,
315 new_state.value.i)); 320 new_state.value.i));
316 321
317 // Update |last_known_usage_| to |current_time| if the memory is locked. This 322 // Update |last_known_usage_| to |current_time| if the memory is locked. This
318 // allows the caller to determine if purging failed because last known usage 323 // allows the caller to determine if purging failed because last known usage
319 // was incorrect or memory was locked. In the second case, the caller should 324 // was incorrect or memory was locked. In the second case, the caller should
320 // most likely wait for some amount of time before attempting to purge the 325 // most likely wait for some amount of time before attempting to purge the
321 // the memory again. 326 // the memory again.
322 if (result.value.u != old_state.value.u) { 327 if (result.value.u != old_state.value.u) {
323 last_known_usage_ = result.GetLockState() == SharedState::LOCKED 328 last_known_usage_ = result.GetLockState() == SharedState::LOCKED
324 ? current_time 329 ? current_time
325 : result.GetTimestamp(); 330 : result.GetTimestamp();
326 return false; 331 return false;
327 } 332 }
328 333
334 #if defined(OS_POSIX) && !defined(OS_NACL)
335 // Advise the kernel to remove resources associated with purged pages.
336 // Subsequent accesses of memory pages will succeed, but will 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_REMOVE)) {
danakj 2015/10/21 18:34:25 Then this doesn't read like it's doing MADV_REMOVE
341 DPLOG(ERROR) << "madvise() failed";
342 }
343 #endif
344
329 last_known_usage_ = Time(); 345 last_known_usage_ = Time();
330 return true; 346 return true;
331 } 347 }
332 348
333 bool DiscardableSharedMemory::IsMemoryResident() const { 349 bool DiscardableSharedMemory::IsMemoryResident() const {
334 DCHECK(shared_memory_.memory()); 350 DCHECK(shared_memory_.memory());
335 351
336 SharedState result(subtle::NoBarrier_Load( 352 SharedState result(subtle::NoBarrier_Load(
337 &SharedStateFromSharedMemory(shared_memory_)->value.i)); 353 &SharedStateFromSharedMemory(shared_memory_)->value.i));
338 354
339 return result.GetLockState() == SharedState::LOCKED || 355 return result.GetLockState() == SharedState::LOCKED ||
340 !result.GetTimestamp().is_null(); 356 !result.GetTimestamp().is_null();
341 } 357 }
342 358
343 bool DiscardableSharedMemory::IsMemoryLocked() const { 359 bool DiscardableSharedMemory::IsMemoryLocked() const {
344 DCHECK(shared_memory_.memory()); 360 DCHECK(shared_memory_.memory());
345 361
346 SharedState result(subtle::NoBarrier_Load( 362 SharedState result(subtle::NoBarrier_Load(
347 &SharedStateFromSharedMemory(shared_memory_)->value.i)); 363 &SharedStateFromSharedMemory(shared_memory_)->value.i));
348 364
349 return result.GetLockState() == SharedState::LOCKED; 365 return result.GetLockState() == SharedState::LOCKED;
350 } 366 }
351 367
352 void DiscardableSharedMemory::Close() { 368 void DiscardableSharedMemory::Close() {
353 shared_memory_.Close(); 369 shared_memory_.Close();
354 } 370 }
355 371
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
376 Time DiscardableSharedMemory::Now() const { 372 Time DiscardableSharedMemory::Now() const {
377 return Time::Now(); 373 return Time::Now();
378 } 374 }
379 375
380 } // namespace base 376 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698