diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/ports/SkPurgeableMemoryBlock_mac.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/ports/SkPurgeableMemoryBlock_mac.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,104 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkPurgeableMemoryBlock.h" + +#include + +bool SkPurgeableMemoryBlock::IsSupported() { + return true; +} + +#ifdef SK_DEBUG +bool SkPurgeableMemoryBlock::PlatformSupportsPurgingAllUnpinnedBlocks() { + return true; +} + +bool SkPurgeableMemoryBlock::PurgeAllUnpinnedBlocks() { + // Unused. + int state = 0; + kern_return_t ret = vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state); + return ret == KERN_SUCCESS; +} + +bool SkPurgeableMemoryBlock::purge() { + return false; +} +#endif + +static size_t round_to_page_size(size_t size) { + const size_t mask = 4096 - 1; + return (size + mask) & ~mask; +} + +SkPurgeableMemoryBlock::SkPurgeableMemoryBlock(size_t size) + : fAddr(NULL) + , fSize(round_to_page_size(size)) + , fPinned(false) { +} + +SkPurgeableMemoryBlock::~SkPurgeableMemoryBlock() { + SkDEBUGCODE(kern_return_t ret =) vm_deallocate(mach_task_self(), + reinterpret_cast(fAddr), + static_cast(fSize)); +#ifdef SK_DEBUG + if (ret != KERN_SUCCESS) { + SkDebugf("SkPurgeableMemoryBlock destructor failed to deallocate.\n"); + } +#endif +} + +void* SkPurgeableMemoryBlock::pin(SkPurgeableMemoryBlock::PinResult* pinResult) { + SkASSERT(!fPinned); + SkASSERT(pinResult != NULL); + if (NULL == fAddr) { + vm_address_t addr = 0; + kern_return_t ret = vm_allocate(mach_task_self(), &addr, static_cast(fSize), + VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE); + if (KERN_SUCCESS == ret) { + fAddr = reinterpret_cast(addr); + *pinResult = kUninitialized_PinResult; + fPinned = true; + } else { + fAddr = NULL; + } + } else { + int state = VM_PURGABLE_NONVOLATILE; + kern_return_t ret = vm_purgable_control(mach_task_self(), + reinterpret_cast(fAddr), + VM_PURGABLE_SET_STATE, &state); + if (ret != KERN_SUCCESS) { + fAddr = NULL; + fPinned = false; + return NULL; + } + + fPinned = true; + + if (state & VM_PURGABLE_EMPTY) { + *pinResult = kUninitialized_PinResult; + } else { + *pinResult = kRetained_PinResult; + } + } + return fAddr; +} + +void SkPurgeableMemoryBlock::unpin() { + SkASSERT(fPinned); + int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT; + SkDEBUGCODE(kern_return_t ret =) vm_purgable_control(mach_task_self(), + reinterpret_cast(fAddr), + VM_PURGABLE_SET_STATE, &state); + fPinned = false; + +#ifdef SK_DEBUG + if (ret != KERN_SUCCESS) { + SkDebugf("SkPurgeableMemoryBlock::unpin() failed.\n"); + } +#endif +}